Pomoc w kokpicie – tworzymy wtyczkę

Wszystkie moje wpisy powstają w zasadzie tylko wtedy, gdy wdrażam pewną funkcjonalność w swoich projektach. Tym razem, chciałbym podzielić się z wami wpisem dotyczącym sekcją pomocy, która jest umiejscowiona w górnym rogu kokpitu.

Z systemami jest ten sam problem co z telefonami – nikt nie czyta instrukcji obsługi. Ja wychodzę z założenia, że dobrze napisana instrukcja obsługi to podstawa każdego systemu i urządzenia. Nie ważne czy ją czytamy. Ważne żeby ją mieć, ponieważ możemy uniknąć wielu pytań od użytkowników a przez to zaoszczędzimy czas i pieniądze.

O ile WordPress zapewnia pomoc dla użytkownika, to można mieć do niej wiele uwag. Dla mnie jest zbyt ogólna i nie wyjaśnia wielu ważnych kwestii. Oczywiście nie ma co narzekać, gdyż niewiele systemów umożliwia przejście do pomocy z poziomu danej strony panelu administracyjnego czy jej rozbudowę.

Naszą wtyczkę pomocy oprzemy o własny typ wpisów. Dzięki temu rozwiązaniu będziemy mogli edytować ją w każdej chwili oraz co najważniejsze eksportować pliki pomocy. Takimi plikami będziemy mogli się dzielić z innymi. I to właśnie może być świetne.

W pierwszej kolejności zadeklarujemy naszą klasę oraz dodamy kilka zaczepów w konstruktorze:

    public function __construct() {
        $this->all_screens = array(
            'dashboard' => __('Dashboard', 'ppch'),
                'update-core' => __('--Update', 'ppch'),
            'edit-post' => __('Post', 'ppch'),
                'post' => __('--Edit post', 'ppch'),
                'edit-category' => __('--Categories', 'ppch'),
                'edit-post_tag' => __('--Tags', 'ppch'),
            'themes' => __('Themes', 'ppch'),
                'widgets' => __('--Widgets', 'ppch'),
                'nav-menus' => __('--Menus', 'ppch'),
                'theme-editor' => __('Theme editor', 'ppch'),
            'plugins' => __('Plugins', 'ppch'),
                'plugin-install' => __('--Plugin install', 'ppch'),
                'plugin-editor' => __('--Plugin editor', 'ppch'),
            'users' => __('Users', 'ppch'),
                'user' => __('--Add user', 'ppch'),
                'user-edit' => __('--Edit user', 'ppch'),
                'profile' => __('--Profile', 'ppch'),
            'tools' => __('Tools', 'ppch'),
                'import' => __('--Import', 'ppch'),
                'export' => __('--Export', 'ppch'),
            'options-general' => __('Options', 'ppch'),
            'edit-wp_help' => __('WP Help', 'ppch')
        );
        
        add_filter( 'contextual_help', array( $this, 'helper' ), 1, 3 );
        add_action( 'init', array( $this, 'register_post_type' ) );
        add_action( 'add_meta_boxes', array( $this, 'meta_boxes' ) );
        add_action( 'save_post_wp_help', array( $this, 'save_post_meta' ), 10 );
        add_filter( 'manage_wp_help_posts_columns', array( $this, 'add_column' ), 5 );
        add_action( 'manage_wp_help_posts_custom_column', array( $this, 'column_wrap' ), 5, 2 );
        add_action( 'admin_menu', array( $this, 'remove_meta_boxes' ) );
    }

