PluginProbe
Polylang / 3.8.6
Polylang v3.8.6
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / src / admin / admin-notices.php

admin-notices.php in Polylang 3.8.6, at src/admin/admin-notices.php

296 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * A class to manage admin notices
8 * displayed only to admin, based on 'manage_options' capability
9 * and only on dashboard, plugins and Polylang admin pages
10 *
11 * @since 2.3.9
12 * @since 2.7 Dismissed notices are stored in an option instead of a user meta
13 */
14 class PLL_Admin_Notices {
15 /**
16 * Stores the plugin options.
17 *
18 * @var \WP_Syntex\Polylang\Options\Options
19 */
20 protected $options;
21
22 /**
23 * Stores custom notices.
24 *
25 * @var string[]
26 */
27 private static $notices = array();
28
29 /**
30 * Constructor
31 * Setup actions
32 *
33 * @since 2.3.9
34 *
35 * @param PLL_Admin_Base $polylang The Polylang object.
36 */
37 public function __construct( PLL_Admin_Base $polylang ) {
38 $this->options = $polylang->options;
39
40 add_action( 'admin_init', array( $this, 'hide_notice' ) );
41 add_action( 'admin_notices', array( $this, 'display_notices' ) );
42 }
43
44 /**
45 * Add a custom notice
46 *
47 * @since 2.3.9
48 *
49 * @param string $name Notice name
50 * @param string $html Content of the notice
51 * @return void
52 */
53 public static function add_notice( $name, $html ) {
54 self::$notices[ $name ] = $html;
55 }
56
57 /**
58 * Get custom notices.
59 *
60 * @since 2.3.9
61 *
62 * @return string[]
63 */
64 public static function get_notices() {
65 return self::$notices;
66 }
67
68 /**
69 * Has a notice been dismissed?
70 *
71 * @since 2.3.9
72 *
73 * @param string $notice Notice name
74 * @return bool
75 */
76 public static function is_dismissed( $notice ) {
77 $dismissed = get_option( 'pll_dismissed_notices', array() );
78
79 // Handle legacy user meta
80 $dismissed_meta = get_user_meta( get_current_user_id(), 'pll_dismissed_notices', true );
81 if ( is_array( $dismissed_meta ) ) {
82 if ( array_diff( $dismissed_meta, $dismissed ) ) {
83 $dismissed = array_merge( $dismissed, $dismissed_meta );
84 update_option( 'pll_dismissed_notices', $dismissed );
85 }
86 if ( ! is_multisite() ) {
87 // Don't delete on multisite to avoid the notices to appear in other sites.
88 delete_user_meta( get_current_user_id(), 'pll_dismissed_notices' );
89 }
90 }
91
92 return in_array( $notice, $dismissed );
93 }
94
95 /**
96 * Should we display notices on this screen?
97 *
98 * @since 2.3.9
99 *
100 * @param string $notice The notice name.
101 * @param array $allowed_screens The screens allowed to display the notice.
102 * If empty, default screens are used, i.e. dashboard, plugins, languages, strings and settings.
103 *
104 * @return bool
105 */
106 protected function can_display_notice( string $notice, array $allowed_screens = array() ) {
107 $screen = get_current_screen();
108
109 if ( empty( $screen ) ) {
110 return false;
111 }
112
113 if ( empty( $allowed_screens ) ) {
114 $allowed_screens = array(
115 'dashboard',
116 'plugins',
117 PLL_Admin_Base::get_screen_id( 'lang' ),
118 PLL_Admin_Base::get_screen_id( 'strings' ),
119 PLL_Admin_Base::get_screen_id( 'settings' ),
120 );
121 }
122
123 /**
124 * Filters admin notices which can be displayed.
125 *
126 * @since 2.7.0
127 *
128 * @param bool $display Whether the notice should be displayed or not.
129 * @param string $notice The notice name.
130 */
131 return apply_filters( 'pll_can_display_notice', in_array( $screen->id, $allowed_screens, true ), $notice );
132 }
133
134 /**
135 * Stores a dismissed notice in the database.
136 *
137 * @since 2.3.9
138 *
139 * @param string $notice Notice name.
140 * @return void
141 */
142 public static function dismiss( $notice ) {
143 $dismissed = get_option( 'pll_dismissed_notices', array() );
144
145 if ( ! in_array( $notice, $dismissed ) ) {
146 $dismissed[] = $notice;
147 update_option( 'pll_dismissed_notices', array_unique( $dismissed ) );
148 }
149 }
150
151 /**
152 * Handle a click on the dismiss button
153 *
154 * @since 2.3.9
155 *
156 * @return void
157 */
158 public function hide_notice() {
159 if ( isset( $_GET['pll-hide-notice'], $_GET['_pll_notice_nonce'] ) ) {
160 $notice = sanitize_key( $_GET['pll-hide-notice'] );
161 check_admin_referer( $notice, '_pll_notice_nonce' );
162 self::dismiss( $notice );
163 wp_safe_redirect( remove_query_arg( array( 'pll-hide-notice', '_pll_notice_nonce' ), wp_get_referer() ) );
164 exit;
165 }
166 }
167
168 /**
169 * Displays notices
170 *
171 * @since 2.3.9
172 *
173 * @return void
174 */
175 public function display_notices() {
176 if ( current_user_can( 'manage_options' ) ) {
177 // Core notices
178 if ( defined( 'WOOCOMMERCE_VERSION' ) && ! defined( 'PLLWC_VERSION' ) && $this->can_display_notice( 'pllwc' ) && ! static::is_dismissed( 'pllwc' ) ) {
179 $this->pllwc_notice();
180 }
181
182 if ( ! defined( 'POLYLANG_PRO' ) && $this->can_display_notice( 'review' ) && ! static::is_dismissed( 'review' ) && ! empty( $this->options['first_activation'] ) && time() > $this->options['first_activation'] + 15 * DAY_IN_SECONDS ) {
183 $this->review_notice();
184 }
185
186 $allowed_screen = PLL_Admin_Base::get_screen_id( 'strings' );
187 if (
188 ( ! empty( $this->options['previous_version'] ) && version_compare( $this->options['previous_version'], '3.7.0', '<' ) )
189 && $this->can_display_notice( 'empty-strings-translations', (array) $allowed_screen )
190 && ! static::is_dismissed( 'empty-strings-translations' )
191 ) {
192 $this->empty_strings_translations_notice();
193 }
194
195 // Custom notices
196 foreach ( static::get_notices() as $notice => $html ) {
197 if ( $this->can_display_notice( $notice ) && ! static::is_dismissed( $notice ) ) {
198 ?>
199 <div class="pll-notice notice notice-info">
200 <?php
201 $this->dismiss_button( $notice );
202 echo wp_kses_post( $html );
203 ?>
204 </div>
205 <?php
206 }
207 }
208 }
209 }
210
211 /**
212 * Displays a dismiss button
213 *
214 * @since 2.3.9
215 *
216 * @param string $name Notice name
217 * @return void
218 */
219 public function dismiss_button( $name ) {
220 printf(
221 '<a class="notice-dismiss" href="%s"><span class="screen-reader-text">%s</span></a>',
222 esc_url( wp_nonce_url( add_query_arg( 'pll-hide-notice', $name ), $name, '_pll_notice_nonce' ) ),
223 /* translators: accessibility text */
224 esc_html__( 'Dismiss this notice.', 'polylang' )
225 );
226 }
227
228 /**
229 * Displays a notice if WooCommerce is activated without Polylang for WooCommerce
230 *
231 * @since 2.3.9
232 *
233 * @return void
234 */
235 private function pllwc_notice() {
236 ?>
237 <div class="pll-notice notice notice-warning">
238 <?php $this->dismiss_button( 'pllwc' ); ?>
239 <p>
240 <?php
241 printf(
242 /* translators: %1$s is link start tag, %2$s is link end tag. */
243 esc_html__( 'We have noticed that you are using Polylang with WooCommerce. To ensure compatibility, we recommend you use %1$sPolylang for WooCommerce%2$s.', 'polylang' ),
244 '<a href="https://polylang.pro/pricing/polylang-for-woocommerce/">',
245 '</a>'
246 );
247 ?>
248 </p>
249 </div>
250 <?php
251 }
252
253 /**
254 * Displays a notice asking for a review
255 *
256 * @since 2.3.9
257 *
258 * @return void
259 */
260 private function review_notice() {
261 ?>
262 <div class="pll-notice notice notice-info">
263 <?php $this->dismiss_button( 'review' ); ?>
264 <p>
265 <?php
266 printf(
267 /* translators: %1$s is link start tag, %2$s is link end tag. */
268 esc_html__( 'We have noticed that you have been using Polylang for some time. We hope you love it, and we would really appreciate it if you would %1$sgive us a 5 stars rating%2$s.', 'polylang' ),
269 '<a href="https://wordpress.org/support/plugin/polylang/reviews/?rate=5#new-post">',
270 '</a>'
271 );
272 ?>
273 </p>
274 </div>
275 <?php
276 }
277
278 /**
279 * Displays a notice about the empty strings translations.
280 *
281 * @since 3.7
282 *
283 * @return void
284 */
285 private function empty_strings_translations_notice() {
286 ?>
287 <div class="pll-notice notice notice-info">
288 <?php $this->dismiss_button( 'empty-strings-translations' ); ?>
289 <p>
290 <?php esc_html_e( 'Translations matching the original string are shown as empty in the table. Untranslated content remains unchanged.', 'polylang' ); ?>
291 </p>
292 </div>
293 <?php
294 }
295 }
296