PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.84
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.84
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
wp-data-access / WPDataAccess / Dashboard / WPDA_Widget.php

WPDA_Widget.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.84, at WPDataAccess/Dashboard/WPDA_Widget.php

379 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- verified on page
4 namespace WPDataAccess\Dashboard;
5
6 use WPDataAccess\WPDA;
7 /**
8 * Abstract widget base class
9 */
10 abstract class WPDA_Widget {
11 /**
12 * Nonce seed
13 */
14 const WIDGET_ADD = 'WPDA_WIDGET_ADD';
15
16 /**
17 * Nonce seed
18 */
19 const WIDGET_REFRESH = 'WPDA_WIDGET_REFRESH';
20
21 /**
22 * Widget sequence number
23 *
24 * @var int
25 */
26 protected static $widget_sequence_nr = 0;
27
28 /**
29 * Active column number
30 *
31 * @var int|mixed
32 */
33 protected $column = 1;
34
35 /**
36 * Share indicator
37 *
38 * @var bool
39 */
40 protected $can_share = false;
41
42 /**
43 * Layout indicator
44 *
45 * @var bool
46 */
47 protected $has_layout = false;
48
49 /**
50 * Settings indicator
51 *
52 * @var bool
53 */
54 protected $has_setting = false;
55
56 /**
57 * Refresh indicator
58 *
59 * @var bool
60 */
61 protected $can_refresh = false;
62
63 /**
64 * Widget name
65 *
66 * @var mixed|string
67 */
68 protected $name = 'No name';
69
70 /**
71 * Widget title
72 *
73 * @var mixed|string
74 */
75 protected $title = 'No title';
76
77 /**
78 * Widget content
79 *
80 * @var mixed|string
81 */
82 protected $content = 'Loading...';
83
84 /**
85 * Nonce
86 *
87 * @var null
88 */
89 protected $wp_nonce = null;
90
91 /**
92 * Current widget id
93 *
94 * @var int|mixed
95 */
96 protected $widget_id = 0;
97
98 /**
99 * Widget positioning
100 *
101 * @var string
102 */
103 protected $position = 'append';
104
105 /**
106 * Current state
107 *
108 * @var mixed|string|null
109 */
110 protected $state = null;
111
112 /**
113 * Lock indicator
114 *
115 * @var bool
116 */
117 protected $is_locked = false;
118
119 /**
120 * Widget shares
121 *
122 * @var array
123 */
124 protected $share = array(
125 'post' => 'true',
126 'page' => 'true',
127 'embed' => 'block',
128 'allow' => array(),
129 );
130
131 /**
132 * Constructor
133 *
134 * @param array $args Constructor arguments.
135 */
136 public function __construct( $args = array() ) {
137 wp_enqueue_script( 'jquery-ui-widget' );
138 if ( isset( $args['name'] ) ) {
139 $this->name = $args['name'];
140 }
141 if ( isset( $args['column'] ) ) {
142 $this->column = $args['column'];
143 }
144 if ( isset( $args['title'] ) ) {
145 $this->title = $args['title'];
146 }
147 if ( isset( $args['content'] ) ) {
148 $this->content = $args['content'];
149 }
150 if ( isset( $args['position'] ) && 'prepend' === $args['position'] ) {
151 $this->position = 'prepend';
152 }
153 if ( isset( $args['widget_id'] ) ) {
154 $this->widget_id = $args['widget_id'];
155 // Used to add widgets via ajax.
156 } else {
157 $this->widget_id = ++self::$widget_sequence_nr;
158 // Used to add widgets on page load.
159 }
160 if ( isset( $args['is_locked'] ) ) {
161 $this->is_locked = true === $args['is_locked'] || 'true' === $args['is_locked'];
162 }
163 if ( isset( $args['share'] ) && isset(
164 $args['share']['roles'],
165 $args['share']['users'],
166 $args['share']['post'],
167 $args['share']['page'],
168 $args['share']['embed'],
169 $args['share']['allow']
170 ) ) {
171 $this->share = array(
172 'roles' => $args['share']['roles'],
173 'users' => $args['share']['users'],
174 'post' => $args['share']['post'],
175 'page' => $args['share']['page'],
176 'embed' => $args['share']['embed'],
177 'allow' => $args['share']['allow'],
178 );
179 }
180 $this->state = ( isset( $args['state'] ) ? $args['state'] : 'new' );
181 $this->wp_nonce = wp_create_nonce( static::WIDGET_REFRESH . WPDA::get_current_user_login() );
182 }
183
184 /**
185 * Construct widget container
186 *
187 * @return false|string
188 */
189 protected function container() {
190 ob_start();
191 ?>
192 <script type="application/javascript" class="wpda-widget-<?php
193 echo esc_attr( $this->widget_id );
194 ?>">
195 jQuery(function() {
196 var widget = `<?php
197 // phpcs:disable WordPress.Security.EscapeOutput
198 echo $this->html();
199 // phpcs:enable WordPress.Security.EscapeOutput
200 ?>`;
201
202 jQuery("#wpda-dashboard-column-<?php
203 echo esc_attr( $this->column );
204 ?>").<?php
205 echo esc_attr( $this->position );
206 ?>(widget);
207 jQuery("#wpda-widget-<?php
208 echo esc_attr( $this->widget_id );
209 ?>").data("name", "<?php
210 echo esc_attr( $this->name );
211 ?>" );
212
213 jQuery("#wpda-widget-<?php
214 echo esc_attr( $this->widget_id );
215 ?> .wpda-widget-close").on("click", function() {
216 removePanelFromDashboard(jQuery(this).closest('.wpda-widget'));
217 });
218 });
219 </script>
220 <?php
221 $this->js();
222 return ob_get_clean();
223 }
224
225 /**
226 * Construct widget html
227 *
228 * @return string
229 */
230 protected function html() {
231 $share = '';
232 $layout = '';
233 $setting = '';
234 $refresh = ( $this->can_refresh ? "<i class='fas fa-sync-alt wpda-widget-refresh wpda_tooltip' title='Refresh'></i> &nbsp;" : '' );
235 $close = ( !$this->is_locked ? '<i class="fas fa-window-close wpda-widget-close wpda_tooltip" title="Close"></i>' : '' );
236 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
237 $widget = <<<EOF
238 <div id="wpda-widget-{$this->widget_id}" data-id="{$this->widget_id}" class="wpda-widget ui-widget">
239 <div class="wpda-widget-content">
240 <div class="ui-widget-header">
241 <span>{$this->name}</span>
242 <span class="icons">
243 \t\t\t\t\t\t\t\t{$share}
244 \t\t\t\t\t\t\t\t{$layout}
245 \t\t\t\t\t\t\t\t{$setting}
246 \t\t\t\t\t\t\t\t{$refresh}
247 \t\t\t\t\t\t\t\t{$close}
248 \t\t\t\t\t\t\t</span>
249 </div>
250 <div class="ui-widget-content">
251 {$this->content}
252 </div>
253 </div>
254 </div>
255 EOF;
256 return $widget;
257 }
258
259 /**
260 * Cross origin check
261 *
262 * @param WPDA_Widget $widget Widget.
263 * @return bool
264 */
265 protected static function check_cors( $widget ) {
266 if ( isset( $_POST['wpda_caller'] ) && 'embedded' === $_POST['wpda_caller'] ) {
267 $share = ( isset( $widget['widgetShare'] ) ? $widget['widgetShare'] : null );
268 if ( 'block' === $share['embed'] ) {
269 WPDA::sent_header( 'application/json', '*' );
270 // phpcs:disable WordPress.Security.EscapeOutput
271 echo static::msg( 'ERROR', 'No access' );
272 // phpcs:enable WordPress.Security.EscapeOutput
273 wp_die();
274 } else {
275 if ( '*' === $share['embed'] ) {
276 WPDA::sent_header( 'application/json', '*' );
277 return true;
278 } else {
279 // Access is already checked with sonce token.
280 WPDA::sent_header( 'application/json', '*' );
281 return true;
282 }
283 }
284 }
285 return false;
286 }
287
288 /**
289 * Abstract method forcing each subclass to add its own specific javascript code
290 *
291 * @return mixed
292 */
293 protected abstract function js();
294
295 // Method to add custom JavaScript code.
296 /**
297 * Add widget to dashboard
298 *
299 * @return void
300 */
301 public function add() {
302 // phpcs:disable WordPress.Security.EscapeOutput
303 echo $this->container();
304 // phpcs:enable WordPress.Security.EscapeOutput
305 ?>
306 <script type="application/javascript">
307 jQuery(function() {
308 increaseWidgetSequenceNr();
309 });
310 </script>
311 <?php
312 }
313
314 /**
315 * Abstract widget method forcing each subclass to implement its own specific widget functionality
316 *
317 * @return mixed
318 */
319 public static abstract function widget();
320
321 /**
322 * Construct widget via ajax (general part used for each widget)
323 *
324 * @return void
325 */
326 public static function ajax_widget() {
327 $wp_nonce = ( isset( $_POST['wp_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_nonce'] ) ) : '' );
328 if ( !wp_verify_nonce( $wp_nonce, static::WIDGET_ADD . WPDA::get_current_user_login() ) ) {
329 WPDA::sent_header( 'application/json' );
330 // phpcs:disable WordPress.Security.EscapeOutput
331 echo static::msg( 'ERROR', 'Token expired, please refresh page' );
332 // phpcs:enable WordPress.Security.EscapeOutput
333 wp_die();
334 }
335 static::widget();
336 }
337
338 /**
339 * Abstract refresh method forcing each subclass to implement its own specific refresh functionality
340 *
341 * @return mixed
342 */
343 public static abstract function refresh();
344
345 /**
346 * Refresh widget via ajax (general part used for each widget)
347 *
348 * @return void
349 */
350 public static function ajax_refresh() {
351 $wp_nonce = ( isset( $_POST['wp_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_nonce'] ) ) : '' );
352 if ( !wp_verify_nonce( $wp_nonce, static::WIDGET_REFRESH . WPDA::get_current_user_login() ) ) {
353 WPDA::sent_header( 'application/json' );
354 // phpcs:disable WordPress.Security.EscapeOutput
355 echo static::msg( 'ERROR', 'Token expired, please refresh page' );
356 // phpcs:enable WordPress.Security.EscapeOutput
357 wp_die();
358 }
359 static::refresh();
360 }
361
362 /**
363 * Construct JSON response message
364 *
365 * @param string $status Response status.
366 * @param string $msg Response message.
367 * @return mixed
368 */
369 protected static function msg( $status, $msg ) {
370 $error = array(
371 'status' => esc_attr( $status ),
372 'msg' => $msg,
373 );
374 return wp_json_encode( $error );
375 }
376
377 }
378
379 // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing