/core/controllers/upgrade.php

  1. <?php 
  2.  
  3. /** 
  4. * Upgrade 
  5. * 
  6. * @description: All the functionality for upgrading ACF 
  7. * @since 3.2.6 
  8. * @created: 23/06/12 
  9. */ 
  10.  
  11. class acf_upgrade 
  12.  
  13. /** 
  14. * __construct 
  15. * 
  16. * @description: 
  17. * @since 3.1.8 
  18. * @created: 23/06/12 
  19. */ 
  20.  
  21. function __construct() 
  22. // actions 
  23. add_action('admin_menu', array($this, 'admin_menu'), 11); 
  24.  
  25.  
  26. // ajax 
  27. add_action('wp_ajax_acf_upgrade', array($this, 'upgrade_ajax')); 
  28.  
  29.  
  30. /** 
  31. * admin_menu 
  32. * 
  33. * @description: 
  34. * @since 3.1.8 
  35. * @created: 23/06/12 
  36. */ 
  37.  
  38. function admin_menu() 
  39. // dont run on plugin activate! 
  40. if( isset($_GET['action']) && $_GET['action'] == 'activate-plugin' ) 
  41. return; 
  42.  
  43.  
  44. // vars 
  45. $plugin_version = apply_filters('acf/get_info', 'version'); 
  46. $acf_version = get_option('acf_version'); 
  47.  
  48.  
  49. // bail early if a new install 
  50. if( empty($acf_version) ) { 
  51.  
  52. update_option('acf_version', $plugin_version ); 
  53. return; 
  54.  
  55.  
  56.  
  57. // bail early if $acf_version is >= $plugin_version 
  58. if( version_compare( $acf_version, $plugin_version, '>=') ) { 
  59.  
  60. return; 
  61.  
  62.  
  63.  
  64. // update version 
  65. update_option('acf_version', $plugin_version ); 
  66.  
  67.  
  68. // update admin page 
  69. add_submenu_page('edit.php?post_type=acf', __('Upgrade', 'acf'), __('Upgrade', 'acf'), 'manage_options', 'acf-upgrade', array($this, 'html') ); 
  70.  
  71.  
  72.  
  73. /** 
  74. * html 
  75. * 
  76. * @description: 
  77. * @since 3.1.8 
  78. * @created: 23/06/12 
  79. */ 
  80.  
  81. function html() 
  82. $version = get_option('acf_version', '1.0.5'); 
  83. $next = false; 
  84.  
  85. // list of starting points 
  86. if( $version < '3.0.0' ) 
  87. $next = '3.0.0'; 
  88. elseif( $version < '3.1.8' ) 
  89. $next = '3.1.8'; 
  90. elseif( $version < '3.2.5' ) 
  91. $next = '3.2.5'; 
  92. elseif( $version < '3.3.3' ) 
  93. $next = '3.3.3'; 
  94. elseif( $version < '3.4.1' ) 
  95. $next = '3.4.1'; 
  96.  
  97. ?> 
  98. <script type="text/javascript"> 
  99. (function($) { 
  100.  
  101. function add_message(messaage) 
  102. $('#wpbody-content').append('<p>' + messaage + '</p>'); 
  103.  
  104. function run_upgrade(version) 
  105. $.ajax({ 
  106. url: ajaxurl,  
  107. data: { 
  108. action : 'acf_upgrade',  
  109. version : version 
  110. },  
  111. type: 'post',  
  112. dataType: 'json',  
  113. success: function(json) { 
  114.  
  115. if(json) 
  116. if(json.status) 
  117. add_message(json.message); 
  118.  
  119. // next update? 
  120. if(json.next) 
  121. run_upgrade(json.next); 
  122. else 
  123. // all done 
  124. add_message('Upgrade Complete! <a href="<?php echo admin_url(); ?>edit.php?post_type=acf">Continue to ACF »</a>'); 
  125. else 
  126. // error! 
  127. add_message('Error: ' + json.message); 
  128. else 
  129. // major error! 
  130. add_message('Sorry. Something went wrong during the upgrade process. Please report this on the support forum'); 
  131. }); 
  132.  
  133. <?php if($next) { echo 'run_upgrade("' . $next . '");'; } ?> 
  134.  
  135. })(jQuery); 
  136. </script> 
  137. <style type="text/css"> 
  138. #message { 
  139. display: none; 
  140. </style> 
  141. <?php 
  142.  
  143. if(!$next) 
  144. echo '<p>No Upgrade Required</p>'; 
  145.  
  146.  
  147. /** 
  148. * upgrade_ajax 
  149. * 
  150. * @description: 
  151. * @since 3.1.8 
  152. * @created: 23/06/12 
  153. */ 
  154.  
  155. function upgrade_ajax() 
  156. // global 
  157. global $wpdb; 
  158.  
  159.  
  160. // tables 
  161. $acf_fields = $wpdb->prefix.'acf_fields'; 
  162. $acf_values = $wpdb->prefix.'acf_values'; 
  163. $acf_rules = $wpdb->prefix.'acf_rules'; 
  164. $wp_postmeta = $wpdb->prefix.'postmeta'; 
  165. $wp_options = $wpdb->prefix.'options'; 
  166.  
  167.  
  168. // vars 
  169. $return = array( 
  170. 'status' => false,  
  171. 'message' => "",  
  172. 'next' => false,  
  173. ); 
  174.  
  175.  
  176. // versions 
  177. switch($_POST['version']) 
  178.  
  179. /**--------------------- 
  180. * 
  181. * 3.0.0 
  182. * 
  183. *--------------------*/ 
  184.  
  185. case '3.0.0': 
  186.  
  187. // upgrade options first as "field_group_layout" will cause get_fields to fail! 
  188.  
  189. // get acf's 
  190. $acfs = get_posts(array( 
  191. 'numberposts' => -1,  
  192. 'post_type' => 'acf',  
  193. 'orderby' => 'menu_order title',  
  194. 'order' => 'asc',  
  195. 'suppress_filters' => false,  
  196. )); 
  197.  
  198. if($acfs) 
  199. foreach($acfs as $acf) 
  200. // position 
  201. update_post_meta($acf->ID, 'position', 'normal'); 
  202.  
  203. //layout 
  204. $layout = get_post_meta($acf->ID, 'field_group_layout', true) ? get_post_meta($acf->ID, 'field_group_layout', true) : 'in_box'; 
  205. if($layout == 'in_box') 
  206. $layout = 'default'; 
  207. else 
  208. $layout = 'no_box'; 
  209. update_post_meta($acf->ID, 'layout', $layout); 
  210. delete_post_meta($acf->ID, 'field_group_layout'); 
  211.  
  212. // show_on_page 
  213. $show_on_page = get_post_meta($acf->ID, 'show_on_page', true) ? get_post_meta($acf->ID, 'show_on_page', true) : array(); 
  214. if($show_on_page) 
  215. $show_on_page = unserialize($show_on_page); 
  216. update_post_meta($acf->ID, 'show_on_page', $show_on_page); 
  217.  
  218.  
  219. $return = array( 
  220. 'status' => true,  
  221. 'message' => "Migrating Options...",  
  222. 'next' => '3.0.0 (step 2)',  
  223. ); 
  224.  
  225. break; 
  226.  
  227. /**--------------------- 
  228. * 
  229. * 3.0.0 
  230. * 
  231. *--------------------*/ 
  232.  
  233. case '3.0.0 (step 2)': 
  234.  
  235. // get acf's 
  236. $acfs = get_posts(array( 
  237. 'numberposts' => -1,  
  238. 'post_type' => 'acf',  
  239. 'orderby' => 'menu_order title',  
  240. 'order' => 'asc',  
  241. 'suppress_filters' => false,  
  242. )); 
  243.  
  244. if($acfs) 
  245. foreach($acfs as $acf) 
  246. // allorany doesn't need to change! 
  247.  
  248. $rules = $wpdb->get_results("SELECT * FROM $acf_rules WHERE acf_id = '$acf->ID' ORDER BY order_no ASC", ARRAY_A); 
  249.  
  250. if($rules) 
  251. foreach($rules as $rule) 
  252. // options rule has changed 
  253. if($rule['param'] == 'options_page') 
  254. $rule['value'] = 'Options'; 
  255.  
  256. add_post_meta($acf->ID, 'rule', $rule); 
  257.  
  258.  
  259. $return = array( 
  260. 'status' => true,  
  261. 'message' => "Migrating Location Rules...",  
  262. 'next' => '3.0.0 (step 3)',  
  263. ); 
  264.  
  265. break; 
  266.  
  267. /**--------------------- 
  268. * 
  269. * 3.0.0 
  270. * 
  271. *--------------------*/ 
  272.  
  273. case '3.0.0 (step 3)': 
  274.  
  275. $message = "Migrating Fields?"; 
  276.  
  277. $parent_id = 0; 
  278. $fields = $wpdb->get_results("SELECT * FROM $acf_fields WHERE parent_id = $parent_id ORDER BY order_no, name", ARRAY_A); 
  279.  
  280. if($fields) 
  281. // loop through fields 
  282. foreach($fields as $field) 
  283.  
  284. // unserialize options 
  285. if(@unserialize($field['options'])) 
  286. $field['options'] = unserialize($field['options']); 
  287. else 
  288. $field['options'] = array(); 
  289.  
  290.  
  291. // sub fields 
  292. if($field['type'] == 'repeater') 
  293. $field['options']['sub_fields'] = array(); 
  294.  
  295. $parent_id = $field['id']; 
  296. $sub_fields = $wpdb->get_results("SELECT * FROM $acf_fields WHERE parent_id = $parent_id ORDER BY order_no, name", ARRAY_A); 
  297.  
  298.  
  299. // if fields are empty, this must be a new or broken acf. 
  300. if(empty($sub_fields)) 
  301. $field['options']['sub_fields'] = array(); 
  302. else 
  303. // loop through fields 
  304. foreach($sub_fields as $sub_field) 
  305. // unserialize options 
  306. if(@unserialize($sub_field['options'])) 
  307. $sub_field['options'] = @unserialize($sub_field['options']); 
  308. else 
  309. $sub_field['options'] = array(); 
  310.  
  311. // merge options with field 
  312. $sub_field = array_merge($sub_field, $sub_field['options']); 
  313.  
  314. unset($sub_field['options']); 
  315.  
  316. // each field has a unique id! 
  317. if(!isset($sub_field['key'])) $sub_field['key'] = 'field_' . $sub_field['id']; 
  318.  
  319. $field['options']['sub_fields'][] = $sub_field; 
  320.  
  321. // end if sub field 
  322.  
  323.  
  324. // merge options with field 
  325. $field = array_merge($field, $field['options']); 
  326.  
  327. unset($field['options']); 
  328.  
  329. // each field has a unique id! 
  330. if(!isset($field['key'])) $field['key'] = 'field_' . $field['id']; 
  331.  
  332. // update field 
  333. $this->parent->update_field( $field['post_id'], $field); 
  334.  
  335. // create field name (field_rand) 
  336. //$message .= print_r($field, true) . '<br /><br />'; 
  337. // end foreach $fields 
  338.  
  339.  
  340. $return = array( 
  341. 'status' => true,  
  342. 'message' => $message,  
  343. 'next' => '3.0.0 (step 4)',  
  344. ); 
  345.  
  346. break; 
  347.  
  348. /**--------------------- 
  349. * 
  350. * 3.0.0 
  351. * 
  352. *--------------------*/ 
  353.  
  354. case '3.0.0 (step 4)': 
  355.  
  356. $message = "Migrating Values..."; 
  357.  
  358. // update normal values 
  359. $values = $wpdb->get_results("SELECT v.field_id, m.post_id, m.meta_key, m.meta_value FROM $acf_values v LEFT JOIN $wp_postmeta m ON v.value = m.meta_id WHERE v.sub_field_id = 0", ARRAY_A); 
  360. if($values) 
  361. foreach($values as $value) 
  362. // options page 
  363. if($value['post_id'] == 0) $value['post_id'] = 999999999; 
  364.  
  365. // unserialize value (relationship, multi select, etc) 
  366. if(@unserialize($value['meta_value'])) 
  367. $value['meta_value'] = unserialize($value['meta_value']); 
  368.  
  369. update_post_meta($value['post_id'], $value['meta_key'], $value['meta_value']); 
  370. update_post_meta($value['post_id'], '_' . $value['meta_key'], 'field_' . $value['field_id']); 
  371.  
  372. // update repeater values 
  373. $values = $wpdb->get_results("SELECT v.field_id, v.sub_field_id, v.order_no, m.post_id, m.meta_key, m.meta_value FROM $acf_values v LEFT JOIN $wp_postmeta m ON v.value = m.meta_id WHERE v.sub_field_id != 0", ARRAY_A); 
  374. if($values) 
  375. $rows = array(); 
  376.  
  377. foreach($values as $value) 
  378. // update row count 
  379. $row = (int) $value['order_no'] + 1; 
  380.  
  381. // options page 
  382. if($value['post_id'] == 0) $value['post_id'] = 999999999; 
  383.  
  384. // unserialize value (relationship, multi select, etc) 
  385. if(@unserialize($value['meta_value'])) 
  386. $value['meta_value'] = unserialize($value['meta_value']); 
  387.  
  388. // current row 
  389. $current_row = isset($rows[$value['post_id']][$value['field_id']]) ? $rows[$value['post_id']][$value['field_id']] : 0; 
  390. if($row > $current_row) $rows[$value['post_id']][$value['field_id']] = (int) $row; 
  391.  
  392. // get field name 
  393. $field_name = $wpdb->get_var($wpdb->prepare("SELECT name FROM $acf_fields WHERE id = %d", $value['field_id'])); 
  394.  
  395. // get sub field name 
  396. $sub_field_name = $wpdb->get_var($wpdb->prepare("SELECT name FROM $acf_fields WHERE id = %d", $value['sub_field_id'])); 
  397.  
  398. // save new value 
  399. $new_meta_key = $field_name . '_' . $value['order_no'] . '_' . $sub_field_name; 
  400. update_post_meta($value['post_id'], $new_meta_key , $value['meta_value']); 
  401.  
  402. // save value hidden field id 
  403. update_post_meta($value['post_id'], '_' . $new_meta_key, 'field_' . $value['sub_field_id']); 
  404.  
  405. foreach($rows as $post_id => $field_ids) 
  406. foreach($field_ids as $field_id => $row_count) 
  407. // get sub field name 
  408. $field_name = $wpdb->get_var($wpdb->prepare("SELECT name FROM $acf_fields WHERE id = %d", $field_id)); 
  409.  
  410. delete_post_meta($post_id, $field_name); 
  411. update_post_meta($post_id, $field_name, $row_count); 
  412. update_post_meta($post_id, '_' . $field_name, 'field_' . $field_id); 
  413.  
  414.  
  415.  
  416. // update version (only upgrade 1 time) 
  417. update_option('acf_version', '3.0.0'); 
  418.  
  419. $return = array( 
  420. 'status' => true,  
  421. 'message' => $message,  
  422. 'next' => '3.1.8',  
  423. ); 
  424.  
  425. break; 
  426.  
  427.  
  428. /**--------------------- 
  429. * 
  430. * 3.1.8 
  431. * 
  432. *--------------------*/ 
  433.  
  434. case '3.1.8': 
  435.  
  436. // vars 
  437. $message = __("Migrating options values from the $wp_postmeta table to the $wp_options table", 'acf') . '...'; 
  438.  
  439. // update normal values 
  440. $rows = $wpdb->get_results( $wpdb->prepare("SELECT meta_key FROM $wp_postmeta WHERE post_id = %d", 999999999) , ARRAY_A); 
  441.  
  442. if($rows) 
  443. foreach($rows as $row) 
  444. // original name 
  445. $field_name = $row['meta_key']; 
  446.  
  447.  
  448. // name 
  449. $new_name = ""; 
  450. if( substr($field_name, 0, 1) == "_" ) 
  451. $new_name = '_options' . $field_name; 
  452. else 
  453. $new_name = 'options_' . $field_name; 
  454.  
  455.  
  456. // value 
  457. $value = get_post_meta( 999999999, $field_name, true ); 
  458.  
  459.  
  460. // update option 
  461. update_option( $new_name, $value ); 
  462.  
  463.  
  464. // deleet old postmeta 
  465. delete_post_meta( 999999999, $field_name ); 
  466.  
  467. // foreach($values as $value) 
  468. // if($values) 
  469.  
  470.  
  471. // update version 
  472. update_option('acf_version', '3.1.8'); 
  473.  
  474. $return = array( 
  475. 'status' => true,  
  476. 'message' => $message,  
  477. 'next' => '3.2.5',  
  478. ); 
  479.  
  480. break; 
  481.  
  482.  
  483. /**--------------------- 
  484. * 
  485. * 3.1.8 
  486. * 
  487. *--------------------*/ 
  488.  
  489. case '3.2.5': 
  490.  
  491. // vars 
  492. $message = __("Modifying field group options 'show on page'", 'acf') . '...'; 
  493.  
  494.  
  495. // get acf's 
  496. $acfs = get_posts(array( 
  497. 'numberposts' => -1,  
  498. 'post_type' => 'acf',  
  499. 'orderby' => 'menu_order title',  
  500. 'order' => 'asc',  
  501. 'suppress_filters' => false,  
  502. )); 
  503.  
  504.  
  505. $show_all = array('the_content', 'discussion', 'custom_fields', 'comments', 'slug', 'author'); 
  506.  
  507.  
  508. // populate acfs 
  509. if($acfs) 
  510. foreach($acfs as $acf) 
  511. $show_on_page = get_post_meta($acf->ID, 'show_on_page', true) ? get_post_meta($acf->ID, 'show_on_page', true) : array(); 
  512.  
  513. $hide_on_screen = array_diff($show_all, $show_on_page); 
  514.  
  515. update_post_meta($acf->ID, 'hide_on_screen', $hide_on_screen); 
  516. delete_post_meta($acf->ID, 'show_on_page'); 
  517.  
  518.  
  519.  
  520. // update version 
  521. update_option('acf_version', '3.2.5'); 
  522.  
  523. $return = array( 
  524. 'status' => true,  
  525. 'message' => $message,  
  526. 'next' => '3.3.3',  
  527. ); 
  528.  
  529. break; 
  530.  
  531.  
  532. /** 
  533. * 3.3.3 
  534. * 
  535. * @description: changed field option: taxonomies filter on relationship / post object and page link fields. 
  536. * @created: 20/07/12 
  537. */ 
  538.  
  539. case '3.3.3': 
  540.  
  541. // vars 
  542. $message = __("Modifying field option 'taxonomy'", 'acf') . '...'; 
  543. $wp_term_taxonomy = $wpdb->prefix.'term_taxonomy'; 
  544. $term_taxonomies = array(); 
  545.  
  546. $rows = $wpdb->get_results("SELECT * FROM $wp_term_taxonomy", ARRAY_A); 
  547.  
  548. if($rows) 
  549. foreach($rows as $row) 
  550. $term_taxonomies[ $row['term_id'] ] = $row['taxonomy'] . ":" . $row['term_id']; 
  551.  
  552.  
  553. // get acf's 
  554. $acfs = get_posts(array( 
  555. 'numberposts' => -1,  
  556. 'post_type' => 'acf',  
  557. 'orderby' => 'menu_order title',  
  558. 'order' => 'asc',  
  559. 'suppress_filters' => false,  
  560. )); 
  561.  
  562. // populate acfs 
  563. if($acfs) 
  564. foreach($acfs as $acf) 
  565. $fields = $this->parent->get_acf_fields($acf->ID); 
  566.  
  567. if( $fields ) 
  568. foreach( $fields as $field ) 
  569.  
  570. // only edit the option: taxonomy 
  571. if( !isset($field['taxonomy']) ) 
  572. continue; 
  573.  
  574.  
  575. if( is_array($field['taxonomy']) ) 
  576. foreach( $field['taxonomy'] as $k => $v ) 
  577.  
  578. // could be "all" 
  579. if( !is_numeric($v) ) 
  580. continue; 
  581.  
  582. $field['taxonomy'][ $k ] = $term_taxonomies[ $v ]; 
  583.  
  584.  
  585. // foreach( $field['taxonomy'] as $k => $v ) 
  586. // if( $field['taxonomy'] ) 
  587.  
  588.  
  589. $this->parent->update_field( $acf->ID, $field); 
  590.  
  591. // foreach( $fields as $field ) 
  592. // if( $fields ) 
  593. // foreach($acfs as $acf) 
  594. // if($acfs) 
  595.  
  596.  
  597. // update version 
  598. update_option('acf_version', '3.3.3'); 
  599.  
  600. $return = array( 
  601. 'status' => true,  
  602. 'message' => $message,  
  603. 'next' => '3.4.1',  
  604. ); 
  605.  
  606. break; 
  607.  
  608.  
  609. /** 
  610. * 3.4.1 
  611. * 
  612. * @description: Move user custom fields from wp_options to wp_usermeta 
  613. * @created: 20/07/12 
  614. */ 
  615.  
  616. case '3.4.1': 
  617.  
  618. // vars 
  619. $message = __("Moving user custom fields from wp_options to wp_usermeta", 'acf') . '...'; 
  620.  
  621. $option_row_ids = array(); 
  622. $option_rows = $wpdb->get_results("SELECT option_id, option_name, option_value FROM $wpdb->options WHERE option_name LIKE 'user%' OR option_name LIKE '\_user%'", ARRAY_A); 
  623.  
  624.  
  625. if( $option_rows ) 
  626. foreach( $option_rows as $k => $row) 
  627. preg_match('/user_([0-9]+)_(.*)/', $row['option_name'], $matches); 
  628.  
  629.  
  630. // if no matches, this is not an acf value, ignore it 
  631. if( !$matches ) 
  632. continue; 
  633.  
  634.  
  635. // add to $delete_option_rows 
  636. $option_row_ids[] = $row['option_id']; 
  637.  
  638.  
  639. // meta_key prefix 
  640. $meta_key_prefix = ""; 
  641. if( substr($row['option_name'], 0, 1) == "_" ) 
  642. $meta_key_prefix = '_'; 
  643.  
  644.  
  645. // update user meta 
  646. update_user_meta( $matches[1], $meta_key_prefix . $matches[2], $row['option_value'] ); 
  647.  
  648.  
  649.  
  650. // clear up some memory ( aprox 14 kb ) 
  651. unset( $option_rows ); 
  652.  
  653.  
  654. // remove $option_row_ids 
  655. if( $option_row_ids ) 
  656. $option_row_ids = implode(', ', $option_row_ids); 
  657.  
  658. $wpdb->query("DELETE FROM $wpdb->options WHERE option_id IN ($option_row_ids)"); 
  659.  
  660.  
  661. // update version 
  662. update_option('acf_version', '3.4.1'); 
  663.  
  664. $return = array( 
  665. 'status' => true,  
  666. 'message' => $message,  
  667. 'next' => false,  
  668. ); 
  669.  
  670. break; 
  671.  
  672.  
  673.  
  674. // return json 
  675. echo json_encode($return); 
  676. die; 
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683. new acf_upgrade(); 
  684.  
  685. ?> 
.