@@ -35,12 +35,13 @@ class AdminNotices
3535 * Registers a notice to be conditionally displayed in the admin
3636 *
3737 * @since 1.0.0
38+ * @since 1.1.0 no longer include namespace in AdminNotice id
3839 *
3940 * @param string|callable $render
4041 */
4142 public static function show (string $ notificationId , $ render ): AdminNotice
4243 {
43- $ notice = new AdminNotice (self :: $ namespace . ' / ' . $ notificationId , $ render );
44+ $ notice = new AdminNotice ($ notificationId , $ render );
4445
4546 self ::getRegistrar ()->registerNotice ($ notice );
4647
@@ -59,7 +60,7 @@ public static function show(string $notificationId, $render): AdminNotice
5960 public static function render (AdminNotice $ notice , bool $ echo = true ): ?string
6061 {
6162 ob_start ();
62- (new DisplayNoticesInAdmin ())($ notice );
63+ (new DisplayNoticesInAdmin (self :: $ namespace ))($ notice );
6364 $ output = ob_get_clean ();
6465
6566 if ($ echo ) {
@@ -108,12 +109,15 @@ public static function removeContainer(): void
108109 *
109110 * This should be called at the beginning of the plugin file along with other configuration.
110111 *
112+ * @since 1.1.0 added namespace validation
111113 * @since 1.0.0
112114 */
113115 public static function initialize (string $ namespace , string $ pluginUrl ): void
114116 {
115117 if (empty ($ namespace )) {
116118 throw new RuntimeException ('Namespace must be provided ' );
119+ } elseif (preg_match ('/[^a-zA-Z0-9_-]/ ' , $ namespace )) {
120+ throw new RuntimeException ('Namespace must only contain letters, numbers, hyphens, and underscores ' );
117121 }
118122
119123 self ::$ packageUrl = $ pluginUrl ;
@@ -138,6 +142,7 @@ public static function getNotices(): array
138142 /**
139143 * Rests a dismissed notice for a given user so the notice will be shown again
140144 *
145+ * @since 1.1.0 uses namespacing
141146 * @since 1.0.0
142147 */
143148 public static function resetNoticeForUser (string $ notificationId , int $ userId ): void
@@ -146,17 +151,18 @@ public static function resetNoticeForUser(string $notificationId, int $userId):
146151
147152 $ preferencesKey = $ wpdb ->get_blog_prefix () . 'persisted_preferences ' ;
148153 $ preferences = get_user_meta ($ userId , $ preferencesKey , true );
154+ $ packageKey = 'stellarwp/admin-notices/ ' . self ::$ namespace ;
149155
150- $ notificationKey = self ::$ namespace . '/ ' . $ notificationId ;
151- if (isset ($ preferences ['stellarwp/admin-notices ' ][$ notificationKey ])) {
152- unset($ preferences ['stellarwp/admin-notices ' ][$ notificationKey ]);
156+ if (isset ($ preferences [$ packageKey ][$ notificationId ])) {
157+ unset($ preferences [$ packageKey ][$ notificationId ]);
153158 update_user_meta ($ userId , $ preferencesKey , $ preferences );
154159 }
155160 }
156161
157162 /**
158163 * Resets all dismissed notices for a given user so all notices will be shown again
159164 *
165+ * @since 1.1.0 uses namespacing and simplified the method
160166 * @since 1.0.0
161167 */
162168 public static function resetAllNoticesForUser (int $ userId ): void
@@ -165,44 +171,52 @@ public static function resetAllNoticesForUser(int $userId): void
165171
166172 $ preferencesKey = $ wpdb ->get_blog_prefix () . 'persisted_preferences ' ;
167173 $ preferences = get_user_meta ($ userId , $ preferencesKey , true );
174+ $ packageKey = 'stellarwp/admin-notices/ ' . self ::$ namespace ;
168175
169- if (isset ($ preferences ['stellarwp/admin-notices ' ])) {
170- $ preferenceRemoved = false ;
171- foreach ($ preferences ['stellarwp/admin-notices ' ] as $ key => $ value ) {
172- if (strpos ($ key , self ::$ namespace . '/ ' ) === 0 ) {
173- unset($ preferences ['stellarwp/admin-notices ' ][$ key ]);
174- $ preferenceRemoved = true ;
175- }
176- }
177-
178- if ($ preferenceRemoved ) {
179- update_user_meta ($ userId , $ preferencesKey , $ preferences );
180- }
176+ if (isset ($ preferences [$ packageKey ])) {
177+ unset($ preferences [$ packageKey ]);
178+ update_user_meta ($ userId , $ preferencesKey , $ preferences );
181179 }
182180 }
183181
184182 /**
185183 * Hook action to display the notices in the admin
186184 *
185+ * @since 1.1.0 passes the namespace to the display notices class
187186 * @since 1.0.0
188187 */
189188 public static function setUpNotices (): void
190189 {
191- (new DisplayNoticesInAdmin ())(...self ::getNotices ());
190+ (new DisplayNoticesInAdmin (self :: $ namespace ))(...self ::getNotices ());
192191 }
193192
194193 /**
195194 * Hook action to enqueue the scripts needed for dismissing notices
196195 *
196+ * @since 1.1.0 added the namespacing attribute to the script tag
197197 * @since 1.0.2 use filetime for versioning, which will bust the cache when the library is updated
198198 * @since 1.0.0
199199 */
200200 public static function enqueueScripts (): void
201201 {
202+ $ namespace = self ::$ namespace ;
203+ $ handle = "$ namespace-admin-notices " ;
202204 $ version = filemtime (__DIR__ . '/resources/admin-notices.js ' );
203205
206+ add_filter ('script_loader_tag ' , static function ($ tag , $ tagHandle ) use ($ handle , $ namespace ) {
207+ if ($ handle !== $ tagHandle ) {
208+ return $ tag ;
209+ }
210+
211+ $ tag = str_replace (' src ' , ' defer src ' , $ tag );
212+
213+ $ replacement = "<script data-stellarwp-namespace=' $ namespace' " ;
214+
215+ return str_replace ('<script ' , $ replacement , $ tag );
216+ }, 10 , 2 );
217+
204218 wp_enqueue_script (
205- ' stellarwp-admin-notices ' ,
219+ $ handle ,
206220 self ::$ packageUrl . '/src/resources/admin-notices.js ' ,
207221 ['jquery ' , 'wp-data ' , 'wp-preferences ' ],
208222 $ version ,
0 commit comments