PluginProbe
Leaky Paywall / trunk
Leaky Paywall vtrunk
5.1.9 5.1.8 5.1.7 5.1.6 5.1.5 5.1.4 5.1.3 5.1.2 5.1.1 5.1.0 5.0.9 4.16.17 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.17.0 4.17.1 4.17.2 4.18.0 4.18.1 All 180 releases
leaky-paywall / class.php

class.php in Leaky Paywall trunk, at class.php

1,214 lines 53.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Registers zeen101's Leaky Paywall class
4 *
5 * @package zeen101's Leaky Paywall
6 * @since 1.0.0
7 */
8
9 /**
10 * This class registers the main issuem functionality
11 *
12 * @since 1.0.0
13 */
14 class Leaky_Paywall {
15
16 /**
17 * Leaky Paywall Name
18 *
19 * @var string
20 */
21 private $plugin_name = LEAKY_PAYWALL_NAME;
22
23 /**
24 * Leaky Paywall Slug
25 *
26 * @var string
27 */
28 private $plugin_slug = LEAKY_PAYWALL_SLUG;
29
30 /**
31 * Leaky Paywall Basename
32 *
33 * @var string
34 */
35 private $basename = LEAKY_PAYWALL_BASENAME;
36
37 /**
38 * Class constructor, puts things in motion
39 *
40 * @since 1.0.0
41 */
42 public function __construct() {
43
44 add_action( 'http_api_curl', array( $this, 'force_ssl_version' ) );
45
46 add_action( 'admin_enqueue_scripts', array( $this, 'admin_wp_enqueue_scripts' ) );
47 add_filter('script_loader_tag', array( $this, 'add_type_attribute' ) , 10, 3);
48 add_action( 'admin_print_styles', array( $this, 'admin_wp_print_styles' ) );
49 add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
50
51 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
52 add_action( 'admin_menu', array( $this, 'suppress_legacy_reporting_tool_menu' ), 999 );
53 add_action( 'admin_menu', array( $this, 'suppress_legacy_bulk_import_menu' ), 999 );
54 add_action( 'admin_notices', array( $this, 'multiple_levels_deactivation_notice' ) );
55 add_action( 'admin_notices', array( $this, 'reporting_tool_deactivation_notice' ) );
56 add_action( 'admin_notices', array( $this, 'bulk_import_deactivation_notice' ) );
57
58 add_action( 'wp_ajax_leaky_paywall_process_notice_link', array( $this, 'ajax_process_notice_link' ) );
59 add_action( 'wp_ajax_leaky_paywall_add_subscriber', array( $this, 'ajax_add_subscriber' ) );
60
61 add_action( 'wp', array( $this, 'process_content_restrictions' ) );
62 add_action( 'wp', array( $this, 'process_pdf_restrictions' ) );
63 add_action( 'rest_api_init', array( $this, 'process_rest_content_restrictions' ) );
64 add_action( 'wp_head', array( $this, 'output_paywall_schema' ) );
65
66 add_filter( 'issuem_pdf_attachment_url', array( $this, 'restrict_pdf_attachment_url' ), 10, 2 );
67 }
68
69 /**
70 * Process restrictions with WP REST API
71 */
72 public function process_rest_content_restrictions() {
73
74 $restrictions = new Leaky_Paywall_Restrictions();
75 add_filter( 'the_content', array( $restrictions, 'process_rest_content_restrictions' ) );
76
77 }
78
79 /**
80 * Process restrictions with javascript
81 *
82 * Note: The AJAX handlers are no longer needed when using the REST API
83 * restriction check (leaky-paywall-check.js). The REST endpoint registered
84 * by Leaky_Paywall_REST_Restrictions handles all restriction checks.
85 */
86 public function process_js_content_restrictions() {
87 }
88
89 /**
90 * Process restrictions with php
91 */
92 public function process_content_restrictions() {
93 if ( is_admin() ) {
94 return;
95 }
96
97 $settings = get_leaky_paywall_settings();
98
99 if ( 'on' === $settings['enable_js_cookie_restrictions'] ) {
100 return;
101 }
102
103 $restrictions = new Leaky_Paywall_Restrictions();
104 $restrictions->process_content_restrictions();
105 }
106
107 /**
108 * Process restrictions for IssueM PDFs
109 */
110 public function process_pdf_restrictions() {
111 if ( isset( $_GET['issuem-pdf-download'] ) ) {
112 $restrictions = new Leaky_Paywall_Restrictions();
113 $restrictions->pdf_access();
114 }
115 }
116
117 /**
118 * Output JSON-LD schema markup for paywalled content
119 *
120 * @since 5.0
121 */
122 public function output_paywall_schema() {
123 if ( ! is_singular() ) {
124 return;
125 }
126
127 $settings = get_leaky_paywall_settings();
128
129 if ( empty( $settings['paywall_schema_markup'] ) || 'on' !== $settings['paywall_schema_markup'] ) {
130 return;
131 }
132
133 $restrictions = new Leaky_Paywall_Restrictions( get_the_ID() );
134
135 if ( ! $restrictions->post_is_restricted_by_rules() ) {
136 return;
137 }
138
139 $schema = array(
140 '@context' => 'https://schema.org',
141 '@type' => apply_filters( 'leaky_paywall_schema_type', 'Article', get_the_ID() ),
142 'headline' => get_the_title(),
143 'isAccessibleForFree' => false,
144 'hasPart' => array(
145 '@type' => 'WebPageElement',
146 'isAccessibleForFree' => false,
147 'cssSelector' => apply_filters( 'leaky_paywall_schema_css_selector', '.entry-content' ),
148 ),
149 );
150
151 echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES ) . '</script>' . "\n";
152 }
153
154 /**
155 * Send the user to the my account page if they user has paid and they try to access the login page
156 *
157 * @since 4.10.3
158 */
159 public function redirect_from_login_page() {
160 $settings = get_leaky_paywall_settings();
161
162 if ( ! empty( $settings['page_for_login'] ) && is_page( $settings['page_for_login'] ) ) {
163
164 if ( ! empty( $settings['page_for_profile'] ) ) {
165 wp_safe_redirect( get_page_link( $settings['page_for_profile'] ) );
166 exit;
167 } elseif ( ! empty( $settings['page_for_subscription'] ) ) {
168 wp_safe_redirect( get_page_link( $settings['page_for_subscription'] ) );
169 exit;
170 }
171 }
172 }
173
174 /**
175 * Process the passwordless login functionality
176 *
177 * @since 4.10.3
178 */
179 public function process_passwordless_login() {
180 $settings = get_leaky_paywall_settings();
181
182 if ( ! empty( $settings['page_for_login'] ) && is_page( $settings['page_for_login'] ) ) {
183
184 if ( empty( $_REQUEST['r'] ) ) {
185 return;
186 }
187
188 $login_hash = sanitize_text_field( wp_unslash( $_REQUEST['r'] ) );
189
190 if ( verify_leaky_paywall_login_hash( $login_hash ) ) {
191
192 leaky_paywall_attempt_login( $login_hash );
193 if ( ! empty( $settings['page_for_profile'] ) ) {
194 wp_safe_redirect( get_page_link( $settings['page_for_profile'] ) );
195 exit;
196 } elseif ( ! empty( $settings['page_for_subscription'] ) ) {
197 wp_safe_redirect( get_page_link( $settings['page_for_subscription'] ) );
198 exit;
199 }
200 } else {
201
202 $output = '<h3>' . __( 'Invalid or Expired Login Link', 'leaky-paywall' ) . '</h3>';
203 /* Translators: %s - page for login url */
204 $output .= '<p>' . sprintf( __( 'Sorry, this login link is invalid or has expired. <a href="%s">Try again?</a>', 'leaky-paywall' ), get_page_link( $settings['page_for_login'] ) ) . '</p>';
205 /* Translators: %s - site name */
206 $output .= '<a href="' . get_home_url() . '">' . sprintf( __( 'back to %s', 'leaky-paywall' ), $settings['site_name'] ) . '</a>';
207
208 $message = apply_filters( 'leaky_paywall_invalid_login_link' );
209
210 wp_die( esc_attr( $message ), esc_attr( $output ) );
211 }
212 }
213 }
214
215 /**
216 * Restrict a PDF attachment url
217 *
218 * @param string $attachment_url The attachment url.
219 * @param int $attachment_id The id of the attachment.
220 * @return string The new attachment url
221 */
222 public function restrict_pdf_attachment_url( $attachment_url, $attachment_id ) {
223
224 $settings = get_leaky_paywall_settings();
225
226 if ( 'on' === $settings['restrict_pdf_downloads'] ) {
227 return esc_url( add_query_arg( 'issuem-pdf-download', $attachment_id ) );
228 }
229
230 return $attachment_url;
231
232 }
233
234 /**
235 * Initialize pigeonpack Admin Menu
236 *
237 * @since 1.0.0
238 * @uses add_menu_page() Creates Pigeon Pack menu
239 * @uses add_submenu_page() Creates Settings submenu to Pigeon Pack menu
240 * @uses add_submenu_page() Creates Help submenu to Pigeon Pack menu
241 * @uses do_action() To call 'pigeonpack_admin_menu' for future addons
242 */
243 public function admin_menu() {
244
245 $dashboard = new Leaky_Paywall_Dashboard();
246 $settings = new Leaky_Paywall_Settings();
247 $insights = new Leaky_Paywall_Insights();
248 $admin_subscriber = new Leaky_Paywall_Admin_Subscriber();
249
250 $capability = apply_filters( 'manage_leaky_paywall_settings', 'manage_options' );
251 $admin_icon = $this->get_svg();
252
253 add_menu_page( __( 'Leaky Paywall', 'leaky-paywall' ), __( 'Leaky Paywall', 'leaky-paywall' ), $capability, 'issuem-leaky-paywall', array( $dashboard, 'dashboard_page' ), $admin_icon );
254
255 add_submenu_page( 'issuem-leaky-paywall', __( 'Dashboard', 'leaky-paywall' ), __( 'Dashboard', 'leaky-paywall' ), $capability, 'issuem-leaky-paywall', array( $dashboard, 'dashboard_page' ) );
256
257 add_submenu_page( 'issuem-leaky-paywall', __( 'Settings', 'leaky-paywall' ), __( 'Settings', 'leaky-paywall' ), $capability, 'leaky-paywall-settings', array( $settings, 'settings_page' ) );
258
259 add_submenu_page( 'issuem-leaky-paywall', __( 'Subscribers', 'leaky-paywall' ), __( 'Subscribers', 'leaky-paywall' ), $capability, 'leaky-paywall-subscribers', array( $admin_subscriber, 'show_subscribers_page' ) );
260
261 add_submenu_page( 'issuem-leaky-paywall', __( 'Transactions', 'leaky-paywall' ), __( 'Transactions', 'leaky-paywall' ), $capability, 'edit.php?post_type=lp_transaction' );
262
263 $tools = new Leaky_Paywall_Tools();
264 add_submenu_page( 'issuem-leaky-paywall', __( 'Tools', 'leaky-paywall' ), __( 'Tools', 'leaky-paywall' ), $capability, 'leaky-paywall-tools', array( $tools, 'tools_page' ) );
265
266 $extensions_page = isset( $GLOBALS['leaky_paywall_extensions_page'] ) ? $GLOBALS['leaky_paywall_extensions_page'] : new Leaky_Paywall_Extensions_Page();
267 add_submenu_page( 'issuem-leaky-paywall', __( 'Extensions', 'leaky-paywall' ), __( 'Extensions', 'leaky-paywall' ), $capability, 'leaky-paywall-extensions', array( $extensions_page, 'render_page' ) );
268
269 $license_page = new Leaky_Paywall_License_Page();
270 add_submenu_page( 'issuem-leaky-paywall', __( 'License', 'leaky-paywall' ), __( 'License', 'leaky-paywall' ), $capability, 'leaky-paywall-license', array( $license_page, 'render_page' ) );
271
272 if ( ! leaky_paywall_is_pro() ) {
273 add_submenu_page( 'issuem-leaky-paywall', __( 'Upgrade', 'leaky-paywall' ), __( 'Upgrade', 'leaky-paywall' ), $capability, 'leaky-paywall-upgrade', array( $this, 'upgrade_page' ) );
274 }
275
276
277 }
278
279
280 /**
281 * Prints backend Leaky Paywall styles
282 *
283 * @global $hook_suffix
284 * @since 1.0.0
285 */
286 public function admin_wp_print_styles() {
287 global $hook_suffix;
288
289 if (
290 'leaky-paywall_page_leaky-paywall-subscribers' === $hook_suffix
291 || 'toplevel_page_issuem-leaky-paywall' === $hook_suffix
292 || 'leaky-paywall_page_leaky-paywall-settings' === $hook_suffix
293 || 'index.php' === $hook_suffix
294 || 'leaky-paywall_page_leaky-paywall-upgrade' === $hook_suffix
295 || 'leaky-paywall_page_leaky-paywall-insights' === $hook_suffix
296 || 'leaky-paywall_page_leaky-paywall-tools' === $hook_suffix
297 || 'leaky-paywall_page_leaky-paywall-license' === $hook_suffix
298 || 'leaky-paywall_page_leaky-paywall-extensions' === $hook_suffix
299 || 'admin_page_leaky-paywall-setup' === $hook_suffix
300 ) {
301 wp_enqueue_style( 'leaky_paywall_admin_style', LEAKY_PAYWALL_URL . 'css/issuem-leaky-paywall-admin.css', '', LEAKY_PAYWALL_VERSION );
302 }
303
304 if ( 'leaky-paywall_page_leaky-paywall-insights' === $hook_suffix ) {
305 wp_enqueue_style( 'leaky_paywall_admin_insights_style', LEAKY_PAYWALL_URL . 'css/leaky-paywall-admin-insights.css', '', LEAKY_PAYWALL_VERSION );
306 }
307
308 if ( 'leaky-paywall_page_leaky-paywall-tools' === $hook_suffix ) {
309 wp_enqueue_style( 'jquery-ui-css', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css' );
310 }
311
312 if ( 'toplevel_page_issuem-leaky-paywall' === $hook_suffix ) {
313 wp_enqueue_style( 'leaky_paywall_admin_dashboard_style', LEAKY_PAYWALL_URL . 'css/leaky-paywall-admin-dashboard.css', '', LEAKY_PAYWALL_VERSION );
314 }
315
316 if ( 'post.php' === $hook_suffix || 'post-new.php' === $hook_suffix ) {
317 wp_enqueue_style( 'leaky_paywall_post_style', LEAKY_PAYWALL_URL . 'css/issuem-leaky-paywall-post.css', '', LEAKY_PAYWALL_VERSION );
318
319 $screen = get_current_screen();
320 if ( $screen && 'lp_transaction' === $screen->post_type ) {
321 wp_enqueue_style( 'leaky_paywall_admin_style', LEAKY_PAYWALL_URL . 'css/issuem-leaky-paywall-admin.css', '', LEAKY_PAYWALL_VERSION );
322 }
323 }
324
325 if ( 'edit.php' === $hook_suffix ) {
326 $screen = get_current_screen();
327 if ( $screen && 'lp_transaction' === $screen->post_type ) {
328 wp_enqueue_style( 'leaky_paywall_admin_style', LEAKY_PAYWALL_URL . 'css/issuem-leaky-paywall-admin.css', '', LEAKY_PAYWALL_VERSION );
329 }
330 }
331
332 }
333
334 public function get_svg() {
335
336 $svg_b64 = 'PHN2ZyB3aWR0aD0iNDIzIiBoZWlnaHQ9IjQyMyIgdmlld0JveD0iMCAwIDQyMyA0MjMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0zNjEuNDAzIDAuNzY0MTZWNjMuMDA5M0g2MS40MDgyQzkxLjQ1NTggMjMuNzc3MiAxMzguMDY3IDAuNzY0MTYgMTg3LjQ4MSAwLjc2NDE2SDM2MS40MDNaIiBmaWxsPSIjRTQ1NjM3Ii8+CjxwYXRoIGQ9Ik02MS40MDgyIDQyMi41MTVWMzYwLjI3SDM2MS40MDNDMzMxLjM1NSAzOTkuNTAyIDI4NC43NjIgNDIyLjUxNSAyMzUuMzMgNDIyLjUxNUg2MS40MDgyWiIgZmlsbD0iI0U0NTYzNyIvPgo8cGF0aCBkPSJNMjQuMDg5NCA2Mi40MDg3SDYxLjQyOTZWMzYwLjg3MkgyNC4wODk0QzExLjE4OTcgMzYwLjg3MiAwLjczMjQyMiAzNTAuNDE1IDAuNzMyNDIyIDMzNy41MTVWODUuNzY1N0MwLjczMjQyMiA3Mi44ODMyIDExLjE4OTcgNjIuNDA4NyAyNC4wODk0IDYyLjQwODdaIiBmaWxsPSIjRTQ1NjM3Ii8+CjxwYXRoIGQ9Ik0zOTguNzQ3IDM2MC44NzJIMzYxLjQwNkwzNjEuNDA2IDYyLjQwODNIMzk4Ljc0N0M0MTEuNjI5IDYyLjQwODMgNDIyLjEwNCA3Mi44NjU3IDQyMi4xMDQgODUuNzY1M0w0MjIuMTA0IDMzNy41MTVDNDIyLjEwNCAzNTAuMzk4IDQxMS42NDYgMzYwLjg3MiAzOTguNzQ3IDM2MC44NzJaIiBmaWxsPSIjRTQ1NjM3Ii8+CjxwYXRoIGQ9Ik0yOTkuOTE4IDEyMy4xNDFIMTIyLjkxOFYzMDAuMTQxSDI5OS45MThWMTIzLjE0MVoiIGZpbGw9IiNFNDU2MzciLz4KPC9zdmc+Cg==';
337
338 $icon = 'data:image/svg+xml;base64,' . $svg_b64;
339
340 return $icon;
341 }
342
343 /**
344 * Enqueues backend IssueM styles
345 *
346 * @param string $hook_suffix The hook suffix.
347 * @since 1.0.0
348 */
349 public function admin_wp_enqueue_scripts( $hook_suffix ) {
350
351 if ( 'leaky-paywall_page_leaky-paywall-settings' === $hook_suffix ) {
352 wp_enqueue_media();
353 wp_enqueue_script( 'leaky_paywall_js', LEAKY_PAYWALL_URL . 'js/issuem-leaky-paywall-settings.js', array( 'jquery' ), LEAKY_PAYWALL_VERSION, true );
354
355 wp_localize_script(
356 'leaky_paywall_js',
357 'leaky_paywall_js',
358 array(
359 'lpJsNonce' => wp_create_nonce('leaky-paywall-js-nonce'),
360 )
361 );
362 }
363
364 if ( 'leaky-paywall_page_leaky-paywall-subscribers' === $hook_suffix ) {
365
366 // Removing i18n of UI datepicker for subscriber page only.
367 remove_action( 'admin_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 );
368
369 wp_enqueue_script( 'leaky_paywall_subscribers_js', LEAKY_PAYWALL_URL . 'js/issuem-leaky-paywall-subscribers.js', array( 'jquery-ui-datepicker' ), LEAKY_PAYWALL_VERSION, true );
370 wp_enqueue_style( 'leaky_paywall_admin_subscribers_style', LEAKY_PAYWALL_URL . 'css/leaky-paywall-subscribers.css', '', LEAKY_PAYWALL_VERSION );
371 }
372
373
374 if ( 'leaky-paywall_page_leaky-paywall-tools' === $hook_suffix ) {
375 wp_enqueue_script( 'leaky_paywall_export_js', LEAKY_PAYWALL_URL . 'js/leaky-paywall-export.js', array( 'jquery', 'jquery-ui-datepicker' ), LEAKY_PAYWALL_VERSION, true );
376 wp_enqueue_media();
377 wp_enqueue_script( 'leaky_paywall_import_js', LEAKY_PAYWALL_URL . 'js/leaky-paywall-import.js', array( 'jquery' ), LEAKY_PAYWALL_VERSION, true );
378 }
379
380 if ( 'leaky-paywall_page_leaky-paywall-insights' === $hook_suffix
381 || 'toplevel_page_issuem-leaky-paywall' === $hook_suffix ) {
382 wp_enqueue_script('leaky_paywall_chart_js', LEAKY_PAYWALL_URL . 'js/chart.min.js', array(), LEAKY_PAYWALL_VERSION, false);
383 }
384
385 wp_localize_script(
386 'leaky_paywall_subscribers_js',
387 'leaky_paywall_notice_ajax',
388 array(
389 'ajaxurl' => admin_url( 'admin-ajax.php' ),
390 'lpNoticeNonce' => wp_create_nonce( 'leaky-paywall-notice-nonce' ),
391 'addSubscriberNonce' => wp_create_nonce( 'leaky_paywall_admin_subscriber_add' ),
392 )
393 );
394
395 if ( 'post.php' === $hook_suffix || 'post-new.php' === $hook_suffix ) {
396 wp_enqueue_script( 'leaky_paywall_post_js', LEAKY_PAYWALL_URL . 'js/issuem-leaky-paywall-post.js', array( 'jquery' ), LEAKY_PAYWALL_VERSION, true );
397 }
398 }
399
400 public function add_type_attribute( $tag, $handle, $src )
401 {
402
403 // Insights script gets the type="module" treatment.
404 if ( 'leaky_paywall_insights' === $handle ) {
405 return '<script type="module" src="' . esc_url( $src ) . '"></script>';
406 }
407
408 // Let publishers inject extra attributes (e.g., data-cookieconsent="ignore"
409 // for Cookiebot, data-ot-ignore for OneTrust) onto any LP-owned script tag
410 // so consent-management platforms don't block functional scripts. Filter
411 // receives an empty array by default; each returned key/value becomes an
412 // attribute on the <script> tag. Only fires for handles we consider ours.
413 $lp_handles = array(
414 'leaky-paywall',
415 'lp-list-builder',
416 'lp-listbuilder-preview',
417 'leaky_paywall_insights',
418 'leaky-paywall-recurring',
419 'lp-offer-engine',
420 'lp-offer-engine-email-admin',
421 // Stripe.js (js.stripe.com/v3/) and LP's Stripe-side registration
422 // glue. Both are required for payment and are 'Necessary' under
423 // GDPR (the visitor is trying to complete a purchase). Including
424 // them here lets publishers whitelist Stripe in one snippet via
425 // the leaky_paywall_script_tag_attributes filter, so their
426 // consent-management platform doesn't block payment scripts.
427 'stripe',
428 'leaky_paywall_stripe_registration',
429 );
430
431 if ( ! in_array( $handle, apply_filters( 'leaky_paywall_owned_script_handles', $lp_handles ), true ) ) {
432 return $tag;
433 }
434
435 $extra_attrs = apply_filters( 'leaky_paywall_script_tag_attributes', array(), $handle, $src );
436
437 if ( empty( $extra_attrs ) || ! is_array( $extra_attrs ) ) {
438 return $tag;
439 }
440
441 $attr_string = '';
442 foreach ( $extra_attrs as $key => $value ) {
443 $attr_string .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
444 }
445
446 // Inject the new attributes right after the opening <script tag.
447 return preg_replace( '/^<script\b/', '<script' . $attr_string, $tag, 1 );
448 }
449
450
451 /**
452 * Enqueues frontend scripts and styles
453 *
454 * @since 1.0.0
455 */
456 public function frontend_scripts() {
457
458 $settings = get_leaky_paywall_settings();
459
460 if ( 'default' === $settings['css_style'] ) {
461 wp_enqueue_style( 'issuem-leaky-paywall', LEAKY_PAYWALL_URL . '/css/issuem-leaky-paywall.css', '', LEAKY_PAYWALL_VERSION );
462 }
463
464 if ( 'on' === $settings['enable_js_cookie_restrictions'] ) {
465
466 if ( is_home() || is_front_page() || is_archive() ) {
467 return;
468 }
469
470 $post_container = apply_filters( 'leaky_paywall_js_restriction_post_container', $settings['js_restrictions_post_container'] );
471 $page_container = apply_filters( 'leaky_paywall_js_restriction_page_container', $settings['js_restrictions_page_container'] );
472 $lead_in_elements = apply_filters( 'leaky_paywall_js_restriction_lead_in_elements', $settings['lead_in_elements'] );
473
474 $check_deps = array();
475 if ( wp_script_is( 'lp-list-builder', 'registered' ) ) {
476 $check_deps[] = 'lp-list-builder';
477 }
478
479 wp_enqueue_script(
480 'leaky-paywall-check',
481 LEAKY_PAYWALL_URL . 'js/leaky-paywall-check.js',
482 $check_deps,
483 LEAKY_PAYWALL_VERSION,
484 true
485 );
486
487 wp_localize_script(
488 'leaky-paywall-check',
489 'leaky_paywall_check_config',
490 array(
491 'rest_url' => rest_url( 'leaky-paywall/v1/check-restrictions' ),
492 'nonce' => wp_create_nonce( 'wp_rest' ),
493 'post_container' => $post_container,
494 'page_container' => $page_container,
495 'lead_in_elements' => $lead_in_elements,
496 )
497 );
498
499 // Hide content before JS restriction check to prevent CLS.
500 $container = is_page() ? $page_container : $post_container;
501 $selectors = array_filter( array_map( 'trim', explode( ',', $container ) ) );
502 $hide_css = '';
503
504 foreach ( $selectors as $selector ) {
505 $hide_css .= '.single ' . $selector . ' { visibility: hidden; }';
506 }
507
508 wp_register_style( 'leaky-paywall-restrictions', false );
509 wp_enqueue_style( 'leaky-paywall-restrictions' );
510 wp_add_inline_style( 'leaky-paywall-restrictions', $hide_css );
511 }
512
513 wp_enqueue_script( 'zeen101_micromodal', LEAKY_PAYWALL_URL . 'js/micromodal.min.js', array('jquery'), LEAKY_PAYWALL_VERSION, true);
514 wp_enqueue_script( 'leaky_paywall_validate', LEAKY_PAYWALL_URL . 'js/leaky-paywall-validate.js', array( 'jquery' ), LEAKY_PAYWALL_VERSION, true );
515 wp_enqueue_script( 'leaky_paywall_script', LEAKY_PAYWALL_URL . 'js/script.js', array( 'jquery' ), LEAKY_PAYWALL_VERSION, true );
516
517 wp_localize_script(
518 'leaky_paywall_validate',
519 'leaky_paywall_validate_ajax',
520 array(
521 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
522 'register_nonce' => wp_create_nonce( 'lp_register_nonce' ),
523 'password_text' => esc_html__('Passwords do not match.', 'leaky-paywall')
524 )
525 );
526
527 wp_localize_script(
528 'leaky_paywall_script',
529 'leaky_paywall_script_ajax',
530 array(
531 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ),
532 'stripe_pk' => leaky_paywall_get_stripe_public_key(),
533 )
534 );
535
536 $gateways = new Leaky_Paywall_Payment_Gateways();
537
538 if ( ( $gateways->is_gateway_enabled( 'stripe' ) || $gateways->is_gateway_enabled('stripe_checkout') ) && leaky_paywall_get_stripe_public_key() ) {
539
540 wp_enqueue_script('leaky_paywall_stripe_registration', LEAKY_PAYWALL_URL . 'js/stripe-registration.js', array('jquery', 'stripe'), LEAKY_PAYWALL_VERSION, true);
541
542 wp_localize_script(
543 'leaky_paywall_stripe_registration',
544 'leaky_paywall_stripe_registration_ajax',
545 array(
546 'ajaxurl' => admin_url('admin-ajax.php', 'relative'),
547 'stripe_pk' => leaky_paywall_get_stripe_public_key(),
548 'continue_text' => esc_html__('Processing... Please Wait', 'leaky-paywall'),
549 'next_text' => esc_html__('Next', 'leaky-paywall'),
550 'billing_address' => $settings['stripe_billing_address'],
551 'redirect_url' => get_page_link($settings['page_for_profile']),
552 'client_id' => ( 'live' === leaky_paywall_get_current_mode() && ! empty( $settings['connected_account_id'] ) ) ? $settings['connected_account_id'] : '',
553 'automatic_tax_enabled' => ( 'on' === $settings['stripe_automatic_tax'] && 'on' === $settings['stripe_billing_address'] ) ? 'on' : 'off',
554 'tax_preview_nonce' => wp_create_nonce( 'lp_tax_preview' ),
555 )
556 );
557
558 }
559 }
560
561 /**
562 * Check if zeen101's Leaky Paywall MultiSite options are enabled
563 *
564 * @since CHANGEME
565 */
566 public function is_site_wide_enabled() {
567 return ( is_multisite() ) ? get_site_option( 'issuem-leaky-paywall-site-wide' ) : false;
568 }
569
570 /**
571 * Create and Display Leaky Paywall Subscribers page
572 *
573 * @since 1.0.0
574 */
575 public function subscribers_page() {
576 global $blog_id;
577 $settings = get_leaky_paywall_settings();
578
579 if ( is_multisite_premium() && ! is_main_site( $blog_id ) ) {
580 $site = '_' . $blog_id;
581 } else {
582 $site = '';
583 }
584
585 $date_format = 'F j, Y';
586 $jquery_date_format = leaky_paywall_jquery_datepicker_format( $date_format );
587 $headings = apply_filters( 'leaky_paywall_bulk_add_headings', array( 'username', 'email', 'price', 'expires', 'status', 'level-id', 'subscriber-id' ) );
588
589 $mode = 'off' === $settings['test_mode'] ? 'live' : 'test';
590
591 $this->display_zeen101_dot_com_leaky_rss_item();
592
593 ?>
594
595 <div id="lp-header" class="lp-header">
596 <div id="lp-header-wrapper">
597 <span id="lp-header-branding">
598 <img class="lp-header-logo" width="200" src="<?php echo esc_url( LEAKY_PAYWALL_URL ) . '/images/leaky-paywall-logo.png'; ?>">
599 </span>
600 <span class="lp-header-page-title-wrap">
601 <span class="lp-header-separator">/</span>
602 <h1 class="lp-header-page-title">Subscribers</h1>
603 </span>
604 </div>
605 </div>
606
607
608 <div class="wrap">
609
610 <?php
611 if ( ! empty( $_POST['leaky_paywall_add_subscriber'] ) ) {
612 if ( ! wp_verify_nonce( sanitize_key( $_POST['leaky_paywall_add_subscriber'] ), 'add_new_subscriber' ) ) {
613 echo '<div class="error settings-error" id="setting-error-invalid_nonce"><p><strong>' . esc_html__( 'Unable to verify security token. Subscriber not added. Please try again.', 'leaky-paywall' ) . '</strong></p></div>';
614 } else {
615 // process form data.
616 if (
617 ! empty( $_POST['leaky-paywall-subscriber-email'] ) && is_email( trim( rawurldecode( sanitize_email( wp_unslash( $_POST['leaky-paywall-subscriber-email'] ) ) ) ) )
618 && ! empty( $_POST['leaky-paywall-subscriber-login'] )
619 ) {
620
621 $login = isset( $_POST['leaky-paywall-subscriber-login'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-login'] ) ) : '';
622 $email = isset( $_POST['leaky-paywall-subscriber-email'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-email'] ) ) : '';
623 $payment_gateway = isset( $_POST['leaky-paywall-subscriber-payment-gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-payment-gateway'] ) ) : '';
624 $subscriber_id = isset( $_POST['leaky-paywall-subscriber-id'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-id'] ) ) : '';
625 if ( empty( $_POST['leaky-paywall-subscriber-expires'] ) ) {
626 $expires = 0;
627 } else {
628 $expires = gmdate( 'Y-m-d 23:59:59', strtotime( trim( urldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-expires'] ) ) ) ) ) );
629 }
630
631 $meta = array(
632 'level_id' => isset( $_POST['leaky-paywall-subscriber-level-id'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-level-id'] ) ) : '',
633 'subscriber_id' => $subscriber_id,
634 'price' => isset( $_POST['leaky-paywall-subscriber-price'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-price'] ) ) : '',
635 'description' => __( 'Manual Addition', 'issuem-leaky-paywall' ),
636 'expires' => $expires,
637 'payment_gateway' => $payment_gateway,
638 'payment_status' => isset( $_POST['leaky-paywall-subscriber-status'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-status'] ) ) : '',
639 'interval' => 0,
640 'plan' => '',
641 'site' => $site,
642 );
643
644 $user_id = leaky_paywall_new_subscriber( null, $email, $subscriber_id, $meta, $login );
645
646 do_action( 'add_leaky_paywall_subscriber', $user_id );
647
648 echo '<div class="updated notice is-dismissible" id="message"><p><strong>' . esc_html__( 'Subscriber added.', 'leaky-paywall' ) . '</strong></p></div>';
649 } else {
650
651 echo '<div class="error settings-error" id="setting-error-missing_email"><p><strong>' . esc_html__( 'You must include a valid email address.', 'leaky-paywall' ) . '</strong></p></div>';
652 }
653 }
654 } elseif ( ! empty( $_POST['leaky_paywall_edit_subscriber'] ) ) {
655
656 if ( ! wp_verify_nonce( sanitize_key( $_POST['leaky_paywall_edit_subscriber'] ), 'edit_subscriber' ) ) {
657 echo '<div class="error settings-error" id="setting-error-invalid_nonce"><p><strong>' . esc_html__( 'Unable to verify security token. Subscriber not added. Please try again.', 'leaky-paywall' ) . '</strong></p></div>';
658 } else {
659 // process form data.
660 if (
661 ! empty( $_POST['leaky-paywall-subscriber-email'] ) && is_email( trim( rawurldecode( sanitize_email( wp_unslash( $_POST['leaky-paywall-subscriber-email'] ) ) ) ) )
662 && ! empty( $_POST['leaky-paywall-subscriber-original-email'] ) && is_email( trim( rawurldecode( sanitize_email( wp_unslash( $_POST['leaky-paywall-subscriber-original-email'] ) ) ) ) )
663 && ! empty( $_POST['leaky-paywall-subscriber-login'] ) && ! empty( $_POST['leaky-paywall-subscriber-original-login'] )
664 ) {
665
666 $orig_login = isset( $_POST['leaky-paywall-subscriber-original-login'] ) ? trim( rawurldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-original-login'] ) ) ) ) : '';
667 $orig_email = isset( $_POST['leaky-paywall-subscriber-original-email'] ) ? trim( rawurldecode( sanitize_email( wp_unslash( $_POST['leaky-paywall-subscriber-original-email'] ) ) ) ) : '';
668 $user = get_user_by( 'email', $orig_email );
669
670 if ( ! empty( $user ) ) {
671 $new_login = isset( $_POST['leaky-paywall-subscriber-login'] ) ? trim( rawurldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-login'] ) ) ) ) : '';
672 $new_email = isset( $_POST['leaky-paywall-subscriber-email'] ) ? trim( rawurldecode( sanitize_email( wp_unslash( $_POST['leaky-paywall-subscriber-email'] ) ) ) ) : '';
673 $price = isset( $_POST['leaky-paywall-subscriber-price'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-price'] ) ) : '';
674 $status = isset( $_POST['leaky-paywall-subscriber-status'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-status'] ) ) : '';
675 $payment_gateway = isset( $_POST['leaky-paywall-subscriber-payment-gateway'] ) ? trim( rawurldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-payment-gateway'] ) ) ) ) : '';
676 $subscriber_id = isset( $_POST['leaky-paywall-subscriber-id'] ) ? trim( rawurldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-id'] ) ) ) ) : '';
677 $plan = isset( $_POST['leaky-paywall-plan'] ) ? sanitize_text_field( wp_unslash( $_POST['leaky-paywall-plan'] ) ) : '';
678
679 if ( empty( $_POST['leaky-paywall-subscriber-expires'] ) ) {
680 $expires = 0;
681 } else {
682 $expires = gmdate( 'Y-m-d 23:59:59', strtotime( urldecode( sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-expires'] ) ) ) ) );
683 }
684
685 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_price' . $site, true ) !== $price ) {
686 update_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_price' . $site, $price );
687 }
688 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_expires' . $site, true ) !== $expires ) {
689 update_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_expires' . $site, $expires );
690 }
691 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_payment_status' . $site, true ) !== $status ) {
692 leaky_paywall_set_subscriber_status( $user->ID, $status, 'registration' );
693 }
694 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_payment_gateway' . $site, true ) !== $payment_gateway ) {
695 update_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_payment_gateway' . $site, $payment_gateway );
696 }
697 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_subscriber_id' . $site, true ) !== $subscriber_id ) {
698 update_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_subscriber_id' . $site, $subscriber_id );
699 }
700 if ( get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_plan' . $site, true ) !== $plan ) {
701 update_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_plan' . $site, $plan );
702 }
703
704 if ( $orig_email !== $new_email ) {
705 $args = array( 'ID' => $user->ID );
706 $args['user_email'] = ( $orig_email === $new_email ) ? $orig_email : $new_email;
707
708 $user_id = wp_update_user( $args );
709 }
710
711 if ( $orig_login !== $new_login ) {
712 global $wpdb;
713 $wpdb->update(
714 $wpdb->users,
715 array( 'user_login' => $new_login ),
716 array( 'ID' => $user->ID ),
717 array( '%s' ),
718 array( '%d' )
719 );
720 clean_user_cache( $user->ID );
721 }
722
723 if ( isset( $_POST['leaky-paywall-subscriber-level-id'] ) ) {
724 leaky_paywall_set_subscriber_level( $user->ID, sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-level-id'] ) ), 'admin' );
725 }
726
727 if ( isset( $_POST['leaky-paywall-subscriber-notes'] ) ) {
728 update_user_meta( $user->ID, '_leaky_paywall_subscriber_notes', sanitize_text_field( wp_unslash( $_POST['leaky-paywall-subscriber-notes'] ) ) );
729 }
730
731 do_action( 'update_leaky_paywall_subscriber', $user->ID );
732
733 echo '<div class="updated notice is-dismissible" id="message"><p><strong>' . esc_html__( 'Subscriber updated.', 'leaky-paywall' ) . '</strong></p></div>';
734 }
735 } else {
736
737 echo '<div class="error settings-error" id="setting-error-missing_email"><p><strong>' . esc_html__( 'You must include a valid email address.', 'leaky-paywall' ) . '</strong></p></div>';
738 }
739 }
740 }
741
742 // Create an instance of our package class...
743 $subscriber_table = new Leaky_Paywall_Subscriber_List_Table();
744 $pagenum = $subscriber_table->get_pagenum();
745 // Fetch, prepare, sort, and filter our data...
746 $subscriber_table->prepare_items();
747 $total_pages = $subscriber_table->get_pagination_arg( 'total_pages' );
748 if ( $pagenum > $total_pages && $total_pages > 0 ) {
749 wp_safe_redirect( esc_url_raw( add_query_arg( 'paged', $total_pages ) ) );
750 exit();
751 }
752
753 ?>
754
755 <div id="leaky-paywall-subscriber-add-edit">
756 <?php
757
758 $email = '';
759
760 if ( isset( $_GET['edit'] ) ) {
761 $email = rawurldecode( sanitize_email( wp_unslash( $_GET['edit'] ) ) );
762 }
763
764 $user = get_user_by( 'email', $email );
765
766 if ( ! empty( $email ) && ! empty( $user ) ) {
767
768 $login = $user->user_login;
769
770 $subscriber_id = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_subscriber_id' . $site, true );
771 $plan = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_plan' . $site, true );
772 $subscriber_level_id = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_level_id' . $site, true );
773 $payment_status = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_payment_status' . $site, true );
774 $payment_gateway = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_payment_gateway' . $site, true );
775 $price = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_price' . $site, true );
776 $expires = get_user_meta( $user->ID, '_issuem_leaky_paywall_' . $mode . '_expires' . $site, true );
777 $subscriber_notes = get_user_meta( $user->ID, '_leaky_paywall_subscriber_notes', true );
778
779 if ( '0000-00-00 00:00:00' === $expires ) {
780 $expires = '';
781 } else {
782 $expires = mysql2date( $date_format, $expires, false );
783 }
784
785 ?>
786 <form id="leaky-paywall-susbcriber-edit" name="leaky-paywall-subscriber-edit" method="post">
787 <div style="display: table">
788 <p><label for="leaky-paywall-subscriber-login" style="display:table-cell"><?php esc_html_e( 'Username (required)', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-login" class="regular-text" type="text" value="<?php echo esc_attr( $login ); ?>" name="leaky-paywall-subscriber-login" /></p><input id="leaky-paywall-subscriber-original-login" type="hidden" value="<?php echo esc_attr( $login ); ?>" name="leaky-paywall-subscriber-original-login" /></p>
789 <p><label for="leaky-paywall-subscriber-email" style="display:table-cell"><?php esc_html_e( 'Email Address (required)', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-email" class="regular-text" type="text" value="<?php echo esc_attr( $email ); ?>" placeholder="support@zeen101.com" name="leaky-paywall-subscriber-email" /></p><input id="leaky-paywall-subscriber-original-email" type="hidden" value="<?php echo esc_attr( $email ); ?>" name="leaky-paywall-subscriber-original-email" /></p>
790 <p><label for="leaky-paywall-subscriber-price" style="display:table-cell"><?php esc_html_e( 'Price Paid', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-price" class="regular-text" type="text" value="<?php echo esc_attr( $price ); ?>" placeholder="0.00" name="leaky-paywall-subscriber-price" /></p>
791 <p>
792 <label for="leaky-paywall-subscriber-expires" style="display:table-cell"><?php esc_html_e( 'Expires', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-expires" class="regular-text datepicker" type="text" value="<?php echo esc_attr( $expires ); ?>" placeholder="<?php echo esc_attr( gmdate( $date_format, time() ) ); ?>" name="leaky-paywall-subscriber-expires" autocomplete="off" />
793 <input type="hidden" name="date_format" value="<?php echo esc_attr( $jquery_date_format ); ?>" />
794 <br><span style="color: #999;"><?php esc_html_e( 'Enter 0 for never expires', 'leaky-paywall' ); ?></span>
795 </p>
796 <p>
797 <label for="leaky-paywall-subscriber-level-id" style="display:table-cell"><?php esc_html_e( 'Subscription Level', 'leaky-paywall' ); ?></label>
798 <select name="leaky-paywall-subscriber-level-id">
799 <?php
800 foreach ( $settings['levels'] as $key => $level ) {
801 if ( ! $level['label'] ) {
802 continue;
803 }
804 echo '<option value="' . esc_attr( $key ) . '" ' . selected( $key, $subscriber_level_id, true ) . '>' . esc_html( stripslashes( $level['label'] ) );
805 echo isset($level['deleted']) && $level['deleted'] == 1 ? '(deleted)' : '';
806 echo '</option>';
807 }
808 ?>
809 </select>
810 </p>
811 <p>
812 <label for="leaky-paywall-subscriber-status" style="display:table-cell"><?php esc_html_e( 'Payment Status', 'leaky-paywall' ); ?></label>
813 <select name="leaky-paywall-subscriber-status">
814 <option value="active" <?php selected( 'active', $payment_status ); ?>><?php esc_html_e( 'Active', 'leaky-paywall' ); ?></option>
815 <option value="pending_cancel" <?php selected( 'pending_cancel', $payment_status ); ?>><?php esc_html_e( 'Pending Cancel', 'leaky-paywall' ); ?></option>
816 <option value="trial" <?php selected( 'trial', $payment_status ); ?>><?php esc_html_e( 'Trial', 'leaky-paywall' ); ?></option>
817 <option value="past_due" <?php selected( 'past_due', $payment_status ); ?>><?php esc_html_e( 'Past Due', 'leaky-paywall' ); ?></option>
818 <option value="canceled" <?php selected( 'canceled', $payment_status ); ?>><?php esc_html_e( 'Canceled', 'leaky-paywall' ); ?></option>
819 <option value="expired" <?php selected( 'expired', $payment_status ); ?>><?php esc_html_e( 'Expired', 'leaky-paywall' ); ?></option>
820 <option value="deactivated" <?php selected( 'deactivated', $payment_status ); ?>><?php esc_html_e( 'Deactivated', 'leaky-paywall' ); ?></option>
821 </select>
822 </p>
823 <p>
824 <label for="leaky-paywall-subscriber-payment-gateway" style="display:table-cell"><?php esc_html_e( 'Payment Method', 'leaky-paywall' ); ?></label>
825 <?php $payment_gateways = leaky_paywall_payment_gateways(); ?>
826 <select name="leaky-paywall-subscriber-payment-gateway">
827 <?php
828 foreach ( $payment_gateways as $key => $gateway ) {
829 echo '<option value="' . esc_attr( $key ) . '" ' . selected( $key, $payment_gateway, false ) . '>' . esc_html( $gateway ) . '</option>';
830 }
831 ?>
832 </select>
833 </p>
834 <p>
835 <label for="leaky-paywall-subscriber-id" style="display:table-cell"><?php esc_html_e( 'Subscriber ID', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-id" class="regular-text" type="text" value="<?php echo esc_attr( $subscriber_id ); ?>" name="leaky-paywall-subscriber-id" />
836 </p>
837 <p>
838 <label for="leaky-paywall-plan" style="display:table-cell"><?php esc_html_e( 'Plan', 'leaky-paywall' ); ?></label><input id="leaky-paywall-plan" class="regular-text" type="text" value="<?php echo esc_attr( $plan ); ?>" name="leaky-paywall-plan" />
839 <br><span style="color: #999;"><?php esc_html_e( 'Leave empty for Non-Recurring', 'leaky-paywall' ); ?></span>
840 </p>
841 <p>
842 <label for="leaky-paywall-subscriber-notes" style="display:table-cell"><?php esc_html_e( 'Subscriber Notes', 'leaky-paywall' ); ?></label>
843 <textarea id="leaky-paywall-subscriber-notes" class="regular-text" name="leaky-paywall-subscriber-notes"><?php echo esc_html( $subscriber_notes ); ?></textarea>
844 </p>
845 <?php do_action( 'update_leaky_paywall_subscriber_form', $user->ID ); ?>
846 </div>
847 <?php submit_button( 'Update Subscriber' ); ?>
848 <p>
849 <a href="<?php echo esc_url( remove_query_arg( 'edit' ) ); ?>"><?php esc_html_e( 'Cancel', 'leaky-paywall' ); ?></a>
850 </p>
851 <?php wp_nonce_field( 'edit_subscriber', 'leaky_paywall_edit_subscriber' ); ?>
852 </form>
853 <?php } else { ?>
854 <form id="leaky-paywall-susbcriber-add" name="leaky-paywall-subscriber-add" method="post">
855 <div style="display: table">
856 <p><label for="leaky-paywall-subscriber-login" style="display:table-cell"><?php esc_html_e( 'Username (required)', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-login" class="regular-text" type="text" value="" name="leaky-paywall-subscriber-login" /></p>
857 <p><label for="leaky-paywall-subscriber-email" style="display:table-cell"><?php esc_html_e( 'Email Address (required)', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-email" class="regular-text" type="text" value="" placeholder="support@zeen101.com" name="leaky-paywall-subscriber-email" /></p>
858 <p><label for="leaky-paywall-subscriber-price" style="display:table-cell"><?php esc_html_e( 'Price Paid', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-price" class="regular-text" type="text" value="" placeholder="0.00" name="leaky-paywall-subscriber-price" /></p>
859 <p>
860 <label for="leaky-paywall-subscriber-expires" style="display:table-cell"><?php esc_html_e( 'Expires', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-expires" class="regular-text datepicker" type="text" value="" placeholder="<?php echo esc_attr( gmdate( $date_format, time() ) ); ?>" name="leaky-paywall-subscriber-expires" autocomplete="off" />
861 <input type="hidden" name="date_format" value="<?php echo esc_attr( $jquery_date_format ); ?>" />
862 <br><span style="color: #999;"><?php esc_html_e( 'Enter 0 for never expires', 'leaky-paywall' ); ?></span>
863 </p>
864 <p>
865 <label for="leaky-paywall-subscriber-level-id" style="display:table-cell"><?php esc_html_e( 'Subscription Level', 'leaky-paywall' ); ?></label>
866 <select name="leaky-paywall-subscriber-level-id">
867 <?php
868 foreach ( $settings['levels'] as $key => $level ) {
869 if ( ! $level['label'] ) {
870 continue;
871 }
872 if (isset($level['deleted']) ) {
873 continue;
874 }
875 echo '<option value="' . esc_attr( $key ) . '">' . esc_html( stripslashes( $level['label'] ) );
876 echo isset( $level['deleted'] ) && $level['deleted'] == 1 ? '(deleted)' : '';
877 echo '</option>';
878 }
879 ?>
880 </select>
881 </p>
882 <p>
883 <label for="leaky-paywall-subscriber-status" style="display:table-cell"><?php esc_html_e( 'Payment Status', 'leaky-paywall' ); ?></label>
884 <select name="leaky-paywall-subscriber-status">
885 <option value="active"><?php esc_html_e( 'Active', 'leaky-paywall' ); ?></option>
886 <option value="pending_cancel"><?php esc_html_e( 'Pending Cancel', 'leaky-paywall' ); ?></option>
887 <option value="trial"><?php esc_html_e( 'Trial', 'leaky-paywall' ); ?></option>
888 <option value="past_due"><?php esc_html_e( 'Past Due', 'leaky-paywall' ); ?></option>
889 <option value="canceled"><?php esc_html_e( 'Canceled', 'leaky-paywall' ); ?></option>
890 <option value="expired"><?php esc_html_e( 'Expired', 'leaky-paywall' ); ?></option>
891 <option value="deactivated"><?php esc_html_e( 'Deactivated', 'leaky-paywall' ); ?></option>
892 </select>
893 </p>
894 <p>
895 <label for="leaky-paywall-subscriber-payment-gateway" style="display:table-cell"><?php esc_html_e( 'Payment Method', 'leaky-paywall' ); ?></label>
896 <?php $payment_gateways = leaky_paywall_payment_gateways(); ?>
897 <select name="leaky-paywall-subscriber-payment-gateway">
898 <?php
899 foreach ( $payment_gateways as $key => $gateway ) {
900 echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $gateway ) . '</option>';
901 }
902 ?>
903 </select>
904 </p>
905 <p>
906 <label for="leaky-paywall-subscriber-id" style="display:table-cell"><?php esc_html_e( 'Subscriber ID', 'leaky-paywall' ); ?></label><input id="leaky-paywall-subscriber-id" class="regular-text" type="text" value="" name="leaky-paywall-subscriber-id" />
907 </p>
908 <?php do_action( 'add_leaky_paywall_subscriber_form' ); ?>
909 </div>
910 <?php submit_button( 'Add New Subscriber' ); ?>
911 <?php wp_nonce_field( 'add_new_subscriber', 'leaky_paywall_add_subscriber' ); ?>
912 </form>
913
914 <?php do_action( 'leaky_paywall_after_new_subscriber_form' ); ?>
915
916 <?php } ?>
917 <br class="clear">
918 </div>
919
920 <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
921 <form id="leaky-paywall-subscribers" method="get">
922 <!-- For plugins, we also need to ensure that the form posts back to our current page -->
923 <input type="hidden" name="page" value="<?php echo isset( $_GET['page'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_GET['page'] ) ) ) : ''; ?>" />
924 <!-- Now we can render the completed list table -->
925 <div class="tablenav top">
926 <?php $subscriber_table->user_views(); ?>
927 <?php $subscriber_table->search_box( __( 'Search Subscribers' ), 'leaky-paywall' ); ?>
928 </div>
929 <?php $subscriber_table->display(); ?>
930 </form>
931
932 </div>
933 <?php
934
935 }
936
937 /**
938 * Outputs the Leaky Paywall Add Ons page
939 *
940 * @since 3.1.3
941 */
942 public function insights_page() {
943 ?>
944 <div id="lp-wit-app">
945
946 <div class="wrap">
947
948 <app-stats></app-stats>
949
950 </div>
951
952 </div>
953 <?php
954
955 }
956
957 /**
958 * Display admin notice when the standalone Multiple Levels plugin is still active.
959 */
960 public function multiple_levels_deactivation_notice() {
961 if ( is_plugin_active( 'leaky-paywall-multiple-levels/leaky-paywall-multiple-levels.php' ) ) {
962 echo '<div class="notice notice-info is-dismissible">';
963 echo '<p><strong>Leaky Paywall:</strong> Multiple Levels is now built into Leaky Paywall. You can safely deactivate and delete the <em>Leaky Paywall - Multiple Levels</em> plugin.</p>';
964 echo '</div>';
965 }
966 }
967
968 /**
969 * Display admin notice when the standalone Reporting Tool plugin is still active.
970 */
971 public function reporting_tool_deactivation_notice() {
972 if ( is_plugin_active( 'leaky-paywall-reporting-tool/leaky-paywall-reporting-tool.php' ) ) {
973 echo '<div class="notice notice-warning is-dismissible">';
974 echo '<p><strong>Leaky Paywall:</strong> The Reporting Tool is now built into Leaky Paywall under <strong>Tools &gt; Export</strong>. Please deactivate and delete the <em>Leaky Paywall - Reporting Tool</em> plugin. Its own export downloads no longer work, because the folder it saved them to is now closed to direct access.</p>';
975 echo '</div>';
976 }
977 }
978
979 /**
980 * Remove the old Reporting Tool submenu when the plugin is still active.
981 */
982 public function suppress_legacy_reporting_tool_menu() {
983 if ( is_plugin_active( 'leaky-paywall-reporting-tool/leaky-paywall-reporting-tool.php' ) ) {
984 remove_submenu_page( 'issuem-leaky-paywall', 'reporting-tool' );
985 }
986 }
987
988 /**
989 * Display admin notice when the standalone Bulk Import plugin is still active.
990 */
991 public function bulk_import_deactivation_notice() {
992 if ( is_plugin_active( 'leaky-paywall-bulk-import-subscribers/leaky-paywall-bulk-import-subscribers.php' ) ) {
993 echo '<div class="notice notice-info is-dismissible">';
994 echo '<p><strong>Leaky Paywall:</strong> Bulk Import is now built into Leaky Paywall under <strong>Tools &gt; Import</strong>. You can safely deactivate and delete the <em>Leaky Paywall - Bulk Import Subscribers</em> plugin.</p>';
995 echo '</div>';
996 }
997 }
998
999 /**
1000 * Remove the old Bulk Import submenu when the plugin is still active.
1001 */
1002 public function suppress_legacy_bulk_import_menu() {
1003 if ( is_plugin_active( 'leaky-paywall-bulk-import-subscribers/leaky-paywall-bulk-import-subscribers.php' ) ) {
1004 remove_submenu_page( 'issuem-leaky-paywall', 'lp-bulk-import' );
1005 }
1006 }
1007
1008 /**
1009 * Outputs the Leaky Paywall Add Ons page
1010 *
1011 * @since 3.1.3
1012 */
1013 public function upgrade_page() {
1014 ?>
1015 <div id="leaky-paywall-upgrade-page-wrapper">
1016 <div class="lp-upgrade-header">
1017 <img src="<?php echo esc_url( LEAKY_PAYWALL_URL ) . '/images/leaky-paywall-logo.png'; ?>" width="200" alt="Leaky Paywall">
1018 </div>
1019 <div class="lp-upgrade-card">
1020 <h2><?php esc_html_e( 'Upgrade to Leaky Paywall Pro', 'leaky-paywall' ); ?></h2>
1021 <p class="lp-upgrade-tagline">
1022 <?php esc_html_e( 'Gain access to our proven subscription building system and 40+ Leaky Paywall extensions when you upgrade.', 'leaky-paywall' ); ?>
1023 </p>
1024 <ul>
1025 <li><?php esc_html_e( 'Personal setup meeting and priority support', 'leaky-paywall' ); ?></li>
1026 <li><?php esc_html_e( 'One-on-one strategic support meeting', 'leaky-paywall' ); ?></li>
1027 <li><?php esc_html_e( 'Free-to-paid subscription plans, donations, pay per article, timewall, and flipbook access', 'leaky-paywall' ); ?></li>
1028 <li><?php esc_html_e( 'Add smart on-site subscriber level targeting for your promotions', 'leaky-paywall' ); ?></li>
1029 <li><?php esc_html_e( 'Group and corporate access plans', 'leaky-paywall' ); ?></li>
1030 <li><?php esc_html_e( 'Paywall hardening to stop incognito browsing', 'leaky-paywall' ); ?></li>
1031 <li><?php esc_html_e( 'Integrations with CRMs, circulation software, and payment gateways', 'leaky-paywall' ); ?></li>
1032 <li><?php esc_html_e( 'Sell single purchase access to multiple websites', 'leaky-paywall' ); ?></li>
1033 </ul>
1034 <p>
1035 <a class="lp-upgrade-button" target="_blank" href="https://leakypaywall.com/upgrade-to-leaky-paywall-pro/?utm_medium=plugin&utm_source=upgrade&utm_campaign=settings"><?php esc_html_e( 'Upgrade Now', 'leaky-paywall' ); ?></a>
1036 </p>
1037 </div>
1038 </div>
1039
1040 <?php
1041
1042 }
1043
1044 /**
1045 * Display paypal setup notice in WP admin
1046 */
1047 public function paypal_standard_secure_notice() {
1048 if ( current_user_can( 'manage_options' ) ) {
1049 ?>
1050 <div id="missing-paypal-settings" class="update-nag notice">
1051 <?php
1052 $settings_link = esc_url(
1053 add_query_arg(
1054 array(
1055 'page' => 'issuem-leaky-paywall',
1056 'tab' => 'payments',
1057 ),
1058 admin_url( 'admin.php' )
1059 )
1060 );
1061 /* Translators: %s - url for settings */
1062 printf( esc_attr__( 'Please complete your PayPal setup for Leaky Paywall. %s.', 'leaky-paywall' ), '<a class="btn" href="' . esc_url( $settings_link ) . '">' . esc_html__( 'Complete Your Setup Now', 'leaky-paywall' ) . '</a>' );
1063 ?>
1064 </div>
1065 <?php
1066 }
1067 }
1068
1069
1070 /**
1071 * Displays latest RSS item from Zeen101.com on Subscriber page
1072 *
1073 * @since 1.0.0
1074 */
1075 public function display_zeen101_dot_com_leaky_rss_item() {
1076 $current_user = wp_get_current_user();
1077
1078 $hide = get_user_meta( $current_user->ID, 'leaky_paywall_rss_item_notice_link', true );
1079
1080 if ( 1 === $hide ) {
1081 return;
1082 }
1083
1084 $last_rss_item = get_option( 'last_zeen101_dot_com_leaky_rss_item', true );
1085
1086 if ( $last_rss_item ) {
1087 echo '<div class="notice notice-success">';
1088 echo wp_kses_post( $last_rss_item );
1089 echo '<p><a href="#" class="lp-notice-link" data-notice="rss_item" data-type="dismiss">' . esc_html__( 'Dismiss', 'leaky-paywall' ) . '</a></p>';
1090 echo '</div>';
1091 }
1092 }
1093
1094 /**
1095 * Process ajax calls for notice links
1096 *
1097 * @since 2.0.3
1098 */
1099 public function ajax_process_notice_link() {
1100 $nonce = isset( $_POST['nonce'] ) ? sanitize_key( $_POST['nonce'] ) : '';
1101
1102 if ( ! wp_verify_nonce( $nonce, 'leaky-paywall-notice-nonce' ) ) {
1103 die( 'Busted!' );
1104 }
1105
1106 $current_user = wp_get_current_user();
1107
1108 update_user_meta( $current_user->ID, 'leaky_paywall_rss_item_notice_link', 1 );
1109
1110 exit;
1111 }
1112
1113 public function ajax_add_subscriber() {
1114 $admin_subscriber = new Leaky_Paywall_Admin_Subscriber();
1115 $admin_subscriber->ajax_add_subscriber();
1116 }
1117
1118 /**
1119 * Force SSL version to TLS1.2 when using cURL
1120 *
1121 * Thanks roykho (WooCommerce Commit)
1122 * Thanks olivierbellone (Stripe Engineer)
1123 *
1124 * @param resource $curl the handle.
1125 * @return null
1126 */
1127 public function force_ssl_version( $curl ) {
1128 if ( ! $curl ) {
1129 return;
1130 }
1131
1132 if ( OPENSSL_VERSION_NUMBER >= 0x1000100f ) {
1133 if ( ! defined( 'CURL_SSLVERSION_TLSV1_2' ) ) {
1134 // Note the value 6 comes from its position in the enum that
1135 // defines it in cURL's source code.
1136 define( 'CURL_SSLVERSION_TLSV1_2', 6 ); // constant not defined in PHP < 5.5.
1137 }
1138
1139 curl_setopt( $curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSV1_2 );
1140 } else {
1141 if ( ! defined( 'CURL_SSLVERSION_TLSV1' ) ) {
1142 define( 'CURL_SSLVERSION_TLSV1', 1 ); // constant not defined in PHP < 5.5.
1143 }
1144
1145 curl_setopt( $curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSV1 );
1146 }
1147 }
1148
1149 /**
1150 * Sanitize level settings
1151 *
1152 * @param array $levels The levels to sanitize.
1153 * @return array
1154 */
1155 public function sanitize_levels( $levels ) {
1156 $text_fields = array( 'label', 'deleted', 'price', 'subscription_length_type', 'interval_count', 'interval', 'hide_subscribe_card' );
1157 $textarea_fields = array( 'description', 'registration_form_description' );
1158
1159 foreach ( $levels as $i => $level ) {
1160
1161 foreach ( $level as $key => $value ) {
1162
1163 if ( in_array( $key, $text_fields ) ) {
1164 $levels[ $i ][ $key ] = sanitize_text_field( wp_unslash( $value ) );
1165 }
1166
1167 if ( in_array( $key, $textarea_fields ) ) {
1168 $levels[ $i ][ $key ] = wp_kses_post( wp_unslash( $value ) );
1169 }
1170
1171 if ( 'post_types' == $key ) {
1172 $levels[ $i ][ $key ] = $this->sanitize_level_post_types( $value );
1173 }
1174 }
1175 }
1176
1177 return $levels;
1178 }
1179
1180 /**
1181 * Sanitize level post types
1182 *
1183 * @param array $post_types The post types to sanitize.
1184 */
1185 public function sanitize_level_post_types( $post_types ) {
1186 foreach ( $post_types as $i => $rules ) {
1187 foreach ( $rules as $key => $rule ) {
1188 $post_types[ $i ][ $key ] = sanitize_text_field( $rule );
1189 }
1190 }
1191
1192 return $post_types;
1193 }
1194
1195 /**
1196 * Sanitize restriction settings
1197 *
1198 * @param array $restrictions restrictions settings.
1199 * @return array
1200 */
1201 public function sanitize_restrictions( $restrictions ) {
1202 foreach ( $restrictions as $i => $restriction ) {
1203
1204 foreach ( $restriction as $key => $value ) {
1205
1206 $restrictions[ $i ] [ $key ] = array_map( 'sanitize_text_field', $value );
1207
1208 }
1209 }
1210
1211 return $restrictions;
1212 }
1213 }
1214