PluginProbe
Code Snippets / 3.10.1
Code Snippets v3.10.1
3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 3.0.1 All 64 releases
code-snippets / php / Integration / Promotions / Notices / Promotion_Base.php

Promotion_Base.php in Code Snippets 3.10.1, at php/Integration/Promotions/Notices/Promotion_Base.php

281 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Code_Snippets\Integration\Promotions\Notices;
4
5 use function Code_Snippets\code_snippets;
6 use function Code_Snippets\Settings\get_setting;
7 use const Code_Snippets\PLUGIN_FILE;
8
9 /**
10 * Base class for plugin promotion notices.
11 */
12 abstract class Promotion_Base {
13
14 /**
15 * AJAX action name for dismissing the promotion.
16 */
17 private const AJAX_ACTION = 'code_snippets_dismiss_promotion';
18
19 /**
20 * User meta key to store dismissed promotions.
21 */
22 private const USER_META_KEY = 'code_snippets_dismissed_promotions';
23
24 /**
25 * Get the name of the plugin being promoted.
26 *
27 * @return string The name of the plugin.
28 */
29 abstract public function get_plugin_name(): string;
30
31 /**
32 * Get the slug of the plugin being promoted.
33 *
34 * @return string The slug of the plugin.
35 */
36 abstract public function get_plugin_slug(): string;
37
38 /**
39 * Get the admin screen IDs where the promotion should be displayed.
40 *
41 * @return array An array of admin screen IDs.
42 */
43 abstract public function get_plugin_admin_screens(): array;
44
45 /**
46 * Get the heading text for the promotion notice.
47 *
48 * @return string The promotion heading.
49 */
50 public function get_promotion_heading(): string {
51 return __( 'Clean up your plugin list today', 'code-snippets' );
52 }
53
54 /**
55 * Get the message text for the promotion notice.
56 *
57 * @return string The promotion message.
58 */
59 public function get_promotion_message(): string {
60 // translators: %s: plugin name.
61 $message = __( 'Code Snippets provides a powerful and user-friendly alternative to "%s", with cloud sync, advanced features, and an intuitive interface.', 'code-snippets' );
62 return sprintf( $message, $this->get_plugin_name() );
63 }
64
65 /**
66 * Constructor to initialize the promotion notice.
67 */
68 public function __construct() {
69 add_action( 'current_screen', [ $this, 'register_promotion_hooks' ] );
70 add_action( 'wp_ajax_' . self::AJAX_ACTION, [ $this, 'dismiss_promotion_ajax_handler' ] );
71 }
72
73 /**
74 * Register hooks to display the promotion notice if conditions are met.
75 */
76 public function register_promotion_hooks() {
77 if ( $this->is_plugin_admin_screen() && ! $this->is_promotion_dismissed() ) {
78 add_action( 'admin_notices', [ $this, 'display_promotion' ], 1 );
79 add_action( 'admin_print_styles', [ $this, 'print_promotion_styles' ] );
80 add_action( 'admin_print_footer_scripts', [ $this, 'print_dismiss_script' ], 99 );
81 }
82 }
83
84 /**
85 * Determine if the current admin screen is one of the plugin's admin screens.
86 *
87 * @return bool True if it's a plugin admin screen, false otherwise.
88 */
89 public function is_plugin_admin_screen(): bool {
90 if ( ! is_admin() || ! function_exists( 'get_current_screen' ) ) {
91 return false;
92 }
93
94 $current_screen = get_current_screen();
95 return $current_screen && in_array( $current_screen->id, $this->get_plugin_admin_screens(), true );
96 }
97
98 /**
99 * Check if the promotion has been dismissed by the current user.
100 *
101 * @return bool True if the promotion is dismissed, false otherwise.
102 */
103 public function is_promotion_dismissed(): bool {
104 if ( get_setting( 'general', 'hide_upgrade_menu' ) ) {
105 return true;
106 }
107
108 $user_id = get_current_user_id();
109
110 if ( ! $user_id ) {
111 return false;
112 }
113
114 $dismissed_promotions = get_user_meta( $user_id, self::USER_META_KEY, true );
115 return is_array( $dismissed_promotions ) && in_array( $this->get_plugin_slug(), $dismissed_promotions, true );
116 }
117
118 /**
119 * Print the CSS styles for the promotion notice.
120 */
121 public function print_promotion_styles() {
122 ?>
123 <style>
124 .code-snippets-promotion.notice,
125 .code-snippets-promotion.info,
126 .code-snippets-promotion.warning,
127 .code-snippets-promotion.error {
128 padding: 0;
129 }
130 .code-snippets-promotion {
131 display: flex;
132 padding: 0;
133 border-inline-start-width: 4px;
134 }
135
136 .code-snippets-promotion-icon {
137 padding: 10px;
138 background-color: #F0F9FF;
139 }
140
141 .code-snippets-promotion-content {
142 padding: 10px;
143 }
144
145 .code-snippets-promotion-content p {
146 margin-block: 0 .5em;
147 }
148 </style>
149 <?php
150 }
151
152 /**
153 * Print the JavaScript to handle dismissing the promotion notice.
154 */
155 public function print_dismiss_script() {
156 ?>
157 <script>
158 jQuery(document).ready(function ($) {
159 $('.code-snippets-promotion').on('click', '.notice-dismiss', function () {
160 $.post(ajaxurl, {
161 action: '<?php echo esc_attr( self::AJAX_ACTION ); ?>',
162 nonce: '<?php echo esc_attr( wp_create_nonce( self::AJAX_ACTION ) ); ?>',
163 promotion_id: $(this).closest('.code-snippets-promotion').data('promotion-id')
164 })
165 })
166 })
167 </script>
168 <?php
169 }
170
171 /**
172 * Display the promotion notice in the admin area.
173 */
174 public function display_promotion() {
175 ?>
176 <div
177 class="notice notice-info is-dismissible code-snippets-promotion"
178 data-promotion-id="<?php echo esc_attr( $this->get_plugin_slug() ); ?>"
179 aria-label="<?php esc_attr_e( 'Code Snippets Promotion', 'code-snippets' ); ?>"
180 role="region"
181 >
182 <div class="code-snippets-promotion-icon">
183 <img
184 src="<?php echo esc_url( plugins_url( 'assets/icon.svg', PLUGIN_FILE ) ); ?>"
185 alt="<?php esc_attr_e( 'Code Snippets Logo', 'code-snippets' ); ?>"
186 width="32"
187 height="32"
188 />
189 </div>
190 <div class="code-snippets-promotion-content">
191 <p><strong><?php echo esc_html( $this->get_promotion_heading() ); ?></strong></p>
192 <p><?php echo esc_html( $this->get_promotion_message() ); ?></p>
193 <p><?php $this->print_promotion_buttons(); ?></p>
194 </div>
195 </div>
196 <?php
197 }
198
199 /**
200 * AJAX handler to dismiss the promotion notice.
201 */
202 public function dismiss_promotion_ajax_handler() {
203 check_ajax_referer( self::AJAX_ACTION, 'nonce' );
204
205 if ( ! current_user_can( 'manage_options' ) ) {
206 wp_send_json_error( 'Unauthorized', 403 );
207 }
208
209 $promotion_id = isset( $_POST['promotion_id'] ) ? sanitize_text_field( wp_unslash( $_POST['promotion_id'] ) ) : '';
210
211 if ( empty( $promotion_id ) ) {
212 wp_send_json_error( 'Invalid promotion id.', 400 );
213 }
214
215 $user_id = get_current_user_id();
216 $dismissed_promotions = get_user_meta( $user_id, self::USER_META_KEY, true );
217
218 if ( ! is_array( $dismissed_promotions ) ) {
219 $dismissed_promotions = [];
220 }
221
222 if ( ! in_array( $promotion_id, $dismissed_promotions, true ) ) {
223 $dismissed_promotions[] = $promotion_id;
224 update_user_meta( $user_id, self::USER_META_KEY, $dismissed_promotions );
225 }
226
227 wp_send_json_success();
228 }
229
230 /**
231 * Check if the user should see the migration button.
232 *
233 * @return bool Whether the user should see the migration button.
234 */
235 public function show_migration_button(): bool {
236 return false;
237 }
238
239 /**
240 * Render buttons for the promotion notice.
241 *
242 * @uses show_migration_button() to determine which buttons to show.
243 */
244 protected function print_promotion_buttons() {
245 if ( $this->show_migration_button() ) {
246 $primary_text = __( 'Migrate to Code Snippets', 'code-snippets' );
247 $primary_url = add_query_arg(
248 [
249 'tab' => 'migrate',
250 'from' => $this->get_plugin_slug(),
251 ],
252 code_snippets()->get_menu_url( 'import' )
253 );
254 } else {
255 $primary_text = __( 'Manage your snippets', 'code-snippets' );
256 $primary_url = code_snippets()->get_menu_url();
257 }
258
259 printf(
260 '<a href="%s" class="button button-primary">%s</a>',
261 esc_url( $primary_url ),
262 esc_html( $primary_text )
263 );
264
265 $secondary_url = add_query_arg(
266 [
267 'utm_source' => $this->get_plugin_slug(),
268 'utm_medium' => 'promotion',
269 'utm_campaign' => 'custom-code',
270 ],
271 'https://codesnippets.pro/pricing'
272 );
273
274 printf(
275 ' <a href="%s" class="button button-secondary" target="_blank" rel="noopener noreferrer">%s</a> ',
276 esc_url( $secondary_url ),
277 esc_html__( 'Learn more', 'code-snippets' )
278 );
279 }
280 }
281