PluginProbe
MyRewards / trunk
MyRewards vtrunk
5.7.8 5.7.7 5.7.6 trunk 1.2.2 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.1 2.2.0 2.3.0 2.4.0 2.4.1 2.5.0 2.6.4 2.6.6 3.0.0.0 3.1.0 3.1.2 3.1.2.1 3.10.4 3.10.9 All 165 releases
woorewards / include / pointsflow / action.php

action.php in MyRewards trunk, at include/pointsflow/action.php

281 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace LWS\WOOREWARDS\PointsFlow;
3
4 // don't call the file directly
5 if( !defined( 'ABSPATH' ) ) exit();
6
7 /** Manage Import/Export final process.
8 * Read submitted json for import
9 * and output json from ajax export requests. */
10 class Action
11 {
12 private $importError = false;
13
14 static function register()
15 {
16 $me = new self();
17 \add_action('wp_ajax_'.'woorewards-lite'.'-export-wr', array($me, 'exportWR'));
18 \add_action('wp_ajax_'.'woorewards-lite'.'-export-points', array($me, 'exportPoints'));
19
20 \add_filter('pre_update_option_'.'woorewards-lite'.'_import_file', array($me, 'import'), 9, 3);
21 \add_filter('lws_adminpanel_form_attributes'.LWS_WOOREWARDS_PAGE.'.system', array($me, 'importFormAttributes'));
22 \add_filter('pre_set_transient_settings_errors', array($me, 'importResult'), 999);
23 }
24
25 function importResult($value)
26 {
27 if (false !== $this->importError)
28 {
29 \lws_admin_delete_notice('lws_ap_page');
30 \lws_admin_add_notice_once('woorewards-lite'.'-error', __("Import Error", 'woorewards-lite') . '<br/>' . $this->importError, array('level'=>'error'));
31 }
32 return $value;
33 }
34
35 function importFormAttributes($attrs)
36 {
37 $attrs['enctype']='multipart/form-data';
38 return $attrs;
39 }
40
41 /** @return $oldValue cause WP dont go further with that option. */
42 function import($value, $oldValue, $option)
43 {
44 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified by WP settings API
45 if( !(isset($_POST['lws_wre_points_action']) && 'import' == \sanitize_text_field(\wp_unslash($_POST['lws_wre_points_action']))) )
46 return $oldValue; // we only want a import button click, not a page save
47
48 if( !\current_user_can('manage_options') )
49 {
50 $this->importError = __("You are not allowed to do that", 'woorewards-lite');
51 return $oldValue;
52 }
53 $stack = isset($_REQUEST['woorewards-lite' . '_default_pool']) ? \sanitize_key(\wp_unslash($_REQUEST['woorewards-lite' . '_default_pool'])) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verified by WP settings API
54 if( $stack )
55 {
56 if (\class_exists('\LWS\WOOREWARDS\PRO\Core\Pool')) {
57 $pool = \LWS\WOOREWARDS\PRO\Core\Pool::getOrLoad($stack, false);
58 } else {
59 $pool = \apply_filters('lws_woorewards_get_pools_by_args', false, array(
60 'system' => $stack,
61 'force' => true,
62 ));
63 if ($pool)
64 $pool = $pool->last();
65 }
66 if ($pool)
67 $stack = $pool->getStackId();
68 }
69 else
70 {
71 $this->importError = __("Missing destination loyalty system.", 'woorewards-lite');
72 return $oldValue;
73 }
74
75 $replace = true;
76 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified by WP settings API
77 if (isset($_POST['woorewards-lite' . '_behavior']) && 'add' == \sanitize_text_field(\wp_unslash($_POST['woorewards-lite' . '_behavior'])))
78 $replace = false;
79
80 $key = 'woorewards-lite' . '_import_file';
81 if( isset($_FILES[$key]) && !empty($_FILES[$key]) && !empty($_FILES[$key]['tmp_name']) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified by WP settings API
82 {
83 $filename = \sanitize_file_name(\wp_unslash($_FILES[$key]['name'])); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.Missing
84 if( !empty($_FILES[$key]['error']) ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.Missing
85 {
86 /* translators: %s: filename */
87 $this->importError = sprintf(__("Error during upload of file %s, perhaps the file is too big. You can try to split it up or increase max allowed file size on your server.", 'woorewards-lite'), $filename);
88 }
89 else
90 {
91 if( \sanitize_mime_type(\wp_unslash($_FILES[$key]['type'])) != 'application/json' ) // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
92 {
93 $this->importError = __("Expects a JSON file.", 'woorewards-lite');
94 }
95 else try
96 {
97 $reason = isset($_POST['woorewards-lite' . '_import_reason']) ? \sanitize_text_field(\wp_unslash($_POST['woorewards-lite' . '_import_reason'])) : false; // phpcs:ignore WordPress.Security.NonceVerification.Missing
98 $filename_esc = \wp_unslash($_FILES[$key]['tmp_name']);
99 $json = (array)@json_decode(@file_get_contents($filename_esc), true); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- reading uploaded tmp file
100 $this->importJSON($json, $stack, $replace, $reason);
101 }
102 catch(\Exception $e)
103 {
104 $this->importError = __("The file cannot be read or format is invalid. Expects JSON content.", 'woorewards-lite');
105 }
106 \wp_delete_file(\sanitize_file_name(\wp_unslash($_FILES[$key]['tmp_name']))); // phpcs:ignore WordPress.Security.NonceVerification.Missing
107 }
108 }
109 else
110 $this->importError = __("Please, select a file to import.", 'woorewards-lite');
111 return $oldValue;
112 }
113
114 /** @param $replace (bool) if false, points are added. */
115 protected function importJSON($json, $stack, $replace=true, $reason=false)
116 {
117 $affected = 0;
118 $unknown = array();
119 $ignored = array();
120 global $wpdb;
121 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- dynamic table name from wpdb property
122 $table = $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->lwsWooRewardsHistoric}'");
123 \set_time_limit(0); // phpcs:ignore Generic.PHP.ForbiddenFunctions.Found, Squiz.PHP.DiscouragedFunctions.Discouraged -- long import needs extended time
124 if (!$reason)
125 $reason = _x("Import", "History line", 'woorewards-lite');
126 $metakey = 'lws_wre_points_'.$stack;
127 $blogId = \get_current_blog_id();
128
129 $multiply = floatval(str_replace(',', '.', \get_option('woorewards-lite'.'_multiply', 1)));
130 if( !$multiply )
131 $multiply = 1;
132 $round = \get_option('woorewards-lite'.'_rounding', 'floor');
133
134 foreach( $json as $row )
135 {
136 if( isset($row['email']) && isset($row['points']) )
137 {
138 $email = \trim($row['email']);
139 if (!$email)
140 continue;
141
142 $points = floatval($row['points']) * $multiply;
143 if( 'floor' == $round )
144 $points = floor($points);
145 else if( 'ceil' == $round )
146 $points = ceil($points);
147 else if( 'half_up' == $round )
148 $points = round($points, 0, PHP_ROUND_HALF_UP);
149 else if( 'half_down' == $round )
150 $points = round($points, 0, PHP_ROUND_HALF_DOWN);
151
152 if( $user = \get_user_by('email', $email) )
153 {
154 $oldPts = 0;
155 if ($replace) {
156 \update_user_meta($user->ID, $metakey, $points);
157 } else {
158 $oldPts = \intval(\get_user_meta($user->ID, $metakey, true));
159 \update_user_meta($user->ID, $metakey, $points + $oldPts);
160 }
161 ++$affected;
162 if( $table )
163 {
164 $values = array(
165 'user_id' => $user->ID,
166 'stack' => $stack,
167 'new_total' => $points,
168 'commentar' => $reason,
169 'origin' => 'migration-tool',
170 'blog_id' => $blogId,
171 );
172 $formats = array('%d', '%s', '%d', '%s', '%s');
173 if (!$replace) {
174 $values['new_total'] += $oldPts;
175 $values['points_moved'] = $points;
176 $formats[] = '%d';
177 }
178 $wpdb->insert($table, $values, $formats); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
179 }
180 }
181 else
182 $unknown[$email] = $email;
183 }
184 else
185 {
186 $this->importError = __("Invalid data: ", 'woorewards-lite') . htmlentities(json_encode($row));
187 return false;
188 }
189 }
190
191 /* translators: %d: number of items */
192 \lws_admin_add_notice_once('woorewards-lite'.'-notice', sprintf(__("Import done. %d items affected.", 'woorewards-lite'), $affected), array('level'=>'success'));
193 if( !empty($unknown) )
194 {
195 $warning = __("The following users cannot be found. Points ignored.", 'woorewards-lite');
196 $unknown = htmlentities(implode("\n", $unknown));
197 $warning .= "<textarea>$unknown</textarea>";
198 \lws_admin_add_notice_once('woorewards-lite'.'-warning', $warning, array('level'=>'warning'));
199 }
200 if( !empty($ignored) )
201 {
202 $warning = __("The following point pools cannot be found. Points ignored.", 'woorewards-lite');
203 $ignored = htmlentities(implode("\n", $ignored));
204 $warning .= "<textarea>$ignored</textarea>";
205 \lws_admin_add_notice_once('woorewards-lite'.'-warning2', $warning, array('level'=>'warning'));
206 }
207 return true;
208 }
209
210 function exportWR()
211 {
212 if (!\wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['lws_btn_nonce'] ?? '')), 'woorewards-lite' . '-export-wr')) {
213 \wp_die('forbidden', 403);
214 }
215 if( !\current_user_can('manage_options') )
216 \wp_die('forbidden', 403);
217
218 $poolKey = 'woorewards-lite' . '_from_pool';
219 $poolName = isset($_REQUEST[$poolKey]) ? \sanitize_text_field(\wp_unslash($_REQUEST[$poolKey])) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
220 if( $poolName )
221 {
222 require_once LWS_WOOREWARDS_INCLUDES . '/pointsflow/exportmethod.php';
223 require_once LWS_WOOREWARDS_INCLUDES . '/pointsflow/methods/woorewards.php';
224 $method = new \LWS\WOOREWARDS\PointsFlow\Methods\WooRewards();
225 $this->sendJSONPoints($method, $poolName, $poolName);
226 }
227 \wp_die('Bad request', 400);
228 }
229
230 function exportPoints()
231 {
232 if (!\wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['lws_btn_nonce'] ?? '')), 'woorewards-lite' . '-export-points')) {
233 \wp_die('forbidden', 403);
234 }
235 if( !\current_user_can('manage_options') )
236 \wp_die('forbidden', 403);
237
238 $metaPost = 'woorewards-lite' . '_from_meta';
239 $metaKey = isset($_REQUEST[$metaPost]) ? \sanitize_text_field(\wp_unslash($_REQUEST[$metaPost])) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
240 $argPost = 'woorewards-lite' . '_with_arg';
241 $argValue = isset($_REQUEST[$argPost]) ? \sanitize_text_field(\wp_unslash($_REQUEST[$argPost])) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
242
243 if( !$metaKey || trim($metaKey) == '' )
244 \wp_die('Bad request', 400);
245 if( !$argValue || trim($argValue) == '' )
246 $argValue = false;
247
248 require_once LWS_WOOREWARDS_INCLUDES . '/pointsflow/exportmethods.php';
249 $method = \LWS\WOOREWARDS\PointsFlow\ExportMethods::get($metaKey);
250 if( !$method )
251 \wp_die('Not Implemented', 501);
252
253 if( !$method->instance->supportFreeArgs() && ($args = $method->instance->getArgs()) )
254 {
255 if( !in_array($argValue, array_keys($args)) )
256 \wp_die('Invalid Export argument for ' . esc_html($method->instance->getTitle()), 418);
257 }
258
259 $this->sendJSONPoints($method->instance, $metaKey, $argValue);
260 }
261
262 private function sendJSONPoints($method, $value, $arg=false)
263 {
264 $json = $method->export($value, $arg);
265 \array_walk($json, function(&$row){
266 if (null === $row->points || !\strlen($row->points))
267 $row->points = 0;
268 });
269
270 $base = str_replace(' ', '-', \get_bloginfo('name'));
271 $origin = \remove_accents(strtolower($method->getTitle()));
272 $origin = preg_replace(array('/\s*-+\s*/', '/[\s_]+/'), array('-', '_'), $origin);
273 $origin = \sanitize_key($origin);
274 $date = \gmdate('Ymd');
275 $arg = \sanitize_key($arg);
276 $filename = \esc_attr("{$base}-{$origin}-{$arg}-{$date}.json");
277 header("Content-disposition: attachment; filename=\"{$filename}\""); // force download
278 \wp_send_json($json);
279 }
280
281 }