PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/Background/LPAsyncRequest.php +237 -237 4.3.94.4.8 View file →
@@ -1,237 +1,237 @@
1 -<?php
2 -
3 -namespace LearnPress\Background;
4 -
5 -use WP_Error;
6 -
7 -/**
8 - * Abstract LP_Async_Request class.
9 - *
10 - * This class is used to create asynchronous requests in LearnPress.
11 - * It is recommended to use this class for tasks that can be processed in the background
12 - * It is non-blocking, therefore it does not return data when done.
13 - * Note: don't call too many times on a progress, it can cause server hang.
14 - * Should be considered when using
15 - *
16 - * @since 4.2.8.7 instead of LP_Async_Request since 4.1.6.9.4, only change class name to autoload
17 - * @version 1.0.0
18 - */
19 -abstract class LPAsyncRequest {
20 - /**
21 - * Prefix
22 - * @var string
23 - */
24 - protected $prefix = 'lp';
25 -
26 - /**
27 - * Action
28 - * @var string
29 - */
30 - protected $action = 'async_request';
31 -
32 - /**
33 - * Identifier
34 - *
35 - * @var string
36 - */
37 - protected $identifier;
38 -
39 - /**
40 - * Constant identifier for a task that should be available to logged-in users
41 - */
42 - const LOGGED_IN = 1;
43 -
44 - /**
45 - * Constant identifier for a task that should be available to logged-out users
46 - */
47 - const LOGGED_OUT = 2;
48 -
49 - /**
50 - * Constant identifier for a task that should be available to all users regardless of auth status
51 - */
52 - const BOTH = 3;
53 -
54 - /**
55 - * Data
56 - *
57 - * (default value: array())
58 - *
59 - * @var array
60 - */
61 - protected $data = array();
62 -
63 - /**
64 - * Initiate new async request
65 - */
66 - public function __construct( $auth_level = self::BOTH ) {
67 - $this->identifier = $this->prefix . '_' . $this->action;
68 -
69 - //add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
70 - //add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
71 -
72 - if ( $auth_level & self::LOGGED_IN ) {
73 - add_action( "admin_post_lp_async_$this->identifier", [ $this, 'maybe_handle' ] );
74 - }
75 - if ( $auth_level & self::LOGGED_OUT ) {
76 - add_action( "admin_post_nopriv_lp_async_$this->identifier", [ $this, 'maybe_handle' ] );
77 - }
78 - }
79 -
80 - /**
81 - * Set data used during the request
82 - *
83 - * @param array $data Data.
84 - *
85 - * @return $this
86 - */
87 - public function data( array $data ): LPAsyncRequest {
88 - $this->data = $data;
89 -
90 - return $this;
91 - }
92 -
93 - /**
94 - * Dispatch the async request
95 - *
96 - * @return array|WP_Error
97 - */
98 - public function dispatch() {
99 - $url = esc_url_raw( $this->get_query_url() );
100 - $args = $this->get_post_args();
101 -
102 - return wp_remote_post( $url, $args );
103 - }
104 -
105 - /**
106 - * Get query URL
107 - *
108 - * @return string
109 - */
110 - protected function get_query_url(): string {
111 - if ( property_exists( $this, 'query_url' ) ) {
112 - return $this->query_url;
113 - }
114 -
115 - $url = admin_url( 'admin-post.php' );
116 - return apply_filters( $this->identifier . '/query_url', $url );
117 - }
118 -
119 - /**
120 - * Get post args
121 - *
122 - * @return array
123 - */
124 - protected function get_post_args(): array {
125 - $identifier = $this->identifier;
126 - $this->data['action'] = "lp_async_{$identifier}";
127 - $this->data['_nonce'] = $this->create_async_nonce();
128 -
129 - /**
130 - * Must set timeout to 0.01 to avoid blocking the request.
131 - * Don't change it, because it can make sever hang.
132 - */
133 - $args = array(
134 - 'timeout' => 0.01,
135 - 'blocking' => false,
136 - 'body' => $this->data,
137 - 'cookies' => $_COOKIE,
138 - 'sslverify' => is_ssl(),
139 - );
140 -
141 - /**
142 - * Filters the post arguments used during an async request.
143 - *
144 - * @param array $args
145 - */
146 - return apply_filters( $this->identifier . '_post_args', $args );
147 - }
148 -
149 - /**
150 - * Create nonce for async request
151 - *
152 - * @return false|string
153 - */
154 - protected function create_async_nonce() {
155 - $action = $this->get_nonce_action();
156 - $i = wp_nonce_tick();
157 -
158 - return substr( wp_hash( $i . $action . get_class( $this ), 'nonce' ), - 12, 10 );
159 - }
160 -
161 - /**
162 - * Verify that the correct nonce was used within the time limit.
163 - *
164 - * @param string $nonce
165 - *
166 - * @return bool
167 - */
168 - protected function verify_async_nonce( string $nonce ): bool {
169 - $action = $this->get_nonce_action();
170 - $i = wp_nonce_tick();
171 -
172 - // Nonce generated 0-12 hours ago
173 - if ( substr( wp_hash( $i . $action . get_class( $this ), 'nonce' ), - 12, 10 ) == $nonce ) {
174 - return 1;
175 - }
176 -
177 - // Nonce generated 12-24 hours ago
178 - if ( substr( wp_hash( ( $i - 1 ) . $action . get_class( $this ), 'nonce' ), - 12, 10 ) == $nonce ) {
179 - return 2;
180 - }
181 -
182 - // Invalid nonce
183 - return false;
184 - }
185 -
186 - /**
187 - * Get a nonce action based on the $action property of the class
188 - *
189 - * @return string The nonce action for the current instance
190 - */
191 - protected function get_nonce_action(): string {
192 - $action = $this->identifier;
193 - if ( substr( $action, 0, 7 ) === 'nopriv_' ) {
194 - $action = substr( $action, 7 );
195 - }
196 -
197 - return "lp_async_$action";
198 - }
199 -
200 - /**
201 - * Maybe handle
202 - *
203 - * Check for correct nonce and pass to handler.
204 - */
205 - public function maybe_handle() {
206 - // Don't lock up other requests while processing
207 - session_write_close();
208 -
209 - /**
210 - * set params $_POST['lp_no_check_referer'] = 1
211 - * for case: send request when user not login, but get request when user logged
212 - * @editor tungnx
213 - * @modify 4.1.4
214 - */
215 - /*if ( ! isset( $_POST['lp_no_check_referer'] ) ) {
216 - check_ajax_referer( $this->identifier, 'nonce' );
217 - }*/
218 -
219 - if ( isset( $_POST['_nonce'] ) && $this->verify_async_nonce( $_POST['_nonce'] ) ) {
220 - if ( ! is_user_logged_in() ) {
221 - $this->identifier = "nopriv_$this->identifier";
222 - }
223 -
224 - $this->handle();
225 - }
226 -
227 - wp_die();
228 - }
229 -
230 - /**
231 - * Handle
232 - *
233 - * Override this method to perform any actions required
234 - * during the async request.
235 - */
236 - abstract protected function handle();
237 -}
1 +<?php
2 +
3 +namespace LearnPress\Background;
4 +
5 +use WP_Error;
6 +
7 +/**
8 + * Abstract LP_Async_Request class.
9 + *
10 + * This class is used to create asynchronous requests in LearnPress.
11 + * It is recommended to use this class for tasks that can be processed in the background
12 + * It is non-blocking, therefore it does not return data when done.
13 + * Note: don't call too many times on a progress, it can cause server hang.
14 + * Should be considered when using
15 + *
16 + * @since 4.2.8.7 instead of LP_Async_Request since 4.1.6.9.4, only change class name to autoload
17 + * @version 1.0.0
18 + */
19 +abstract class LPAsyncRequest {
20 + /**
21 + * Prefix
22 + * @var string
23 + */
24 + protected $prefix = 'lp';
25 +
26 + /**
27 + * Action
28 + * @var string
29 + */
30 + protected $action = 'async_request';
31 +
32 + /**
33 + * Identifier
34 + *
35 + * @var string
36 + */
37 + protected $identifier;
38 +
39 + /**
40 + * Constant identifier for a task that should be available to logged-in users
41 + */
42 + const LOGGED_IN = 1;
43 +
44 + /**
45 + * Constant identifier for a task that should be available to logged-out users
46 + */
47 + const LOGGED_OUT = 2;
48 +
49 + /**
50 + * Constant identifier for a task that should be available to all users regardless of auth status
51 + */
52 + const BOTH = 3;
53 +
54 + /**
55 + * Data
56 + *
57 + * (default value: array())
58 + *
59 + * @var array
60 + */
61 + protected $data = array();
62 +
63 + /**
64 + * Initiate new async request
65 + */
66 + public function __construct( $auth_level = self::BOTH ) {
67 + $this->identifier = $this->prefix . '_' . $this->action;
68 +
69 + //add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
70 + //add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
71 +
72 + if ( $auth_level & self::LOGGED_IN ) {
73 + add_action( "admin_post_lp_async_$this->identifier", [ $this, 'maybe_handle' ] );
74 + }
75 + if ( $auth_level & self::LOGGED_OUT ) {
76 + add_action( "admin_post_nopriv_lp_async_$this->identifier", [ $this, 'maybe_handle' ] );
77 + }
78 + }
79 +
80 + /**
81 + * Set data used during the request
82 + *
83 + * @param array $data Data.
84 + *
85 + * @return $this
86 + */
87 + public function data( array $data ): LPAsyncRequest {
88 + $this->data = $data;
89 +
90 + return $this;
91 + }
92 +
93 + /**
94 + * Dispatch the async request
95 + *
96 + * @return array|WP_Error
97 + */
98 + public function dispatch() {
99 + $url = esc_url_raw( $this->get_query_url() );
100 + $args = $this->get_post_args();
101 +
102 + return wp_remote_post( $url, $args );
103 + }
104 +
105 + /**
106 + * Get query URL
107 + *
108 + * @return string
109 + */
110 + protected function get_query_url(): string {
111 + if ( property_exists( $this, 'query_url' ) ) {
112 + return $this->query_url;
113 + }
114 +
115 + $url = admin_url( 'admin-post.php' );
116 + return apply_filters( $this->identifier . '/query_url', $url );
117 + }
118 +
119 + /**
120 + * Get post args
121 + *
122 + * @return array
123 + */
124 + protected function get_post_args(): array {
125 + $identifier = $this->identifier;
126 + $this->data['action'] = "lp_async_{$identifier}";
127 + $this->data['_nonce'] = $this->create_async_nonce();
128 +
129 + /**
130 + * Must set timeout to 0.01 to avoid blocking the request.
131 + * Don't change it, because it can make sever hang.
132 + */
133 + $args = array(
134 + 'timeout' => 0.01,
135 + 'blocking' => false,
136 + 'body' => $this->data,
137 + 'cookies' => $_COOKIE,
138 + 'sslverify' => is_ssl(),
139 + );
140 +
141 + /**
142 + * Filters the post arguments used during an async request.
143 + *
144 + * @param array $args
145 + */
146 + return apply_filters( $this->identifier . '_post_args', $args );
147 + }
148 +
149 + /**
150 + * Create nonce for async request
151 + *
152 + * @return false|string
153 + */
154 + protected function create_async_nonce() {
155 + $action = $this->get_nonce_action();
156 + $i = wp_nonce_tick();
157 +
158 + return substr( wp_hash( $i . $action . get_class( $this ), 'nonce' ), - 12, 10 );
159 + }
160 +
161 + /**
162 + * Verify that the correct nonce was used within the time limit.
163 + *
164 + * @param string $nonce
165 + *
166 + * @return bool
167 + */
168 + protected function verify_async_nonce( string $nonce ): bool {
169 + $action = $this->get_nonce_action();
170 + $i = wp_nonce_tick();
171 +
172 + // Nonce generated 0-12 hours ago
173 + if ( substr( wp_hash( $i . $action . get_class( $this ), 'nonce' ), - 12, 10 ) == $nonce ) {
174 + return 1;
175 + }
176 +
177 + // Nonce generated 12-24 hours ago
178 + if ( substr( wp_hash( ( $i - 1 ) . $action . get_class( $this ), 'nonce' ), - 12, 10 ) == $nonce ) {
179 + return 2;
180 + }
181 +
182 + // Invalid nonce
183 + return false;
184 + }
185 +
186 + /**
187 + * Get a nonce action based on the $action property of the class
188 + *
189 + * @return string The nonce action for the current instance
190 + */
191 + protected function get_nonce_action(): string {
192 + $action = $this->identifier;
193 + if ( substr( $action, 0, 7 ) === 'nopriv_' ) {
194 + $action = substr( $action, 7 );
195 + }
196 +
197 + return "lp_async_$action";
198 + }
199 +
200 + /**
201 + * Maybe handle
202 + *
203 + * Check for correct nonce and pass to handler.
204 + */
205 + public function maybe_handle() {
206 + // Don't lock up other requests while processing
207 + session_write_close();
208 +
209 + /**
210 + * set params $_POST['lp_no_check_referer'] = 1
211 + * for case: send request when user not login, but get request when user logged
212 + * @editor tungnx
213 + * @modify 4.1.4
214 + */
215 + /*if ( ! isset( $_POST['lp_no_check_referer'] ) ) {
216 + check_ajax_referer( $this->identifier, 'nonce' );
217 + }*/
218 +
219 + if ( isset( $_POST['_nonce'] ) && $this->verify_async_nonce( $_POST['_nonce'] ) ) {
220 + if ( ! is_user_logged_in() ) {
221 + $this->identifier = "nopriv_$this->identifier";
222 + }
223 +
224 + $this->handle();
225 + }
226 +
227 + wp_die();
228 + }
229 +
230 + /**
231 + * Handle
232 + *
233 + * Override this method to perform any actions required
234 + * during the async request.
235 + */
236 + abstract protected function handle();
237 +}