Najważniejszą częścią kodu jest stworzenie własnego typu wpisu o nazwie wp_help. Służy do tego funkcja register_post_type. Dla niej podajemy kilka parametrów. Oczywiście nie chcemy, żeby nasz typ wpisu był dostępny na zewnątrz, dlatego argument public ustawiony jest na false.

    public function register_post_type() {
        
        $labels = array(
            'name'                => __( 'Contextual Help', 'ppch' ),
            'singular_name'       => __( 'Contextual Help', 'ppch' ),
            'menu_name'           => __( 'Contextual Help', 'ppch' )
        );
        $args = array(
            'labels'             => $labels,
            'public'             => false,
            'publicly_queryable' => false,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => false,
            'has_archive'        => false,
            'hierarchical'       => false,
            'supports'           => array( 'title', 'editor', 'author', 'revisions' ),
            'show_in_menu'       => 'options-general.php',
            'show_in_nav_menus'  => false,
            'menu_position'         => 10,
            'can_export'         => true,
            'exclude_from_search'=> true,
        );
        register_post_type( 'wp_help', $args );
    }

Dodamy również funkcje, dzięki którym usuniemy pole slug w edycji pomocy oraz dodamy 2 kolumny do listy wpisów pomocy.

    public function remove_meta_boxes() {
        remove_meta_box('slugdiv', 'wp_help', 'normal');
    }
    
    public function add_column( $columns ){
        $columns['page'] = __( 'Page', 'ppch' );
        $columns['roles'] = __( 'Roles', 'ppch' );
        return $columns;
    }
    
    public function column_wrap( $column_name, $id ){
        if( $column_name === 'page' ){
            global $post;
            $wh_screen_id = (array) get_post_meta( $post->ID, 'wh_screen_id', true );
            $screens = '';
            foreach( $wh_screen_id as $screen ) {
                $screens .= $this->all_screens[$screen] . ', ';
                
            }
            echo rtrim( $screens, ', ' );
        }
        if( $column_name === 'roles' ){
            global $post;
            $wh_roles = (array) get_post_meta( $post->ID, 'wh_roles', true );
            $roles = '';
            foreach( $wh_roles as $role ) {
                $roles .= $role == 'all' ? __('All roles', 'ppch') : translate_user_role( ucfirst( $role ) ) . ', ';
                
            }
            echo rtrim( $roles, ', ' );
        }
    }

Jeżeli mamy zarejestrowany typ wpisu musimy dodać własne pola. Bez nich nasz mechanizm nie zadziała, ponieważ musimy zdefiniować, w którym miejscu wyświetlić naszą pomoc, dla jakich grup użytkowników oraz czy zastąpić już istniejący wpis pomocy. Nasz mechanizm zadba o to, aby można było zaznaczyć wiele grup oraz miejsc w którym może się znaleźć wpis.

    public function meta_boxes() {
        add_meta_box('contextual-help-option', __('Options','ppch'), array( $this, 'meta_box_options' ), 'wp_help', 'side', 'default');
    }
    
    public function meta_box_options( $post, $post_id ) {
        $screens = (array) get_post_meta( $post->ID, 'wh_screen_id', true );
        $wh_roles = get_post_meta( $post->ID, 'wh_roles', true );
    ?>
        <p><label for="wh-select-screen"><?php _e('Choose a screen', 'ppch'); ?></label><br/>
        <select name="wh_screen_id[]" id="wh-select-screen" multiple>
        <?php foreach( $this->all_screens as $screen_id=>$name ): ?>
            <option value="<?php echo $screen_id; ?>" <?php echo in_array($screen_id, $screens) ? 'selected' : ''; ?>><?php echo $name; ?></option>
        <?php endforeach; ?>
        </select></p>
        <label for="wh_post_name"><?php _e('Slug'); ?></label><br/>
        <input id="wh_post_name" type="text" value="<?php echo $post->post_name; ?>" size="20" name="post_name"></input>
        <p class="description"><?php _e("Paste here id of help tab you wan't to replace", 'ppch'); ?></p>
        
        <label for="wh_roles"><?php _e('Display for'); ?></label><br/>
        <?php if( !$wh_roles ) $wh_roles = array('all'); ?>
        
        <select id="wh_roles" name="wh_roles[]" multiple>
            <option value="all" <?php echo in_array('all', $wh_roles) ? 'selected' : ''; ?>><?php _e('All roles', 'ppch'); ?></option>
            <?php 
            $editable_roles = get_editable_roles();
            foreach ( $editable_roles as $role => $details ) {
                $name = translate_user_role($details['name'] );
            ?>
            <option <?php echo in_array($role, $wh_roles) ? 'selected' : ''; ?> value="<?php echo esc_attr($role); ?>"><?php echo $name; ?></option>
            <?php  } ?>
        </select>
    <?php
    }

