'; $content .= __( 'Sign up for our UpStream Project Management tips and tricks newsletter and get the UpStream Customizer extension for free!', 'upstream' ) . '

'; $content .= ''; $content .= '  Sign up'; $content .= '

'; $pointers = array( 'signup-newsletter-email3' => array( 'target' => '.wp-heading-inline', 'options' => array( 'content' => '

' . __( 'Get a FREE UpStream extension!' ) . '

' . $content, 'position' => array( 'edge' => 'top', 'align' => 'top', ), ), ), ); return $pointers; } /** * First Project * * @return void */ public function first_project() { // Make sure First Steps tutorial are not shown to Client Users first time they enter a project. $user = wp_get_current_user(); if ( count( array_intersect( (array) $user->roles, array( 'administrator', 'upstream_manager' ) ) ) === 0 && ! current_user_can( 'edit_projects' ) ) { return; } // Get dismissed pointers. Shows whether we have done this or not already. $dismissed = explode( ',', (string) get_user_meta( $user->ID, 'dismissed_wp_pointers', true ) ); if ( in_array( 'upstream_title', $dismissed ) ) { return; } $screen = get_current_screen(); if ( isset( $screen->id ) && 'project' === $screen->id ) { $class = 'notice notice-success is-dismissible'; $message = '' . __( 'Important!', 'upstream' ) . '
'; $message .= __( 'As this is your first project, we have included a walkthrough guide.', 'upstream' ) . '
'; $message .= __( 'We strongly recommend that you take the time to follow it. ', 'upstream' ); $message .= __( 'There is important info in the guide and it does not take too long.', 'upstream' ) . '
'; $message .= '' . __( '(you won\'t see this message or the guide again)', 'upstream' ) . ''; printf( '

%2$s

', esc_attr( $class ), wp_kses_post( $message ) ); } } /** * Check Addons * * @return void */ public function check_addons() { $user = wp_get_current_user(); if ( ! is_admin() || ! current_user_can( 'activate_plugins' ) ) { return; } // only check if it is set. if ( isset( $_GET['upstream_dismiss_ver'] ) ) { update_user_meta( get_current_user_id(), 'upstream_hide_incompat_notices_' . UPSTREAM_VERSION, 'yes' ); } if ( get_user_meta( get_current_user_id(), 'upstream_hide_incompat_notices_' . UPSTREAM_VERSION, true ) === 'yes' ) { return; } $addon_problems = array(); global $upstream_addon_requirements; $required_addon_versions = $upstream_addon_requirements; foreach ( $required_addon_versions as $r ) { $pd = null; if ( @is_plugin_active( $r[0] ) ) { $pd = @get_plugin_data( WP_PLUGIN_DIR . '/' . $r[0] ); } elseif ( @is_plugin_active( strtolower( $r[0] ) ) ) { $pd = @get_plugin_data( WP_PLUGIN_DIR . '/' . strtolower( $r[0] ) ); } if ( $pd && ! empty( $pd['Name'] ) ) { $current_version = $pd['Version']; $reqd_version = $r[1]; if ( version_compare( $current_version, $reqd_version ) < 0 ) { $addon_problems[] = __( '- The installed version of ', 'upstream' ) . '' . $pd['Name'] . '' . __( ' is ', 'upstream' ) . '' . $current_version . '' . __( '. This version of UpStream requires version ', 'upstream' ) . '' . $reqd_version . '' . __( ' or later.', 'upstream' ); } } } if ( count( $addon_problems ) > 0 ) { $class = 'notice'; $message = '' . __( 'Important!', 'upstream' ) . '
'; $message .= __( 'This version of UpStream is not compatible with the following addon versions:', 'upstream' ) . 'For help with this message, click here.'; $message .= '

' . __( 'Do not show this message again for this version', 'upstream' ) . ''; printf( '

%2$s

', esc_attr( $class ), wp_kses_post( $message ) ); } } /** * Pointers for creating a Project. * * @param mixed $pointers Pointers. */ public function register_pointers( $pointers ) { // These pointers will chain - they will not be shown at once. $pointers = array( 'upstream_title' => array( 'target' => '#title', 'next' => 'upstream_status', 'next_trigger' => array( 'target' => '#title', 'event' => 'input', ), 'options' => array( 'content' => '

' . sprintf( // translators: %s: Project label. __( '%s Name', 'upstream' ), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Client label. __( 'This is a required field and will be what your %s see on the frontend.', 'upstream' ), upstream_client_label() ) . '

', 'position' => array( 'edge' => 'top', 'align' => 'left', ), ), ), 'upstream_status' => array( 'target' => '#_upstream_project_status', 'next' => 'upstream_owner', 'next_trigger' => array( 'target' => '#_upstream_project_status', 'event' => 'change blur click', ), 'options' => array( 'content' => '

' . sprintf( // translators: %s: Status label. __( '%s Status', 'upstream' ), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Project label. __( 'Choose a status for this %s.', 'upstream' ), upstream_project_label() ) . '

' . '

' . sprintf( __( 'Statuses are set within the UpStream Settings.', 'upstream' ), upstream_project_label() ) . '

', 'position' => array( 'edge' => 'right', 'align' => 'left', ), ), ), 'upstream_owner' => array( 'target' => '#_upstream_project_owner', 'next' => 'upstream_client', 'next_trigger' => array( 'target' => '#_upstream_project_owner', 'event' => 'change blur click', ), 'options' => array( 'content' => '

' . sprintf( // translators: %s: Project label. __( '%s Owner', 'upstream' ), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Project label. __( 'Choose the owner of this %s.', 'upstream' ), upstream_project_label() ) . '

' . '

' . __( 'Every user who has the Role of UpStream Manager, UpStream User or Administrator appears in this dropdown.', 'upstream' ) . '

' . '

' . sprintf( // translators: %s: Project label. __( 'The selected owner will have full access and control of everything within this %s, regardless of their role.', 'upstream' ), upstream_project_label() ) . '

', 'position' => array( 'edge' => 'right', 'align' => 'left', ), ), ), 'upstream_client' => array( 'target' => '#_upstream_project_client', 'next' => 'upstream_client_users', 'next_trigger' => array( 'target' => '#_upstream_project_client', 'event' => 'change blur click', ), 'options' => array( 'content' => '

' . sprintf( '%s %s', upstream_project_label(), upstream_client_label() ) . '

' . '

' . sprintf( // translators: %1$s: Client label. // translators: %2$s: Project label. __( 'Choose the %1$s of this %2$s.', 'upstream' ), upstream_client_label(), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Client label. __( 'If there are no %s here, you need to add one first by clicking on New Client in the sidebar.', 'upstream' ), upstream_client_label_plural() ) . '

', 'position' => array( 'edge' => 'right', 'align' => 'left', ), ), ), 'upstream_client_users' => array( 'target' => '.cmb2-id--upstream-project-client-users', 'next' => 'upstream_project_start', 'next_trigger' => array( 'target' => '.cmb2-id--upstream-project-client-users', 'event' => 'change blur click', ), 'options' => array( 'content' => '

' . sprintf( // translators: %s: Client label. __( '%s Users', 'upstream' ), upstream_client_label() ) . '

' . '

' . sprintf( // translators: %1$s: Client label. // translators: %2$s: Project label. __( 'Tick the %1$s Users who will have access to this %2$s.', 'upstream' ), upstream_client_label(), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Project label. __( 'The selected Users can then login using their email address and the password that is set within the %s.', 'upstream' ), upstream_client_label() ) . '

' . '

' . sprintf( // translators: %1$s: Client label plural. // translators: %2$s: Client label. __( 'If there are no %1$s Users here, you need to add one first by editing your %2$s', 'upstream' ), upstream_client_label_plural(), upstream_client_label() ) . '

', 'position' => array( 'edge' => 'right', 'align' => 'left', ), ), ), 'upstream_project_start' => array( 'target' => '#_upstream_project_start', 'next' => 'upstream_milestones', 'next_trigger' => array( 'target' => '#_upstream_project_end', 'event' => 'change blur click', ), 'options' => array( 'content' => '

' . sprintf( // translators: %s: Project label. __( '%s Dates', 'upstream' ), upstream_project_label() ) . '

' . '

' . sprintf( // translators: %s: Project label. __( 'Add the projected start and finish dates for this %s.', 'upstream' ), upstream_project_label() ) . '

', 'position' => array( 'edge' => 'right', 'align' => 'left', ), ), ), 'upstream_milestones' => array( 'target' => '#_upstream_project_milestones', 'options' => array( 'content' => '

' . sprintf( '%s', upstream_milestone_label_plural() ) . '

' . '

' . sprintf( // translators: %s: upstream_milestone_label_plural. __( 'You can now start to add your %s.', 'upstream' ), upstream_milestone_label_plural() ) . '

' . '

' . sprintf( // translators: %1$s: upstream_milestone_label_plural. // translators: %2$s: upstream_project_label. // translators: %3$s: upstream_milestone_label_plural. // translators: %4$s: upstream_task_label_plural. __( '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.', 'upstream' ), upstream_milestone_label_plural(), upstream_project_label(), upstream_milestone_label_plural(), upstream_task_label_plural() ) . '

' . '

' . sprintf( // translators: %s: upstream_milestone_label_plural. __( 'If there are no %s in the dropdown, add them by editing the UpStream Settings.', 'upstream' ), upstream_milestone_label_plural() ) . '

', 'position' => array( 'edge' => 'bottom', 'align' => 'top', ), ), ), ); return $pointers; } /** * Enqueue pointers and add script to page. * * @param array $pointers Pointers. */ public function enqueue_pointers( $pointers ) { $screen = get_current_screen(); $screen_id = $screen->id; // Get pointers for this screen. $pointers = apply_filters( 'upstream_admin_pointers-' . $screen_id, array() ); if ( ! $pointers || ! is_array( $pointers ) ) { return; } // Get dismissed pointers. $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); $valid_pointers = array(); // Check pointers and remove dismissed ones. foreach ( $pointers as $pointer_id => $pointer ) { // Sanity check. if ( in_array( $pointer_id, $dismissed ) || empty( $pointer ) || empty( $pointer_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) ) { continue; } $pointer['pointer_id'] = $pointer_id; // Add the pointer to $valid_pointers array. $valid_pointers['pointers'][ $pointer_id ] = $pointer; } // No valid pointers? Stop here. if ( empty( $valid_pointers ) ) { return; } wp_enqueue_style( 'wp-pointer' ); wp_enqueue_script( 'wp-pointer' ); $valid_pointers = wp_json_encode( $valid_pointers ); $return = wp_add_inline_script( 'wp-pointer', " jQuery( function( $ ) { var wc_pointers = {$valid_pointers}; setTimeout( init_wc_pointers, 2000 ); function init_wc_pointers() { $.each( wc_pointers.pointers, function( i ) { show_wc_pointer( i ); return false; }); } function show_wc_pointer( id ) { var pointer = wc_pointers.pointers[ id ]; var options = $.extend( pointer.options, { close: function() { $.post( ajaxurl, { pointer: pointer.pointer_id, action: 'dismiss-wp-pointer' }); if ( pointer.next ) { show_wc_pointer( pointer.next ); } } } ); var this_pointer = $( pointer.target ).pointer( options ); this_pointer.pointer( 'open' ); if ( pointer.next_trigger ) { $( pointer.next_trigger.target ).on( pointer.next_trigger.event, function() { setTimeout( function() { this_pointer.pointer( 'close' ); }, 400 ); }); } } }); " ); } } new UpStream_Admin_Pointers();