Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.00% covered (warning)
75.00%
27 / 36
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Posts_List_Page_Notification
75.00% covered (warning)
75.00%
27 / 36
71.43% covered (warning)
71.43%
5 / 7
23.06
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
4
 init_actions
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 init
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 disable_posts_page
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
5
 enqueue_css
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 add_posts_page_css_class
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 add_notification_icon
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Posts_List_Page_Notification file.
4 * Disable edit_post and delete_post capabilities for Posts Pages in WP-Admin and display a notification icon.
5 *
6 * @package automattic/jetpack-masterbar
7 */
8
9namespace Automattic\Jetpack\Masterbar;
10
11use Automattic\Jetpack\Assets;
12
13/**
14 * Class Posts_List_Page_Notification
15 */
16class Posts_List_Page_Notification {
17
18    /**
19     * Site's Posts page id
20     *
21     * @var int|null
22     */
23    private $posts_page_id;
24
25    /**
26     * If the Post_list contains the site's Posts Page
27     *
28     * @var bool
29     */
30    private $is_page_in_list = false;
31
32    /**
33     * Class instance.
34     *
35     * @var Posts_List_Page_Notification|null
36     */
37    private static $instance = null;
38
39    /**
40     * Posts_List_Page_Notification constructor.
41     *
42     * @param string $posts_page_id The Posts page configured in WordPress.
43     * @param string $show_on_front The show_on_front site option.
44     * @param string $page_on_front The page_on_front site_option.
45     */
46    public function __construct( $posts_page_id, $show_on_front, $page_on_front ) {
47        if ( 'page' === $show_on_front && $posts_page_id !== $page_on_front ) {
48            add_action( 'init', array( $this, 'init_actions' ) );
49        }
50
51        $this->posts_page_id = '' === $posts_page_id ? null : (int) $posts_page_id;
52    }
53
54    /**
55     * Add in all hooks.
56     */
57    public function init_actions() {
58        \add_filter( 'map_meta_cap', array( $this, 'disable_posts_page' ), 10, 4 );
59        \add_filter( 'post_class', array( $this, 'add_posts_page_css_class' ), 10, 3 );
60        \add_action( 'admin_print_footer_scripts-edit.php', array( $this, 'add_notification_icon' ) );
61        \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_css' ) );
62    }
63
64    /**
65     * Creates instance.
66     *
67     * @return Posts_List_Page_Notification
68     */
69    public static function init() {
70        if ( self::$instance === null ) {
71            self::$instance = new self( \get_option( 'page_for_posts' ), \get_option( 'show_on_front' ), \get_option( 'page_on_front' ) );
72        }
73
74        return self::$instance;
75    }
76
77    /**
78     * Disable editing and deleting for the page that is configured as a Posts Page.
79     *
80     * @param array  $caps Array of capabilities.
81     * @param string $cap The current capability.
82     * @param string $user_id The user id.
83     * @param array  $args Argument array.
84     * @return array
85     */
86    public function disable_posts_page( $caps, $cap, $user_id, $args ) {
87        if ( 'edit_post' !== $cap && 'delete_post' !== $cap ) {
88            return $caps;
89        }
90
91        if ( isset( $args[0] ) && $this->posts_page_id === (int) $args[0] ) {
92            $caps[] = 'do_not_allow';
93        }
94
95        return $caps;
96    }
97
98    /**
99     * Load the CSS for the WP Posts List
100     *
101     * We would probably need to move this elsewhere when new features are introduced to wp-posts-list.
102     */
103    public function enqueue_css() {
104        $assets_base_path = '../../dist/wp-posts-list/';
105
106        Assets::register_script(
107            'wp-posts-list',
108            $assets_base_path . 'wp-posts-list.js',
109            __FILE__,
110            array(
111                'enqueue'  => true,
112                'css_path' => $assets_base_path . 'wp-posts-list.css',
113            )
114        );
115    }
116
117    /**
118     * Adds a CSS class on the page configured as a Posts Page.
119     *
120     * @param array  $classes A list of CSS classes.
121     * @param string $class A CSS class.
122     * @param string $post_id The current post id.
123     * @return array
124     */
125    public function add_posts_page_css_class( $classes, $class, $post_id ) {
126        if ( $this->posts_page_id !== (int) $post_id ) {
127            return $classes;
128        }
129
130        $this->is_page_in_list = true;
131
132        $classes[] = 'posts-page';
133
134        return $classes;
135    }
136
137    /**
138     * Add a info icon on the Posts Page letting the user know why they cannot delete and remove the page.
139     */
140    public function add_notification_icon() {
141        // No need to add the JS since the site is not configured with a Posts Page or the current listview doesn't contain the page.
142        if ( null === $this->posts_page_id || ! $this->is_page_in_list ) {
143            return;
144        }
145
146        $text_notice = __( 'The content of your latest posts page is automatically generated and cannot be edited.', 'jetpack-masterbar' );
147        ?>
148        <script>
149            document.querySelector(".posts-page .check-column").innerHTML = '' +
150                    '<div class="info"><span class="icon dashicons dashicons-info-outline"></span><span class="message"><?php echo esc_html( $text_notice ); ?></span></div>';
151        </script>
152        <?php
153    }
154}