PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
mainwp / class / class-mainwp-ui-manage-widgets-layout.php

class-mainwp-ui-manage-widgets-layout.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.1, at class/class-mainwp-ui-manage-widgets-layout.php

293 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Manage MainWP UI Widget Layouts.
4 *
5 * Handles saving, loading, and deleting custom widget layout configurations
6 * for dashboard pages. Allows users to save their preferred widget arrangements.
7 *
8 * @package MainWP/Dashboard
9 */
10
11 namespace MainWP\Dashboard;
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /**
19 * Class MainWP_Ui_Manage_Widgets_Layout
20 *
21 * Manages custom widget layout configurations with save/load/delete functionality.
22 *
23 * @package MainWP\Dashboard
24 */
25 class MainWP_Ui_Manage_Widgets_Layout { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
26
27 /**
28 * Singleton instance of the class.
29 *
30 * @static
31 *
32 * @var MainWP_Ui_Manage_Widgets_Layout|null
33 */
34 private static $instance = null;
35
36 /**
37 * Get the singleton instance of the class.
38 *
39 * @static
40 *
41 * @return MainWP_Ui_Manage_Widgets_Layout Singleton instance.
42 */
43 public static function get_instance() {
44 if ( null === static::$instance ) {
45 static::$instance = new self();
46 }
47 return static::$instance;
48 }
49
50 /**
51 * Constructor.
52 *
53 * Public constructor to enforce singleton pattern.
54 */
55 public function __construct() {
56 }
57
58 /**
59 * Initialize admin hooks.
60 *
61 * Registers AJAX handlers for save, load, and delete layout operations.
62 *
63 * @return void
64 */
65 public function admin_init() {
66 MainWP_Post_Handler::instance()->add_action( 'mainwp_ui_save_widgets_layout', array( $this, 'ajax_save_widgets_layout' ) );
67 MainWP_Post_Handler::instance()->add_action( 'mainwp_ui_load_widgets_layout', array( $this, 'ajax_load_widgets_layout' ) );
68 MainWP_Post_Handler::instance()->add_action( 'mainwp_ui_delete_widgets_layout', array( $this, 'ajax_delete_widgets_layout' ) );
69 }
70
71 /**
72 * Render layout management UI controls.
73 *
74 * Outputs the layout dropdown button and JavaScript handlers for managing
75 * widget layout configurations on the current screen.
76 *
77 * @param string $screen_id Current screen identifier.
78 *
79 * @return void
80 */
81 public static function render_edit_layout( $screen_id ) {
82 $screen_slug = strtolower( $screen_id );
83 $saved_segments = static::set_get_widgets_layout( false, array(), $screen_slug );
84 ?>
85
86 <div class="ui mini basic top left pointing dropdown button mainwp-768-hide">
87 <div><i class="border all icon"></i><span class="mainwp-768-hide"><?php esc_html_e( 'Layout', 'mainwp' ); ?></span></div>
88 <div class="menu">
89 <a class="item" id="mainwp-manage-widgets-load-saved-layout-button" selected-layout-id="" settings-slug="<?php echo esc_attr( $screen_slug ); ?>"><?php esc_html_e( 'Save Layout', 'mainwp' ); ?></a>
90 <?php if ( ! empty( $saved_segments ) ) : ?>
91 <a class="item" id="mainwp-manage-widgets-ui-choose-layout"><?php esc_html_e( 'Load Layout', 'mainwp' ); ?></a>
92 <?php endif; ?>
93 </div>
94 </div>
95
96 <script type="text/javascript">
97 jQuery( document ).ready( function() {
98 mainwp_init_widget_layout_handlers();
99 } );
100 </script>
101 <?php
102 }
103
104 /**
105 * Get or set widget layout configurations for a screen.
106 *
107 * Retrieves or saves widget layout configurations stored in user meta.
108 * Each screen can have multiple saved layouts identified by unique IDs.
109 *
110 * @param bool $set_val Whether to set (true) or get (false) the value.
111 * @param array $saved_segments Array of layout configurations to save (when $set_val is true).
112 * @param string $save_field Screen identifier for the layout (e.g., 'overview', 'sites').
113 *
114 * @return array Array of saved layout configurations, empty array if none exist.
115 */
116 public static function set_get_widgets_layout( $set_val = false, $saved_segments = array(), $save_field = 'overview' ) {
117 global $current_user;
118
119 $field = 'mainwp_' . sanitize_text_field( $save_field ) . '_widgets_saved_layout';
120
121 if ( $current_user && ! empty( $current_user->ID ) ) {
122 if ( $set_val ) {
123 update_user_option( $current_user->ID, $field, $saved_segments );
124 } else {
125 $values = get_user_option( $field, array() );
126 if ( ! is_array( $values ) ) {
127 $values = array();
128 }
129 return $values;
130 }
131 }
132 return array();
133 }
134
135
136 /**
137 * AJAX handler to save widget layout configuration.
138 *
139 * Processes POST request to save the current widget layout arrangement.
140 * Validates nonce, sanitizes input, and stores layout in user meta.
141 *
142 * @since 5.0.0
143 *
144 * @return void Outputs JSON response with 'result' => 'SUCCESS' or error.
145 */
146 public function ajax_save_widgets_layout() { //phpcs:ignore -- NOSONAR - complex.
147 MainWP_Post_Handler::instance()->check_security( 'mainwp_ui_save_widgets_layout' );
148 //phpcs:disable WordPress.Security.NonceVerification.Missing
149
150 $seg_id = ! empty( $_POST['seg_id'] ) ? sanitize_text_field( wp_unslash( $_POST['seg_id'] ) ) : time();
151 $wgids = is_array( $_POST['wgids'] ) ? $_POST['wgids'] : array(); // phpcs:ignore -- NOSONAR - ok.
152 $items = is_array( $_POST['order'] ) ? $_POST['order'] : array(); // phpcs:ignore -- NOSONAR - ok.
153
154 $slug = isset( $_POST['settings_slug'] ) ? sanitize_text_field( wp_unslash($_POST['settings_slug'] )) : 'overview'; // phpcs:ignore -- NOSONAR - ok.
155
156 if ( empty( $slug ) ) {
157 $slug = 'overview';
158 }
159
160 $layout_items = array();
161 if ( is_array( $wgids ) && is_array( $items ) ) {
162 foreach ( $wgids as $idx => $wgid ) {
163 if ( isset( $items[ $idx ] ) ) {
164 $pre = 'widget-'; // compatible with #compatible-widgetid.
165 if ( 0 === strpos( $wgid, $pre ) ) {
166 $wgid = substr( $wgid, strlen( $pre ) );
167 }
168 $layout_items[ $wgid ] = $items[ $idx ];
169 }
170 }
171 }
172
173 $save_layout = array(
174 'name' => isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : 'N/A',
175 'layout' => $layout_items,
176 );
177
178 //phpcs:enable WordPress.Security.NonceVerification.Missing
179
180 $saved_segments = static::set_get_widgets_layout( false, array(), $slug );
181 if ( ! is_array( $saved_segments ) ) {
182 $saved_segments = array();
183 }
184 $saved_segments[ $seg_id ] = $save_layout;
185 static::set_get_widgets_layout( true, $saved_segments, $slug );
186 die( wp_json_encode( array( 'result' => 'SUCCESS' ) ) );
187 }
188
189
190 /**
191 * AJAX handler to load saved widget layouts.
192 *
193 * Retrieves all saved widget layout configurations for the current screen
194 * and returns them as a dropdown select element HTML.
195 *
196 * @since 5.0.0
197 *
198 * @return void Outputs JSON response with 'result' containing HTML dropdown or empty string.
199 */
200 public function ajax_load_widgets_layout() {
201 MainWP_Post_Handler::instance()->check_security( 'mainwp_ui_load_widgets_layout' );
202 $slug = isset( $_POST['settings_slug'] ) ? sanitize_text_field( wp_unslash($_POST['settings_slug'] )) : 'overview'; // phpcs:ignore -- NOSONAR - ok.
203 if ( empty( $slug ) ) {
204 $slug = 'overview';
205 }
206 $saved_segments = static::set_get_widgets_layout( false, array(), $slug );
207 $list_segs = '';
208 if ( is_array( $saved_segments ) && ! empty( $saved_segments ) ) {
209 $list_segs .= '<select id="mainwp-edit-layout-filters" class="ui fluid dropdown">';
210 $list_segs .= '<option value="">' . esc_html__( 'Select layout', 'mainwp' ) . '</option>';
211 foreach ( $saved_segments as $sid => $values ) {
212 if ( empty( $values['name'] ) ) {
213 continue;
214 }
215 $list_segs .= '<option value="' . esc_attr( $sid ) . '">' . esc_html( $values['name'] ) . '</option>';
216 }
217 $list_segs .= '</select>';
218 }
219 die( wp_json_encode( array( 'result' => $list_segs ) ) ); //phpcs:ignore -- ok.
220 }
221
222 /**
223 * AJAX handler to delete a saved widget layout.
224 *
225 * Removes a specific layout configuration from user meta by layout ID.
226 * Validates nonce and layout existence before deletion.
227 *
228 * @since 5.0.0
229 *
230 * @return void Outputs JSON response with 'result' => 'SUCCESS' or 'error' message.
231 */
232 public function ajax_delete_widgets_layout() {
233 MainWP_Post_Handler::instance()->check_security( 'mainwp_ui_delete_widgets_layout' );
234 $seg_id = ! empty( $_POST['seg_id'] ) ? sanitize_text_field( wp_unslash( $_POST['seg_id'] ) ) : 0; //phpcs:ignore -- ok.
235 $slug = ! empty( $_POST['settings_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['settings_slug'] ) ) : 'overview'; //phpcs:ignore -- ok.
236
237 $saved_segments = static::set_get_widgets_layout( false, array(), $slug );
238 if ( ! empty( $seg_id ) && is_array( $saved_segments ) && isset( $saved_segments[ $seg_id ] ) ) {
239 unset( $saved_segments[ $seg_id ] );
240 static::set_get_widgets_layout( true, $saved_segments, $slug );
241 die( wp_json_encode( array( 'result' =>'SUCCESS' ) ) ); //phpcs:ignore -- ok.
242 }
243 die( wp_json_encode( array( 'error' => esc_html__( 'Layout not found. Please try again.', 'mainwp' ) ) ) ); //phpcs:ignore -- ok.
244 }
245
246 /**
247 * Render the layout management modal dialog.
248 *
249 * Outputs HTML for the modal window used to save, load, and delete
250 * widget layout configurations. Includes form fields and action buttons.
251 *
252 * @since 5.0.0
253 *
254 * @return void
255 */
256 public static function render_modal_save_layout() {
257 ?>
258 <div id="mainwp-common-edit-widgets-layout-modal" class="ui tiny modal">
259 <i class="close icon" id="mainwp-common-filter-layout-cancel"></i>
260 <div class="header"><?php esc_html_e( 'Save Layout', 'mainwp' ); ?></div>
261 <div class="content" id="mainwp-common-widgets-layout-content">
262 <div id="mainwp-common-edit-widgets-layout-status" class="ui message" style="display:none;"></div>
263 <div id="mainwp-common-edit-widgets-layout-edit-fields" class="ui form">
264 <div class="field">
265 <label><?php esc_html_e( 'Layout name', 'mainwp' ); ?></label>
266 </div>
267 <div class="field">
268 <input type="text" id="mainwp-common-edit-widgets-layout-name" value=""/>
269 </div>
270 </div>
271 <div id="mainwp-common-layout-widgets-select-fields" style="display:none;">
272 <div class="field">
273 <div id="mainwp-common-edit-widgets-layout-lists-wrapper"></div>
274 </div>
275 </div>
276 </div>
277 <div class="actions">
278 <div class="ui grid">
279 <div class="eight wide left aligned middle aligned column">
280
281 </div>
282 <div class="eight wide column">
283 <input type="button" class="ui green mini button disabled" id="mainwp-common-edit-widgets-layout-save-button" value="<?php esc_attr_e( 'Save Layout', 'mainwp' ); ?>"/>
284 <input type="button" class="ui green mini button disabled" id="mainwp-common-edit-widgets-select-layout-button" value="<?php esc_attr_e( 'Choose Layout', 'mainwp' ); ?>" style="display:none;"/>
285 <input type="button" class="ui basic mini button disabled" id="mainwp-common-edit-widgets-layout-delete-button" value="<?php esc_attr_e( 'Delete', 'mainwp' ); ?>" style="display:none;"/>
286 </div>
287 </div>
288 </div>
289 </div>
290 <?php
291 }
292 }
293