PageRenderTime 23ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-sync/src/class-data-settings.php

https://gitlab.com/chernushov881/charity-fund
PHP | 354 lines | 181 code | 41 blank | 132 comment | 23 complexity | bf2cafec5bbfed5f15f8a3679639b5de MD5 | raw file
  1. <?php
  2. /**
  3. * The Data Settings class.
  4. *
  5. * @package automattic/jetpack-sync
  6. */
  7. namespace Automattic\Jetpack\Sync;
  8. /**
  9. * The Data_Settings class
  10. */
  11. class Data_Settings {
  12. /**
  13. * The data that must be synced for every synced site.
  14. */
  15. const MUST_SYNC_DATA_SETTINGS = array(
  16. 'jetpack_sync_modules' => array(
  17. 'Automattic\\Jetpack\\Sync\\Modules\\Callables',
  18. ),
  19. 'jetpack_sync_callable_whitelist' => array(
  20. 'site_url' => array( 'Automattic\\Jetpack\\Connection\\Urls', 'site_url' ),
  21. 'home_url' => array( 'Automattic\\Jetpack\\Connection\\Urls', 'home_url' ),
  22. 'paused_plugins' => array( 'Automattic\\Jetpack\\Sync\\Functions', 'get_paused_plugins' ),
  23. 'paused_themes' => array( 'Automattic\\Jetpack\\Sync\\Functions', 'get_paused_themes' ),
  24. ),
  25. );
  26. const MODULE_FILTER_MAPPING = array(
  27. 'Automattic\\Jetpack\\Sync\\Modules\\Options' => array(
  28. 'jetpack_sync_options_whitelist',
  29. 'jetpack_sync_options_contentless',
  30. ),
  31. 'Automattic\\Jetpack\\Sync\\Modules\\Constants' => array(
  32. 'jetpack_sync_constants_whitelist',
  33. ),
  34. 'Automattic\\Jetpack\\Sync\\Modules\\Callables' => array(
  35. 'jetpack_sync_callable_whitelist',
  36. 'jetpack_sync_multisite_callable_whitelist',
  37. ),
  38. 'Automattic\\Jetpack\\Sync\\Modules\\Posts' => array(
  39. 'jetpack_sync_post_meta_whitelist',
  40. ),
  41. 'Automattic\\Jetpack\\Sync\\Modules\\Comments' => array(
  42. 'jetpack_sync_comment_meta_whitelist',
  43. ),
  44. 'Automattic\\Jetpack\\Sync\\Modules\\Users' => array(
  45. 'jetpack_sync_capabilities_whitelist',
  46. ),
  47. 'Automattic\\Jetpack\\Sync\\Modules\\Import' => array(
  48. 'jetpack_sync_known_importers',
  49. ),
  50. );
  51. const MODULES_FILTER_NAME = 'jetpack_sync_modules';
  52. /**
  53. * The static data settings array which contains the aggregated data settings for
  54. * each sync filter.
  55. *
  56. * @var array
  57. */
  58. private static $data_settings = array();
  59. /**
  60. * The static array which contains the list of filter hooks that have already been set up.
  61. *
  62. * @var array
  63. */
  64. private static $set_filter_hooks = array();
  65. /**
  66. * Adds the data settings provided by a plugin to the Sync data settings.
  67. *
  68. * @param array $plugin_settings The array provided by the plugin. The array must use filters
  69. * from the DATA_FILTER_DEFAULTS list as keys.
  70. */
  71. public function add_settings_list( $plugin_settings = array() ) {
  72. if ( empty( $plugin_settings[ self::MODULES_FILTER_NAME ] )
  73. || ! is_array( $plugin_settings[ self::MODULES_FILTER_NAME ] ) ) {
  74. /*
  75. * No modules have been set, so use defaults for everything and bail early.
  76. */
  77. $this->set_all_defaults();
  78. return;
  79. }
  80. $this->add_filters_custom_settings_and_hooks( $plugin_settings );
  81. if ( ! did_action( 'jetpack_sync_add_required_data_settings' ) ) {
  82. $this->add_required_settings();
  83. /**
  84. * Fires when the required settings have been adding to the static
  85. * data_settings array.
  86. *
  87. * @since 1.29.2
  88. *
  89. * @module sync
  90. */
  91. do_action( 'jetpack_sync_add_required_data_settings' );
  92. }
  93. }
  94. /**
  95. * Sets the default values for sync modules and all sync data filters.
  96. */
  97. private function set_all_defaults() {
  98. $this->add_sync_filter_setting( self::MODULES_FILTER_NAME, Modules::DEFAULT_SYNC_MODULES );
  99. foreach ( array_keys( Default_Filter_Settings::DATA_FILTER_DEFAULTS ) as $filter ) {
  100. $this->add_sync_filter_setting( $filter, $this->get_default_setting_for_filter( $filter ) );
  101. }
  102. }
  103. /**
  104. * Returns the default settings for the given filter.
  105. *
  106. * @param string $filter The filter name.
  107. *
  108. * @return array The filter's default settings array.
  109. */
  110. private function get_default_setting_for_filter( $filter ) {
  111. if ( self::MODULES_FILTER_NAME === $filter ) {
  112. return Modules::DEFAULT_SYNC_MODULES;
  113. }
  114. return ( new Default_Filter_Settings() )->get_default_settings( $filter );
  115. }
  116. /**
  117. * Adds the custom settings and sets up the necessary filter hooks.
  118. *
  119. * @param array $filters_settings The custom settings.
  120. */
  121. private function add_filters_custom_settings_and_hooks( $filters_settings ) {
  122. if ( ! isset( $filters_settings[ self::MODULES_FILTER_NAME ] ) ) {
  123. // This shouldn't happen.
  124. return;
  125. }
  126. $this->add_custom_filter_setting( self::MODULES_FILTER_NAME, $filters_settings[ self::MODULES_FILTER_NAME ] );
  127. $enabled_modules = $filters_settings[ self::MODULES_FILTER_NAME ];
  128. $all_modules = Modules::DEFAULT_SYNC_MODULES;
  129. foreach ( $all_modules as $module ) {
  130. if ( in_array( $module, $enabled_modules, true ) ) {
  131. $this->add_filters_for_enabled_module( $module, $filters_settings );
  132. } else {
  133. $this->add_filters_for_disabled_module( $module );
  134. }
  135. }
  136. }
  137. /**
  138. * Adds the filters for the provided enabled module. If the settings provided custom filter settings
  139. * for the module's filters, those are used. Otherwise, the filter's default settings are used.
  140. *
  141. * @param string $module The module name.
  142. * @param array $filters_settings The settings for the filters.
  143. */
  144. private function add_filters_for_enabled_module( $module, $filters_settings ) {
  145. $module_mapping = self::MODULE_FILTER_MAPPING;
  146. $filters_for_module = isset( $module_mapping[ $module ] ) ? $module_mapping[ $module ] : array();
  147. foreach ( $filters_for_module as $filter ) {
  148. if ( isset( $filters_settings[ $filter ] ) ) {
  149. $this->add_custom_filter_setting( $filter, $filters_settings[ $filter ] );
  150. } else {
  151. $this->add_sync_filter_setting( $filter, $this->get_default_setting_for_filter( $filter ) );
  152. }
  153. }
  154. }
  155. /**
  156. * Adds the filters for the provided disabled module. The disabled module's associated filter settings are
  157. * set to an empty array.
  158. *
  159. * @param string $module The module name.
  160. */
  161. private function add_filters_for_disabled_module( $module ) {
  162. $module_mapping = self::MODULE_FILTER_MAPPING;
  163. $filters_for_module = isset( $module_mapping[ $module ] ) ? $module_mapping[ $module ] : array();
  164. foreach ( $filters_for_module as $filter ) {
  165. $this->add_custom_filter_setting( $filter, array() );
  166. }
  167. }
  168. /**
  169. * Adds the provided custom setting for a filter. If the filter setting isn't valid, the default
  170. * value is used.
  171. *
  172. * If the filter's hook hasn't already been set up, it gets set up.
  173. *
  174. * @param string $filter The filter.
  175. * @param array $setting The filter setting.
  176. */
  177. private function add_custom_filter_setting( $filter, $setting ) {
  178. if ( ! $this->is_valid_filter_setting( $filter, $setting ) ) {
  179. /*
  180. * The provided setting isn't valid, so use the default for this filter.
  181. * We're using the default values so there's no need to set the filter hook.
  182. */
  183. $this->add_sync_filter_setting( $filter, $this->get_default_setting_for_filter( $filter ) );
  184. return;
  185. }
  186. if ( ! isset( static::$set_filter_hooks[ $filter ] ) ) {
  187. // First time a custom modules setting is provided, so set the filter hook.
  188. add_filter( $filter, array( $this, 'sync_data_filter_hook' ) );
  189. static::$set_filter_hooks[ $filter ] = 1;
  190. }
  191. $this->add_sync_filter_setting( $filter, $setting );
  192. }
  193. /**
  194. * Determines whether the filter setting is valid. The setting array is in the correct format (associative or indexed).
  195. *
  196. * @param string $filter The filter to check.
  197. * @param array $filter_settings The filter settings.
  198. *
  199. * @return bool Whether the filter settings can be used.
  200. */
  201. private function is_valid_filter_setting( $filter, $filter_settings ) {
  202. if ( ! is_array( $filter_settings ) ) {
  203. // The settings for each filter must be an array.
  204. return false;
  205. }
  206. if ( empty( $filter_settings ) ) {
  207. // Empty settings are allowed.
  208. return true;
  209. }
  210. $indexed_array = isset( $filter_settings[0] );
  211. if ( in_array( $filter, Default_Filter_Settings::ASSOCIATIVE_FILTERS, true ) && ! $indexed_array ) {
  212. return true;
  213. } elseif ( ! in_array( $filter, Default_Filter_Settings::ASSOCIATIVE_FILTERS, true ) && $indexed_array ) {
  214. return true;
  215. }
  216. return false;
  217. }
  218. /**
  219. * Adds the data settings that are always required for every plugin that uses Sync.
  220. */
  221. private function add_required_settings() {
  222. foreach ( self::MUST_SYNC_DATA_SETTINGS as $filter => $setting ) {
  223. $this->add_custom_filter_setting( $filter, $setting );
  224. }
  225. }
  226. /**
  227. * Adds the provided data setting for the provided filter.
  228. *
  229. * @param string $filter The filter name.
  230. * @param array $value The data setting.
  231. */
  232. private function add_sync_filter_setting( $filter, $value ) {
  233. if ( ! isset( static::$data_settings[ $filter ] ) ) {
  234. static::$data_settings[ $filter ] = $value;
  235. return;
  236. }
  237. if ( in_array( $filter, Default_Filter_Settings::ASSOCIATIVE_FILTERS, true ) ) {
  238. $this->add_associative_filter_setting( $filter, $value );
  239. } else {
  240. $this->add_indexed_filter_setting( $filter, $value );
  241. }
  242. }
  243. /**
  244. * Adds the provided data setting for the provided filter. This method handles
  245. * adding settings to data that is stored as an associative array.
  246. *
  247. * @param string $filter The filter name.
  248. * @param array $settings The data settings.
  249. */
  250. private function add_associative_filter_setting( $filter, $settings ) {
  251. foreach ( $settings as $key => $item ) {
  252. if ( ! array_key_exists( $key, static::$data_settings[ $filter ] ) ) {
  253. static::$data_settings[ $filter ][ $key ] = $item;
  254. }
  255. }
  256. }
  257. /**
  258. * Adds the provided data setting for the provided filter. This method handles
  259. * adding settings to data that is stored as an indexed array.
  260. *
  261. * @param string $filter The filter name.
  262. * @param array $settings The data settings.
  263. */
  264. private function add_indexed_filter_setting( $filter, $settings ) {
  265. static::$data_settings[ $filter ] = array_unique(
  266. array_merge(
  267. static::$data_settings[ $filter ],
  268. $settings
  269. )
  270. );
  271. }
  272. /**
  273. * The callback function added to the sync data filters. Combines the list in the $data_settings property
  274. * with any non-default values from the received array.
  275. *
  276. * @param array $filtered_values The data revieved from the filter.
  277. *
  278. * @return array The data settings for the filter.
  279. */
  280. public function sync_data_filter_hook( $filtered_values ) {
  281. if ( ! is_array( $filtered_values ) ) {
  282. // Something is wrong with the input, so set it to an empty array.
  283. $filtered_values = array();
  284. }
  285. $current_filter = current_filter();
  286. if ( ! isset( static::$data_settings[ $current_filter ] ) ) {
  287. return $filtered_values;
  288. }
  289. if ( in_array( $current_filter, Default_Filter_Settings::ASSOCIATIVE_FILTERS, true ) ) {
  290. $extra_filters = array_diff_key( $filtered_values, $this->get_default_setting_for_filter( $current_filter ) );
  291. $this->add_associative_filter_setting( $current_filter, $extra_filters );
  292. return static::$data_settings[ $current_filter ];
  293. }
  294. $extra_filters = array_diff( $filtered_values, $this->get_default_setting_for_filter( $current_filter ) );
  295. $this->add_indexed_filter_setting( $current_filter, $extra_filters );
  296. return static::$data_settings[ $current_filter ];
  297. }
  298. /**
  299. * Sets the $data_settings property to an empty array. This is useful for testing.
  300. */
  301. public function empty_data_settings_and_hooks() {
  302. static::$data_settings = array();
  303. static::$set_filter_hooks = array();
  304. }
  305. /**
  306. * Returns the $data_settings property.
  307. *
  308. * @return array The data_settings property.
  309. */
  310. public function get_data_settings() {
  311. return static::$data_settings;
  312. }
  313. }