Dane z pól meta boksu musimy oczywiście zapisać. Jak zawsze przy tego rodzaju zapisie sprawdzimy czy istnieje id wpisu, uprawnienia do zapisu i czy istnieje pole w tablicy $_POST o nazwie wh_screen_id. Wartość naszego pola zostanie zapisana jako zserializowana tablica, dlatego przed zapisem warto zrobić rzutowanie dla typu array.

    public function save_post_meta( $post_id ) {
        if ( $post_id === null || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) return;
        if ( !current_user_can( 'edit_post', $post_id ) ) return;
        
        if( isset( $_POST['wh_screen_id'] ) ) {
            $wh_screen_id = $_POST['wh_screen_id'];
            add_post_meta( $post_id, 'wh_screen_id', $wh_screen_id, true ) || update_post_meta( $post_id, 'wh_screen_id', $wh_screen_id );
        }
        
        if( isset( $_POST['wh_roles'] ) ) {
            $wh_roles = $_POST['wh_roles'];
            if( in_array( 'all', $wh_roles ) ) $wh_roles = array('all');
            add_post_meta( $post_id, 'wh_roles', $wh_roles, true ) || update_post_meta( $post_id, 'wh_roles', $wh_roles );
        }
    }

Ostatnia rzeczą jaka nam pozostała to dodanie funkcji, która dołączy nasze wpisy pomocy do konkretnych stron kokpitu. Gdybyście chcieli zrobić echo drugiego argumentu, to na każdej stronie w kokpicie pokaże wam się id danej strony. Niestety WordPress nie umożliwia pobrania wszystkich id dla stron kokpitu, dlatego musieliśmy w konstruktorze zdefiniować je sami.

    public function helper( $old_help, $screen_id, $screen )
    {
        global $current_user;
        
        $args = array( 'posts_per_page' => -1, 'post_type'=> 'wp_help' );
        $posts = get_posts( $args );
        $screen->remove_help_tab('inserting-media');
        $screen->remove_help_tab('discussion-settings');
        foreach($posts as $row ) {
            $post_screens = (array) get_post_meta( $row->ID, 'wh_screen_id', true );
            $wh_roles = (array) get_post_meta( $row->ID, 'wh_roles', true );
            if( in_array( $current_user->roles[0], $wh_roles ) || in_array( 'all', $wh_roles ) ) {
                $new_screen_id = sanitize_title( $row->post_name );
                $row->post_content = str_replace( array('{{', '}}'), array('[', ']'), $row->post_content);
                if( in_array( $screen_id, $post_screens ) ) {
                    $screen->add_help_tab( array('id' => $new_screen_id, 'title' => $row->post_title, 'content' => wpautop($row->post_content) ) );
                    //$screen->set_help_sidebar( null );
                }
            }
        }
        return $old_help;
    }

Funkcja sprawdza do jakiej grupy obecny użytkownik należy oraz dla których stron kokpity wyświetlić wpis. W kodzie za komentowałem metodę set_help_sidebar. Z sidebarem pomocy jest ten problem, że nie możemy go definiować dla każdej zakładki z osobna, tylko dla stron. Dlatego dla sidebarów należałoby stworzyć nowy typ wpisu lub poprostu go wyrzucić. Wydaje mi się, że nie jest on potrzebny.

Jak widzicie nie potrzebowaliśmy zbyt wiele kodu, żeby wykonać tak istotną zmianę w WordPressie. Od teraz w menu Ustawienia zobaczymy dodatkową stronę o nazwie WP Pomoc. W niej będziecie zarządzać wpisami pomocy dla WordPressa. Dla leniwych do pobrania wtyczka gotowa do instalacji.

Pobierz wtyczkę WP Help

You may also like...