Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Notification_Counts
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
6 / 6
20
100.00% covered (success)
100.00%
1 / 1
 register
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 all
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 magnitude
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
4
 get_for_menu
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 get_total
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 reset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Central registry of admin-menu notification counts.
4 *
5 * @package automattic/jetpack-menu-badges
6 */
7
8namespace Automattic\Jetpack\Menu_Badges;
9
10/**
11 * Passive source of truth for admin-menu notification counts. Products register
12 * a count against a menu item; renderers read the aggregate. No rendering here.
13 */
14class Notification_Counts {
15
16    /**
17     * Registered entries, keyed by id.
18     *
19     * @var array<string,array>
20     */
21    private static $entries = array();
22
23    /**
24     * Memoized result of all(), or null when stale. Invalidated on register()/reset().
25     *
26     * @var array<string,array>|null
27     */
28    private static $visible_cache = null;
29
30    /**
31     * Register (or overwrite) a notification count for a product.
32     *
33     * @param string $id   Unique id (e.g. 'jetpack-forms').
34     * @param array  $args {
35     *     Notification count entry arguments.
36     *
37     *     @type string|null $menu_slug Submenu item slug to badge; null → top-level only.
38     *     @type int         $count     Magnitude for 'count' entries. Default 0.
39     *     @type string      $type      'count' | 'attention'. Default 'count'.
40     *     @type bool        $is_silent Exclude from totals/display. Default false.
41     * }
42     * @return void
43     */
44    public static function register( $id, array $args ) {
45        self::$entries[ $id ] = array(
46            'menu_slug' => isset( $args['menu_slug'] ) ? (string) $args['menu_slug'] : null,
47            'count'     => isset( $args['count'] ) ? (int) $args['count'] : 0,
48            'type'      => ( isset( $args['type'] ) && 'attention' === $args['type'] ) ? 'attention' : 'count',
49            'is_silent' => ! empty( $args['is_silent'] ),
50        );
51        self::$visible_cache  = null;
52    }
53
54    /**
55     * All non-silent entries, after applying the extension filter.
56     *
57     * @return array<string,array>
58     */
59    public static function all() {
60        if ( null !== self::$visible_cache ) {
61            return self::$visible_cache;
62        }
63
64        /**
65         * Filters the registered menu notification counts.
66         *
67         * @since 0.1.0
68         * @param array<string,array> $entries Map of id => entry.
69         */
70        $entries = apply_filters( 'jetpack_menu_notification_counts', self::$entries );
71
72        $visible = array();
73        foreach ( $entries as $id => $entry ) {
74            if ( empty( $entry['is_silent'] ) ) {
75                $visible[ $id ] = $entry;
76            }
77        }
78
79        self::$visible_cache = $visible;
80        return $visible;
81    }
82
83    /**
84     * The magnitude an entry contributes to a total: its count, or 1 for attention.
85     *
86     * @param array $entry Entry.
87     * @return int
88     */
89    private static function magnitude( array $entry ) {
90        if ( isset( $entry['type'] ) && 'attention' === $entry['type'] ) {
91            return 1;
92        }
93        return isset( $entry['count'] ) ? (int) $entry['count'] : 0;
94    }
95
96    /**
97     * Summed count for a specific submenu item.
98     *
99     * @param string $menu_slug Submenu slug.
100     * @return int
101     */
102    public static function get_for_menu( $menu_slug ) {
103        $total = 0;
104        foreach ( self::all() as $entry ) {
105            if ( isset( $entry['menu_slug'] ) && $entry['menu_slug'] === $menu_slug ) {
106                $total += self::magnitude( $entry );
107            }
108        }
109        return $total;
110    }
111
112    /**
113     * Top-level total across all non-silent entries.
114     *
115     * @return int
116     */
117    public static function get_total() {
118        $total = 0;
119        foreach ( self::all() as $entry ) {
120            $total += self::magnitude( $entry );
121        }
122        return $total;
123    }
124
125    /**
126     * Clear all registered entries (test helper).
127     *
128     * @return void
129     */
130    public static function reset() {
131        self::$entries       = array();
132        self::$visible_cache = null;
133    }
134}