upgrades.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. namespace Elementor;
  3. if ( ! defined( 'ABSPATH' ) ) {
  4. exit; // Exit if accessed directly.
  5. }
  6. /**
  7. * Elementor upgrades.
  8. *
  9. * Elementor upgrades handler class is responsible for updating different
  10. * Elementor versions.
  11. *
  12. * @since 1.0.0
  13. */
  14. class Upgrades {
  15. /**
  16. * Add actions.
  17. *
  18. * Hook into WordPress actions and launch Elementor upgrades.
  19. *
  20. * @static
  21. * @since 1.0.0
  22. * @access public
  23. */
  24. public static function add_actions() {
  25. add_action( 'init', [ __CLASS__, 'init' ], 20 );
  26. }
  27. /**
  28. * Init.
  29. *
  30. * Initialize Elementor upgrades.
  31. *
  32. * Fired by `init` action.
  33. *
  34. * @static
  35. * @since 1.0.0
  36. * @access public
  37. */
  38. public static function init() {
  39. $elementor_version = get_option( 'elementor_version' );
  40. // Normal init.
  41. if ( ELEMENTOR_VERSION === $elementor_version ) {
  42. return;
  43. }
  44. self::check_upgrades( $elementor_version );
  45. Plugin::$instance->files_manager->clear_cache();
  46. update_option( 'elementor_version', ELEMENTOR_VERSION );
  47. }
  48. /**
  49. * Check upgrades.
  50. *
  51. * Checks whether a given Elementor version needs to be upgraded.
  52. *
  53. * If an upgrade required for a specific Elementor version, it will update
  54. * the `elementor_upgrades` option in the database.
  55. *
  56. * @static
  57. * @since 1.0.10
  58. * @access private
  59. *
  60. * @param string $elementor_version
  61. */
  62. private static function check_upgrades( $elementor_version ) {
  63. // It's a new install.
  64. if ( ! $elementor_version ) {
  65. return;
  66. }
  67. $elementor_upgrades = get_option( 'elementor_upgrades', [] );
  68. $upgrades = [
  69. '0.3.2' => 'upgrade_v032',
  70. '0.9.2' => 'upgrade_v092',
  71. '0.11.0' => 'upgrade_v0110',
  72. '2.0.0' => 'upgrade_v200',
  73. '2.0.1' => 'upgrade_v201',
  74. '2.0.10' => 'upgrade_v2010',
  75. '2.1.0' => 'upgrade_v210',
  76. ];
  77. foreach ( $upgrades as $version => $function ) {
  78. if ( version_compare( $elementor_version, $version, '<' ) && ! isset( $elementor_upgrades[ $version ] ) ) {
  79. self::$function();
  80. $elementor_upgrades[ $version ] = true;
  81. update_option( 'elementor_upgrades', $elementor_upgrades );
  82. }
  83. }
  84. }
  85. /**
  86. * Upgrade Elementor 0.3.2
  87. *
  88. * Change the image widget link URL, setting is to `custom` link.
  89. *
  90. * @since 2.0.0
  91. * @static
  92. * @access private
  93. */
  94. private static function upgrade_v032() {
  95. global $wpdb;
  96. $post_ids = $wpdb->get_col(
  97. 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
  98. WHERE `meta_key` = \'_elementor_version\'
  99. AND `meta_value` = \'0.1\';'
  100. );
  101. if ( empty( $post_ids ) ) {
  102. return;
  103. }
  104. foreach ( $post_ids as $post_id ) {
  105. $data = Plugin::$instance->db->get_plain_editor( $post_id );
  106. if ( empty( $data ) ) {
  107. continue;
  108. }
  109. $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
  110. if ( empty( $element['widgetType'] ) || 'image' !== $element['widgetType'] ) {
  111. return $element;
  112. }
  113. if ( ! empty( $element['settings']['link']['url'] ) ) {
  114. $element['settings']['link_to'] = 'custom';
  115. }
  116. return $element;
  117. } );
  118. Plugin::$instance->db->save_editor( $post_id, $data );
  119. }
  120. }
  121. /**
  122. * Upgrade Elementor 0.9.2
  123. *
  124. * Change the icon widget, icon-box widget and the social-icons widget,
  125. * setting their icon padding size to an empty string.
  126. *
  127. * Change the image widget, setting the image size to full image size.
  128. *
  129. * @since 2.0.0
  130. * @static
  131. * @access private
  132. */
  133. private static function upgrade_v092() {
  134. global $wpdb;
  135. // Fix Icon/Icon Box Widgets padding.
  136. $post_ids = $wpdb->get_col(
  137. 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
  138. WHERE `meta_key` = \'_elementor_version\'
  139. AND `meta_value` = \'0.2\';'
  140. );
  141. if ( empty( $post_ids ) ) {
  142. return;
  143. }
  144. foreach ( $post_ids as $post_id ) {
  145. $data = Plugin::$instance->db->get_plain_editor( $post_id );
  146. if ( empty( $data ) ) {
  147. continue;
  148. }
  149. $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
  150. if ( empty( $element['widgetType'] ) ) {
  151. return $element;
  152. }
  153. if ( in_array( $element['widgetType'], [ 'icon', 'icon-box', 'social-icons' ] ) ) {
  154. if ( ! empty( $element['settings']['icon_padding']['size'] ) ) {
  155. $element['settings']['icon_padding']['size'] = '';
  156. }
  157. }
  158. if ( 'image' === $element['widgetType'] ) {
  159. if ( empty( $element['settings']['image_size'] ) ) {
  160. $element['settings']['image_size'] = 'full';
  161. }
  162. }
  163. return $element;
  164. } );
  165. Plugin::$instance->db->save_editor( $post_id, $data );
  166. }
  167. }
  168. /**
  169. * Upgrade Elementor 0.11.0
  170. *
  171. * Change the button widget sizes, setting up new button sizes.
  172. *
  173. * @since 2.0.0
  174. * @static
  175. * @access private
  176. */
  177. private static function upgrade_v0110() {
  178. global $wpdb;
  179. // Fix Button widget to new sizes options.
  180. $post_ids = $wpdb->get_col(
  181. 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
  182. WHERE `meta_key` = \'_elementor_version\'
  183. AND `meta_value` = \'0.3\';'
  184. );
  185. if ( empty( $post_ids ) ) {
  186. return;
  187. }
  188. foreach ( $post_ids as $post_id ) {
  189. $data = Plugin::$instance->db->get_plain_editor( $post_id );
  190. if ( empty( $data ) ) {
  191. continue;
  192. }
  193. $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
  194. if ( empty( $element['widgetType'] ) ) {
  195. return $element;
  196. }
  197. if ( 'button' === $element['widgetType'] ) {
  198. $size_to_replace = [
  199. 'small' => 'xs',
  200. 'medium' => 'sm',
  201. 'large' => 'md',
  202. 'xl' => 'lg',
  203. 'xxl' => 'xl',
  204. ];
  205. if ( ! empty( $element['settings']['size'] ) ) {
  206. $old_size = $element['settings']['size'];
  207. if ( isset( $size_to_replace[ $old_size ] ) ) {
  208. $element['settings']['size'] = $size_to_replace[ $old_size ];
  209. }
  210. }
  211. }
  212. return $element;
  213. } );
  214. Plugin::$instance->db->save_editor( $post_id, $data );
  215. }
  216. }
  217. /**
  218. * Upgrade Elementor 2.0.0
  219. *
  220. * Fix post titles for old autosave drafts that saved with the format 'Auto Save 2018-03-18 17:24'.
  221. *
  222. * @static
  223. * @since 2.0.0
  224. * @access private
  225. */
  226. private static function upgrade_v200() {
  227. global $wpdb;
  228. $posts = $wpdb->get_results(
  229. 'SELECT `ID`, `post_title`, `post_parent`
  230. FROM `' . $wpdb->posts . '` p
  231. LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
  232. WHERE `post_status` = \'inherit\'
  233. AND `post_title` = CONCAT(\'Auto Save \', DATE_FORMAT(post_date, "%Y-%m-%d %H:%i"))
  234. AND m.`meta_key` = \'_elementor_data\';'
  235. );
  236. if ( empty( $posts ) ) {
  237. return;
  238. }
  239. foreach ( $posts as $post ) {
  240. wp_update_post( [
  241. 'ID' => $post->ID,
  242. 'post_title' => get_the_title( $post->post_parent ),
  243. ] );
  244. }
  245. }
  246. /**
  247. * Upgrade Elementor 2.0.1
  248. *
  249. * Fix post titles for old autosave drafts that saved with the format 'Auto Save...'.
  250. *
  251. * @since 2.0.2
  252. * @static
  253. * @access private
  254. */
  255. private static function upgrade_v201() {
  256. global $wpdb;
  257. $posts = $wpdb->get_results(
  258. 'SELECT `ID`, `post_title`, `post_parent`
  259. FROM `' . $wpdb->posts . '` p
  260. LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
  261. WHERE `post_status` = \'inherit\'
  262. AND `post_title` REGEXP \'^Auto Save [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$\'
  263. AND m.`meta_key` = \'_elementor_data\';'
  264. );
  265. if ( empty( $posts ) ) {
  266. return;
  267. }
  268. foreach ( $posts as $post ) {
  269. $parent = get_post( $post->post_parent );
  270. $title = isset( $parent->post_title ) ? $parent->post_title : '';
  271. wp_update_post( [
  272. 'ID' => $post->ID,
  273. 'post_title' => $title,
  274. ] );
  275. }
  276. }
  277. /**
  278. * Upgrade Elementor 2.0.10
  279. *
  280. * Fix post titles for old autosave drafts that saved with the format 'Auto Save...'.
  281. * Fix also Translated titles.
  282. *
  283. * @since 2.0.10
  284. * @static
  285. * @access private
  286. */
  287. private static function upgrade_v2010() {
  288. global $wpdb;
  289. $posts = $wpdb->get_results(
  290. 'SELECT `ID`, `post_title`, `post_parent`
  291. FROM `' . $wpdb->posts . '` p
  292. LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
  293. WHERE `post_status` = \'inherit\'
  294. AND `post_title` REGEXP \'[[:alnum:]]+ [[:alnum:]]+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$\'
  295. AND m.`meta_key` = \'_elementor_data\';'
  296. );
  297. if ( empty( $posts ) ) {
  298. return;
  299. }
  300. foreach ( $posts as $post ) {
  301. $parent = get_post( $post->post_parent );
  302. $title = isset( $parent->post_title ) ? $parent->post_title : '';
  303. wp_update_post( [
  304. 'ID' => $post->ID,
  305. 'post_title' => $title,
  306. ] );
  307. }
  308. }
  309. private static function upgrade_v210() {
  310. global $wpdb;
  311. // upgrade `video` widget settings (merge providers).
  312. $post_ids = $wpdb->get_col(
  313. 'SELECT `post_id` FROM `' . $wpdb->postmeta . '` WHERE `meta_key` = "_elementor_data" AND `meta_value` LIKE \'%"widgetType":"video"%\';'
  314. );
  315. if ( empty( $post_ids ) ) {
  316. return;
  317. }
  318. foreach ( $post_ids as $post_id ) {
  319. $do_update = false;
  320. $data = Plugin::$instance->db->get_plain_editor( $post_id );
  321. if ( empty( $data ) ) {
  322. continue;
  323. }
  324. $data = Plugin::$instance->db->iterate_data( $data, function ( $element ) use ( & $do_update ) {
  325. if ( empty( $element['widgetType'] ) || 'video' !== $element['widgetType'] ) {
  326. return $element;
  327. }
  328. $replacements = [];
  329. if ( empty( $element['settings']['video_type'] ) || 'youtube' === $element['settings']['video_type'] ) {
  330. $replacements = [
  331. 'yt_autoplay' => 'autoplay',
  332. 'yt_controls' => 'controls',
  333. 'yt_mute' => 'mute',
  334. 'yt_showinfo' => 'showinfo',
  335. 'yt_rel' => 'rel',
  336. 'link' => 'youtube_url',
  337. ];
  338. } elseif ( 'vimeo' === $element['settings']['video_type'] ) {
  339. $replacements = [
  340. 'vimeo_autoplay' => 'autoplay',
  341. 'vimeo_loop' => 'loop',
  342. 'vimeo_color' => 'color',
  343. 'vimeo_link' => 'vimeo_url',
  344. ];
  345. }
  346. // cleanup old unused settings.
  347. unset( $element['settings']['yt_rel_videos'] );
  348. foreach ( $replacements as $old => $new ) {
  349. if ( ! empty( $element['settings'][ $old ] ) ) {
  350. $element['settings'][ $new ] = $element['settings'][ $old ];
  351. $do_update = true;
  352. }
  353. }
  354. return $element;
  355. } );
  356. // Only update if needed.
  357. if ( ! $do_update ) {
  358. continue;
  359. }
  360. // We need the `wp_slash` in order to avoid the unslashing during the `update_post_meta`
  361. $json_value = wp_slash( wp_json_encode( $data ) );
  362. update_metadata( 'post', $post_id, '_elementor_data', $json_value );
  363. // Clear WP cache for next step.
  364. wp_cache_flush();
  365. } // End foreach().
  366. }
  367. }