*/ public function expand_theme_data() { return array( $this->get_theme_info() ); } /** * Retrieve the name of the widget by the widget ID. * * @access public * @global $wp_registered_widgets * * @param string $widget_id Widget ID. * @return string Name of the widget, or null if not found. */ public function get_widget_name( $widget_id ) { global $wp_registered_widgets; return ( isset( $wp_registered_widgets[ $widget_id ] ) ? $wp_registered_widgets[ $widget_id ]['name'] : null ); } /** * Retrieve the name of the sidebar by the sidebar ID. * * @access public * @global $wp_registered_sidebars * * @param string $sidebar_id Sidebar ID. * @return string Name of the sidebar, or null if not found. */ public function get_sidebar_name( $sidebar_id ) { global $wp_registered_sidebars; return ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ? $wp_registered_sidebars[ $sidebar_id ]['name'] : null ); } /** * Sync addition of widgets to a sidebar. * * @access public * * @param array $new_widgets New widgets. * @param array $old_widgets Old widgets. * @param string $sidebar Sidebar ID. * @return array All widgets that have been moved to the sidebar. */ public function sync_add_widgets_to_sidebar( $new_widgets, $old_widgets, $sidebar ) { $added_widgets = array_diff( $new_widgets, $old_widgets ); if ( empty( $added_widgets ) ) { return array(); } $moved_to_sidebar = array(); $sidebar_name = $this->get_sidebar_name( $sidebar ); // Don't sync jetpack_widget_added if theme was switched. if ( $this->is_theme_switch() ) { return array(); } foreach ( $added_widgets as $added_widget ) { $moved_to_sidebar[] = $added_widget; $added_widget_name = $this->get_widget_name( $added_widget ); /** * Helps Sync log that a widget got added * * @since 4.9.0 * * @param string $sidebar, Sidebar id got changed * @param string $added_widget, Widget id got added * @param string $sidebar_name, Sidebar id got changed Since 5.0.0 * @param string $added_widget_name, Widget id got added Since 5.0.0 */ do_action( 'jetpack_widget_added', $sidebar, $added_widget, $sidebar_name, $added_widget_name ); } return $moved_to_sidebar; } /** * Sync removal of widgets from a sidebar. * * @access public * * @param array $new_widgets New widgets. * @param array $old_widgets Old widgets. * @param string $sidebar Sidebar ID. * @param array $inactive_widgets Current inactive widgets. * @return array All widgets that have been moved to inactive. */ public function sync_remove_widgets_from_sidebar( $new_widgets, $old_widgets, $sidebar, $inactive_widgets ) { $removed_widgets = array_diff( $old_widgets, $new_widgets ); if ( empty( $removed_widgets ) ) { return array(); } $moved_to_inactive = array(); $sidebar_name = $this->get_sidebar_name( $sidebar ); foreach ( $removed_widgets as $removed_widget ) { // Lets check if we didn't move the widget to in_active_widgets. if ( isset( $inactive_widgets ) && ! in_array( $removed_widget, $inactive_widgets, true ) ) { $removed_widget_name = $this->get_widget_name( $removed_widget ); /** * Helps Sync log that a widgte got removed * * @since 4.9.0 * * @param string $sidebar, Sidebar id got changed * @param string $removed_widget, Widget id got removed * @param string $sidebar_name, Name of the sidebar that changed Since 5.0.0 * @param string $removed_widget_name, Name of the widget that got removed Since 5.0.0 */ do_action( 'jetpack_widget_removed', $sidebar, $removed_widget, $sidebar_name, $removed_widget_name ); } else { $moved_to_inactive[] = $removed_widget; } } return $moved_to_inactive; } /** * Sync a reorder of widgets within a sidebar. * * @access public * * @todo Refactor serialize() to a json_encode(). * * @param array $new_widgets New widgets. * @param array $old_widgets Old widgets. * @param string $sidebar Sidebar ID. */ public function sync_widgets_reordered( $new_widgets, $old_widgets, $sidebar ) { $added_widgets = array_diff( $new_widgets, $old_widgets ); if ( ! empty( $added_widgets ) ) { return; } $removed_widgets = array_diff( $old_widgets, $new_widgets ); if ( ! empty( $removed_widgets ) ) { return; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize if ( serialize( $old_widgets ) !== serialize( $new_widgets ) ) { $sidebar_name = $this->get_sidebar_name( $sidebar ); /** * Helps Sync log that a sidebar id got reordered * * @since 4.9.0 * * @param string $sidebar, Sidebar id got changed * @param string $sidebar_name, Name of the sidebar that changed Since 5.0.0 */ do_action( 'jetpack_widget_reordered', $sidebar, $sidebar_name ); } } /** * Handle the update of the sidebars and widgets mapping option. * * @access public * * @param mixed $old_value The old option value. * @param mixed $new_value The new option value. */ public function sync_sidebar_widgets_actions( $old_value, $new_value ) { // Don't really know how to deal with different array_values yet. if ( ( isset( $old_value['array_version'] ) && 3 !== $old_value['array_version'] ) || ( isset( $new_value['array_version'] ) && 3 !== $new_value['array_version'] ) ) { return; } $moved_to_inactive_ids = array(); $moved_to_sidebar = array(); foreach ( $new_value as $sidebar => $new_widgets ) { if ( in_array( $sidebar, array( 'array_version', 'wp_inactive_widgets' ), true ) ) { continue; } $old_widgets = isset( $old_value[ $sidebar ] ) ? $old_value[ $sidebar ] : array(); if ( ! is_array( $new_widgets ) ) { $new_widgets = array(); } $moved_to_inactive_recently = $this->sync_remove_widgets_from_sidebar( $new_widgets, $old_widgets, $sidebar, $new_value['wp_inactive_widgets'] ); $moved_to_inactive_ids = array_merge( $moved_to_inactive_ids, $moved_to_inactive_recently ); $moved_to_sidebar_recently = $this->sync_add_widgets_to_sidebar( $new_widgets, $old_widgets, $sidebar ); $moved_to_sidebar = array_merge( $moved_to_sidebar, $moved_to_sidebar_recently ); $this->sync_widgets_reordered( $new_widgets, $old_widgets, $sidebar ); } // Don't sync either jetpack_widget_moved_to_inactive or jetpack_cleared_inactive_widgets if theme was switched. if ( $this->is_theme_switch() ) { return; } // Treat inactive sidebar a bit differently. if ( ! empty( $moved_to_inactive_ids ) ) { $moved_to_inactive_name = array_map( array( $this, 'get_widget_name' ), $moved_to_inactive_ids ); /** * Helps Sync log that a widgets IDs got moved to in active * * @since 4.9.0 * * @param array $moved_to_inactive_ids, Array of widgets id that moved to inactive id got changed * @param array $moved_to_inactive_names, Array of widgets names that moved to inactive id got changed Since 5.0.0 */ do_action( 'jetpack_widget_moved_to_inactive', $moved_to_inactive_ids, $moved_to_inactive_name ); } elseif ( empty( $moved_to_sidebar ) && empty( $new_value['wp_inactive_widgets'] ) && ! empty( $old_value['wp_inactive_widgets'] ) ) { /** * Helps Sync log that a got cleared from inactive. * * @since 4.9.0 */ do_action( 'jetpack_cleared_inactive_widgets' ); } } /** * Retrieve the theme data for the current or a specific theme. * * @access private * * @param \WP_Theme $theme Theme object. Optional, will default to the current theme. * * @return array Theme data. */ private function get_theme_info( $theme = null ) { $theme_support = array(); // We are trying to get the current theme info. if ( null === $theme ) { $theme = wp_get_theme(); } $theme_support['name'] = $theme->get( 'Name' ); $theme_support['version'] = $theme->get( 'Version' ); $theme_support['slug'] = $theme->get_stylesheet(); $theme_support['uri'] = $theme->get( 'ThemeURI' ); return $theme_support; } /** * Whether we've deleted a theme in the current request. * * @access private * * @return boolean True if this is a theme deletion request, false otherwise. */ private function get_delete_theme_call() { // Intentional usage of `debug_backtrace()` for production needs. // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace $backtrace = debug_backtrace(); $delete_theme_call = null; foreach ( $backtrace as $call ) { if ( isset( $call['function'] ) && 'delete_theme' === $call['function'] ) { $delete_theme_call = $call; break; } } return $delete_theme_call; } /** * Whether we've switched to another theme in the current request. * * @access private * * @return boolean True if this is a theme switch request, false otherwise. */ private function is_theme_switch() { return did_action( 'after_switch_theme' ); } /** * Return Total number of objects. * * @param array $config Full Sync config. * * @return int total */ public function total( $config ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable return 1; } }