PluginProbe
UpStream: a Project Management Plugin for WordPress / 2.1.0
UpStream: a Project Management Plugin for WordPress v2.1.0
trunk 1.39.0 1.39.1 1.39.2 1.39.3 2.0.7 2.1.0
upstream / includes / admin / class-upstream-admin-pointers.php

class-upstream-admin-pointers.php in UpStream: a Project Management Plugin for WordPress 2.1.0, at includes/admin/class-upstream-admin-pointers.php

516 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Adds and controls pointers for contextual help/tutorials
4 *
5 * @package UpStream
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * UpStream_Admin_Pointers Class.
14 */
15 class UpStream_Admin_Pointers {
16
17 /**
18 * Constructor.
19 */
20 public function __construct() {
21 add_filter( 'admin_notices', array( $this, 'first_project' ) );
22 add_filter( 'admin_notices', array( $this, 'check_addons' ) );
23 add_filter( 'upstream_admin_pointers-project', array( $this, 'register_pointers' ) );
24 add_filter( 'upstream_admin_pointers-edit-project', array( $this, 'register_signup' ) );
25 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_pointers' ) );
26 }
27
28 /**
29 * Register Signup
30 *
31 * @return void
32 */
33 public function register_signup() {
34 if ( ! current_user_can( 'administrator' ) ) {
35 return;
36 }
37
38 global $current_user;
39
40 $content = '<p id="upstream-pointer-signup-box">';
41 $content .= __( 'Sign up for our UpStream Project Management tips and tricks newsletter and get the UpStream Customizer extension for free!', 'upstream' ) . '<br /><br />';
42 $content .= '<label>';
43 $content .= '<b>' . __( 'Email Address:', 'upstream' ) . '</b>';
44 $content .= '<br />';
45 $content .= '<input type="text" id="upstream-pointer-email" value="' . esc_attr( $current_user->user_email ) . '" />';
46 $content .= '</label>';
47 $content .= '&nbsp; <a id="upstream-pointer-b1" onclick="return window.upstream_signup(this);" data-nonce="' . wp_create_nonce( 'upstream_signup' ) . '" class="button button-primary">Sign up</a>';
48 $content .= '</p>';
49
50 $pointers = array(
51 'signup-newsletter-email3' => array(
52 'target' => '.wp-heading-inline',
53 'options' => array(
54 'content' => '<h3>' . __( 'Get a FREE UpStream extension!' ) . '</h3>' . $content,
55 'position' => array(
56 'edge' => 'top',
57 'align' => 'top',
58 ),
59 ),
60 ),
61
62 );
63
64 return $pointers;
65 }
66
67 /**
68 * First Project
69 *
70 * @return void
71 */
72 public function first_project() {
73 // Make sure First Steps tutorial are not shown to Client Users first time they enter a project.
74 $user = wp_get_current_user();
75 if ( count( array_intersect( (array) $user->roles, array( 'administrator', 'upstream_manager' ) ) ) === 0 &&
76 ! current_user_can( 'edit_projects' )
77 ) {
78 return;
79 }
80
81 // Get dismissed pointers. Shows whether we have done this or not already.
82 $dismissed = explode( ',', (string) get_user_meta( $user->ID, 'dismissed_wp_pointers', true ) );
83 if ( in_array( 'upstream_title', $dismissed ) ) {
84 return;
85 }
86
87 $screen = get_current_screen();
88 if ( isset( $screen->id ) && 'project' === $screen->id ) {
89 $class = 'notice notice-success is-dismissible';
90 $message = '<strong>' . __( 'Important!', 'upstream' ) . '</strong><br>';
91 $message .= __(
92 'As this is your first project, we have included a walkthrough guide.',
93 'upstream'
94 ) . '<br>';
95 $message .= __(
96 'We <strong>strongly recommend</strong> that you take the time to follow it. ',
97 'upstream'
98 );
99 $message .= __(
100 'There is important info in the guide and it does not take too long.',
101 'upstream'
102 ) . '<br>';
103 $message .= '<small>' . __( '(you won\'t see this message or the guide again)', 'upstream' ) . '</small>';
104
105 printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), wp_kses_post( $message ) );
106 }
107 }
108
109 /**
110 * Check Addons
111 *
112 * @return void
113 */
114 public function check_addons() {
115 $user = wp_get_current_user();
116 if ( ! is_admin() || ! current_user_can( 'activate_plugins' ) ) {
117 return;
118 }
119
120 // only check if it is set.
121 if ( isset( $_GET['upstream_dismiss_ver'] ) ) {
122 update_user_meta( get_current_user_id(), 'upstream_hide_incompat_notices_' . UPSTREAM_VERSION, 'yes' );
123 }
124
125 if ( get_user_meta( get_current_user_id(), 'upstream_hide_incompat_notices_' . UPSTREAM_VERSION, true ) === 'yes' ) {
126 return;
127 }
128
129 $addon_problems = array();
130 global $upstream_addon_requirements;
131 $required_addon_versions = $upstream_addon_requirements;
132
133 foreach ( $required_addon_versions as $r ) {
134
135 $pd = null;
136 if ( @is_plugin_active( $r[0] ) ) {
137 $pd = @get_plugin_data( WP_PLUGIN_DIR . '/' . $r[0] );
138 } elseif ( @is_plugin_active( strtolower( $r[0] ) ) ) {
139 $pd = @get_plugin_data( WP_PLUGIN_DIR . '/' . strtolower( $r[0] ) );
140 }
141
142 if ( $pd && ! empty( $pd['Name'] ) ) {
143
144 $current_version = $pd['Version'];
145 $reqd_version = $r[1];
146
147 if ( version_compare( $current_version, $reqd_version ) < 0 ) {
148 $addon_problems[] = __( '- The installed version of ', 'upstream' ) .
149 '<b style="font-weight: bold">' . $pd['Name'] . '</b>' . __( ' is ', 'upstream' ) . '<b style="font-weight: bold">' . $current_version . '</b>' .
150 __( '. This version of UpStream requires version ', 'upstream' ) .
151 '<b style="font-weight: bold">' . $reqd_version . '</b>' . __( ' or later.', 'upstream' );
152 }
153 }
154 }
155
156 if ( count( $addon_problems ) > 0 ) {
157 $class = 'notice';
158 $message = '<strong style="font-weight:bold;font-size:2em;color:#f00">' . __( 'Important!', 'upstream' ) . '</strong><br>';
159 $message .= __(
160 'This version of UpStream is not compatible with the following addon versions:',
161 'upstream'
162 ) . '<ul><li>';
163 $message .= implode( '</li><li>', $addon_problems );
164 $message .= '</li></ul>For help with this message, <a href="https://upstreamplugin.com/docs/updating-upstream-addons/">click here</a>.';
165 $message .= '<br><br><a href="?upstream_dismiss_ver=1">' . __( 'Do not show this message again for this version', 'upstream' ) . '</a>';
166
167 printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), wp_kses_post( $message ) );
168 }
169 }
170
171 /**
172 * Pointers for creating a Project.
173 *
174 * @param mixed $pointers Pointers.
175 */
176 public function register_pointers( $pointers ) {
177 // These pointers will chain - they will not be shown at once.
178 $pointers = array(
179 'upstream_title' => array(
180 'target' => '#title',
181 'next' => 'upstream_status',
182 'next_trigger' => array(
183 'target' => '#title',
184 'event' => 'input',
185 ),
186 'options' => array(
187 'content' => '<h3>' . sprintf(
188 // translators: %s: Project label.
189 __( '%s Name', 'upstream' ),
190 upstream_project_label()
191 ) . '</h3>' .
192 '<p>' . sprintf(
193 // translators: %s: Client label.
194 __(
195 'This is a required field and will be what your %s see on the frontend.',
196 'upstream'
197 ),
198 upstream_client_label()
199 ) . '</p>',
200 'position' => array(
201 'edge' => 'top',
202 'align' => 'left',
203 ),
204 ),
205 ),
206 'upstream_status' => array(
207 'target' => '#_upstream_project_status',
208 'next' => 'upstream_owner',
209 'next_trigger' => array(
210 'target' => '#_upstream_project_status',
211 'event' => 'change blur click',
212 ),
213 'options' => array(
214 'content' => '<h3>' . sprintf(
215 // translators: %s: Status label.
216 __( '%s Status', 'upstream' ),
217 upstream_project_label()
218 ) . '</h3>' .
219 '<p>' . sprintf(
220 // translators: %s: Project label.
221 __( 'Choose a status for this %s.', 'upstream' ),
222 upstream_project_label()
223 ) . '</p>' .
224 '<p>' . sprintf(
225 __( 'Statuses are set within the UpStream Settings.', 'upstream' ),
226 upstream_project_label()
227 ) . '</p>',
228 'position' => array(
229 'edge' => 'right',
230 'align' => 'left',
231 ),
232 ),
233 ),
234 'upstream_owner' => array(
235 'target' => '#_upstream_project_owner',
236 'next' => 'upstream_client',
237 'next_trigger' => array(
238 'target' => '#_upstream_project_owner',
239 'event' => 'change blur click',
240 ),
241 'options' => array(
242 'content' => '<h3>' . sprintf(
243 // translators: %s: Project label.
244 __( '%s Owner', 'upstream' ),
245 upstream_project_label()
246 ) . '</h3>' .
247 '<p>' . sprintf(
248 // translators: %s: Project label.
249 __( 'Choose the owner of this %s.', 'upstream' ),
250 upstream_project_label()
251 ) . '</p>' .
252 '<p>' . __(
253 'Every user who has the Role of UpStream Manager, UpStream User or Administrator appears in this dropdown.',
254 'upstream'
255 ) . '</p>' .
256 '<p>' . sprintf(
257 // translators: %s: Project label.
258 __(
259 'The selected owner will have full access and control of everything within this %s, regardless of their role.',
260 'upstream'
261 ),
262 upstream_project_label()
263 ) . '</p>',
264 'position' => array(
265 'edge' => 'right',
266 'align' => 'left',
267 ),
268 ),
269 ),
270 'upstream_client' => array(
271 'target' => '#_upstream_project_client',
272 'next' => 'upstream_client_users',
273 'next_trigger' => array(
274 'target' => '#_upstream_project_client',
275 'event' => 'change blur click',
276 ),
277 'options' => array(
278 'content' => '<h3>' . sprintf(
279 '%s %s',
280 upstream_project_label(),
281 upstream_client_label()
282 ) . '</h3>' .
283 '<p>' . sprintf(
284 // translators: %1$s: Client label.
285 // translators: %2$s: Project label.
286 __( 'Choose the %1$s of this %2$s.', 'upstream' ),
287 upstream_client_label(),
288 upstream_project_label()
289 ) . '</p>' .
290 '<p>' . sprintf(
291 // translators: %s: Client label.
292 __(
293 'If there are no %s here, you need to add one first by clicking on <strong>New Client</strong> in the sidebar.',
294 'upstream'
295 ),
296 upstream_client_label_plural()
297 ) . '</p>',
298 'position' => array(
299 'edge' => 'right',
300 'align' => 'left',
301 ),
302 ),
303 ),
304 'upstream_client_users' => array(
305 'target' => '.cmb2-id--upstream-project-client-users',
306 'next' => 'upstream_project_start',
307 'next_trigger' => array(
308 'target' => '.cmb2-id--upstream-project-client-users',
309 'event' => 'change blur click',
310 ),
311 'options' => array(
312 'content' => '<h3>' . sprintf(
313 // translators: %s: Client label.
314 __( '%s Users', 'upstream' ),
315 upstream_client_label()
316 ) . '</h3>' .
317 '<p>' . sprintf(
318 // translators: %1$s: Client label.
319 // translators: %2$s: Project label.
320 __(
321 'Tick the %1$s Users who will have access to this %2$s.',
322 'upstream'
323 ),
324 upstream_client_label(),
325 upstream_project_label()
326 ) . '</p>' .
327 '<p>' . sprintf(
328 // translators: %s: Project label.
329 __(
330 'The selected Users can then login using their email address and the password that is set within the %s.',
331 'upstream'
332 ),
333 upstream_client_label()
334 ) . '</p>' .
335 '<p>' . sprintf(
336 // translators: %1$s: Client label plural.
337 // translators: %2$s: Client label.
338 __(
339 'If there are no %1$s Users here, you need to add one first by editing your %2$s',
340 'upstream'
341 ),
342 upstream_client_label_plural(),
343 upstream_client_label()
344 ) . '</p>',
345 'position' => array(
346 'edge' => 'right',
347 'align' => 'left',
348 ),
349 ),
350 ),
351 'upstream_project_start' => array(
352 'target' => '#_upstream_project_start',
353 'next' => 'upstream_milestones',
354 'next_trigger' => array(
355 'target' => '#_upstream_project_end',
356 'event' => 'change blur click',
357 ),
358 'options' => array(
359 'content' => '<h3>' . sprintf(
360 // translators: %s: Project label.
361 __( '%s Dates', 'upstream' ),
362 upstream_project_label()
363 ) . '</h3>' .
364 '<p>' . sprintf(
365 // translators: %s: Project label.
366 __(
367 'Add the projected start and finish dates for this %s.',
368 'upstream'
369 ),
370 upstream_project_label()
371 ) . '</p>',
372 'position' => array(
373 'edge' => 'right',
374 'align' => 'left',
375 ),
376 ),
377 ),
378 'upstream_milestones' => array(
379 'target' => '#_upstream_project_milestones',
380 'options' => array(
381 'content' => '<h3>' . sprintf( '%s', upstream_milestone_label_plural() ) . '</h3>' .
382 '<p>' . sprintf(
383 // translators: %s: upstream_milestone_label_plural.
384 __( 'You can now start to add your %s.', 'upstream' ),
385 upstream_milestone_label_plural()
386 ) . '</p>' .
387 '<p>' . sprintf(
388 // translators: %1$s: upstream_milestone_label_plural.
389 // translators: %2$s: upstream_project_label.
390 // translators: %3$s: upstream_milestone_label_plural.
391 // translators: %4$s: upstream_task_label_plural.
392 __(
393 'Once you\'ve added your %1$s, you should now Publish/Update the %2$s. This ensures that all %3$s will be available within the %4$s.',
394 'upstream'
395 ),
396 upstream_milestone_label_plural(),
397 upstream_project_label(),
398 upstream_milestone_label_plural(),
399 upstream_task_label_plural()
400 ) . '</p>' .
401 '<p>' . sprintf(
402 // translators: %s: upstream_milestone_label_plural.
403 __(
404 'If there are no %s in the dropdown, add them by editing the <strong>UpStream Settings</strong>.',
405 'upstream'
406 ),
407 upstream_milestone_label_plural()
408 ) . '</p>',
409 'position' => array(
410 'edge' => 'bottom',
411 'align' => 'top',
412 ),
413 ),
414 ),
415
416 );
417
418 return $pointers;
419 }
420
421 /**
422 * Enqueue pointers and add script to page.
423 *
424 * @param array $pointers Pointers.
425 */
426 public function enqueue_pointers( $pointers ) {
427 $screen = get_current_screen();
428 $screen_id = $screen->id;
429
430 // Get pointers for this screen.
431 $pointers = apply_filters( 'upstream_admin_pointers-' . $screen_id, array() );
432
433 if ( ! $pointers || ! is_array( $pointers ) ) {
434 return;
435 }
436
437 // Get dismissed pointers.
438 $dismissed = explode(
439 ',',
440 (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true )
441 );
442 $valid_pointers = array();
443
444 // Check pointers and remove dismissed ones.
445 foreach ( $pointers as $pointer_id => $pointer ) {
446
447 // Sanity check.
448 if ( in_array(
449 $pointer_id,
450 $dismissed
451 ) || empty( $pointer ) || empty( $pointer_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) ) {
452 continue;
453 }
454
455 $pointer['pointer_id'] = $pointer_id;
456
457 // Add the pointer to $valid_pointers array.
458 $valid_pointers['pointers'][ $pointer_id ] = $pointer;
459 }
460
461 // No valid pointers? Stop here.
462 if ( empty( $valid_pointers ) ) {
463 return;
464 }
465
466 wp_enqueue_style( 'wp-pointer' );
467 wp_enqueue_script( 'wp-pointer' );
468
469 $valid_pointers = wp_json_encode( $valid_pointers );
470
471 $return = wp_add_inline_script(
472 'wp-pointer',
473 "
474 jQuery( function( $ ) {
475 var wc_pointers = {$valid_pointers};
476
477 setTimeout( init_wc_pointers, 2000 );
478
479 function init_wc_pointers() {
480 $.each( wc_pointers.pointers, function( i ) {
481 show_wc_pointer( i );
482 return false;
483 });
484 }
485
486 function show_wc_pointer( id ) {
487 var pointer = wc_pointers.pointers[ id ];
488
489 var options = $.extend( pointer.options, {
490 close: function() {
491 $.post( ajaxurl, {
492 pointer: pointer.pointer_id,
493 action: 'dismiss-wp-pointer'
494 });
495 if ( pointer.next ) {
496 show_wc_pointer( pointer.next );
497 }
498 }
499 } );
500 var this_pointer = $( pointer.target ).pointer( options );
501 this_pointer.pointer( 'open' );
502
503 if ( pointer.next_trigger ) {
504 $( pointer.next_trigger.target ).on( pointer.next_trigger.event, function() {
505 setTimeout( function() { this_pointer.pointer( 'close' ); }, 400 );
506 });
507 }
508 }
509 });
510 "
511 );
512 }
513 }
514
515 new UpStream_Admin_Pointers();
516