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
learnpress / inc / background-process / abstract-lp-async-request.php

abstract-lp-async-request.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.8, at inc/background-process/abstract-lp-async-request.php

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