class-wp-theme-json-schema.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. /**
  3. * WP_Theme_JSON_Schema class
  4. *
  5. * @package WordPress
  6. * @subpackage Theme
  7. * @since 5.9.0
  8. */
  9. /**
  10. * Class that migrates a given theme.json structure to the latest schema.
  11. *
  12. * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
  13. * This is a low-level API that may need to do breaking changes. Please,
  14. * use get_global_settings, get_global_styles, and get_global_stylesheet instead.
  15. *
  16. * @since 5.9.0
  17. * @access private
  18. */
  19. #[AllowDynamicProperties]
  20. class WP_Theme_JSON_Schema {
  21. /**
  22. * Maps old properties to their new location within the schema's settings.
  23. * This will be applied at both the defaults and individual block levels.
  24. */
  25. const V1_TO_V2_RENAMED_PATHS = array(
  26. 'border.customRadius' => 'border.radius',
  27. 'spacing.customMargin' => 'spacing.margin',
  28. 'spacing.customPadding' => 'spacing.padding',
  29. 'typography.customLineHeight' => 'typography.lineHeight',
  30. );
  31. /**
  32. * Function that migrates a given theme.json structure to the last version.
  33. *
  34. * @since 5.9.0
  35. *
  36. * @param array $theme_json The structure to migrate.
  37. *
  38. * @return array The structure in the last version.
  39. */
  40. public static function migrate( $theme_json ) {
  41. if ( ! isset( $theme_json['version'] ) ) {
  42. $theme_json = array(
  43. 'version' => WP_Theme_JSON::LATEST_SCHEMA,
  44. );
  45. }
  46. if ( 1 === $theme_json['version'] ) {
  47. $theme_json = self::migrate_v1_to_v2( $theme_json );
  48. }
  49. return $theme_json;
  50. }
  51. /**
  52. * Removes the custom prefixes for a few properties
  53. * that were part of v1:
  54. *
  55. * 'border.customRadius' => 'border.radius',
  56. * 'spacing.customMargin' => 'spacing.margin',
  57. * 'spacing.customPadding' => 'spacing.padding',
  58. * 'typography.customLineHeight' => 'typography.lineHeight',
  59. *
  60. * @since 5.9.0
  61. *
  62. * @param array $old Data to migrate.
  63. *
  64. * @return array Data without the custom prefixes.
  65. */
  66. private static function migrate_v1_to_v2( $old ) {
  67. // Copy everything.
  68. $new = $old;
  69. // Overwrite the things that changed.
  70. if ( isset( $old['settings'] ) ) {
  71. $new['settings'] = self::rename_paths( $old['settings'], self::V1_TO_V2_RENAMED_PATHS );
  72. }
  73. // Set the new version.
  74. $new['version'] = 2;
  75. return $new;
  76. }
  77. /**
  78. * Processes the settings subtree.
  79. *
  80. * @since 5.9.0
  81. *
  82. * @param array $settings Array to process.
  83. * @param array $paths_to_rename Paths to rename.
  84. *
  85. * @return array The settings in the new format.
  86. */
  87. private static function rename_paths( $settings, $paths_to_rename ) {
  88. $new_settings = $settings;
  89. // Process any renamed/moved paths within default settings.
  90. self::rename_settings( $new_settings, $paths_to_rename );
  91. // Process individual block settings.
  92. if ( isset( $new_settings['blocks'] ) && is_array( $new_settings['blocks'] ) ) {
  93. foreach ( $new_settings['blocks'] as &$block_settings ) {
  94. self::rename_settings( $block_settings, $paths_to_rename );
  95. }
  96. }
  97. return $new_settings;
  98. }
  99. /**
  100. * Processes a settings array, renaming or moving properties.
  101. *
  102. * @since 5.9.0
  103. *
  104. * @param array $settings Reference to settings either defaults or an individual block's.
  105. * @param array $paths_to_rename Paths to rename.
  106. */
  107. private static function rename_settings( &$settings, $paths_to_rename ) {
  108. foreach ( $paths_to_rename as $original => $renamed ) {
  109. $original_path = explode( '.', $original );
  110. $renamed_path = explode( '.', $renamed );
  111. $current_value = _wp_array_get( $settings, $original_path, null );
  112. if ( null !== $current_value ) {
  113. _wp_array_set( $settings, $renamed_path, $current_value );
  114. self::unset_setting_by_path( $settings, $original_path );
  115. }
  116. }
  117. }
  118. /**
  119. * Removes a property from within the provided settings by its path.
  120. *
  121. * @since 5.9.0
  122. *
  123. * @param array $settings Reference to the current settings array.
  124. * @param array $path Path to the property to be removed.
  125. *
  126. * @return void
  127. */
  128. private static function unset_setting_by_path( &$settings, $path ) {
  129. $tmp_settings = &$settings; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
  130. $last_key = array_pop( $path );
  131. foreach ( $path as $key ) {
  132. $tmp_settings = &$tmp_settings[ $key ];
  133. }
  134. unset( $tmp_settings[ $last_key ] );
  135. }
  136. }