PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.2.5
GiveWP – Donation Plugin and Fundraising Platform v2.2.5
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / user-functions.php
give / includes Last commit date
admin 7 years ago api 7 years ago deprecated 7 years ago donors 7 years ago emails 7 years ago forms 7 years ago gateways 7 years ago libraries 7 years ago payments 7 years ago actions.php 7 years ago ajax-functions.php 7 years ago class-give-async-process.php 8 years ago class-give-background-updater.php 7 years ago class-give-cache.php 7 years ago class-give-cli-commands.php 8 years ago class-give-comment.php 7 years ago class-give-cron.php 8 years ago class-give-db-donor-meta.php 8 years ago class-give-db-donors.php 7 years ago class-give-db-form-meta.php 8 years ago class-give-db-logs-meta.php 8 years ago class-give-db-logs.php 7 years ago class-give-db-meta.php 7 years ago class-give-db-payment-meta.php 7 years ago class-give-db-sequential-ordering.php 7 years ago class-give-db-sessions.php 7 years ago class-give-db.php 7 years ago class-give-donate-form.php 8 years ago class-give-donor-wall-widget.php 7 years ago class-give-donor.php 7 years ago class-give-email-access.php 7 years ago class-give-html-elements.php 7 years ago class-give-license-handler.php 7 years ago class-give-logging.php 8 years ago class-give-readme-parser.php 8 years ago class-give-roles.php 8 years ago class-give-scripts.php 7 years ago class-give-session.php 7 years ago class-give-stats.php 8 years ago class-give-template-loader.php 8 years ago class-give-tooltips.php 8 years ago class-give-translation.php 8 years ago class-notices.php 7 years ago country-functions.php 8 years ago currency-functions.php 7 years ago error-tracking.php 8 years ago filters.php 7 years ago formatting.php 7 years ago import-functions.php 7 years ago install.php 7 years ago login-register.php 8 years ago misc-functions.php 7 years ago plugin-compatibility.php 8 years ago post-types.php 8 years ago price-functions.php 7 years ago process-donation.php 7 years ago shortcodes.php 7 years ago template-functions.php 8 years ago user-functions.php 7 years ago
user-functions.php
661 lines
1 <?php
2 /**
3 * User Functions
4 *
5 * Functions related to users / donors
6 *
7 * @package Give
8 * @subpackage Functions
9 * @copyright Copyright (c) 2016, WordImpress
10 * @license https://opensource.org/licenses/gpl-license GNU Public License
11 * @since 1.0
12 */
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Get Users Donations
21 *
22 * Retrieves a list of all donations by a specific user.
23 *
24 * @param int $user User ID or email address.
25 * @param int $number Number of donations to retrieve.
26 * @param bool $pagination Enable/Disable Pagination.
27 * @param string $status Donation Status.
28 *
29 * @since 1.0
30 *
31 * @return bool|array List of all user donations.
32 */
33 function give_get_users_donations( $user = 0, $number = 20, $pagination = false, $status = 'complete' ) {
34
35 if ( empty( $user ) ) {
36 $user = get_current_user_id();
37 }
38
39 if ( 0 === $user && ! Give()->email_access->token_exists ) {
40 return false;
41 }
42
43 $status = ( 'complete' === $status ) ? 'publish' : $status;
44 $paged = 1;
45
46 if ( $pagination ) {
47 if ( get_query_var( 'paged' ) ) {
48 $paged = get_query_var( 'paged' );
49 } elseif ( get_query_var( 'page' ) ) {
50 $paged = get_query_var( 'page' );
51 }
52 }
53
54 $args = apply_filters( 'give_get_users_donations_args', array(
55 'user' => $user,
56 'number' => $number,
57 'status' => $status,
58 'orderby' => 'date',
59 ) );
60
61 if ( $pagination ) {
62 $args['page'] = $paged;
63 } else {
64 $args['nopaging'] = true;
65 }
66
67 $by_user_id = is_numeric( $user ) ? true : false;
68 $donor = new Give_Donor( $user, $by_user_id );
69
70 if ( ! empty( $donor->payment_ids ) ) {
71
72 unset( $args['user'] );
73 $args['post__in'] = array_map( 'absint', explode( ',', $donor->payment_ids ) );
74
75 }
76
77 $donations = give_get_payments( apply_filters( 'give_get_users_donations_args', $args ) );
78
79 // No donations.
80 if ( ! $donations ) {
81 return false;
82 }
83
84 return $donations;
85 }
86
87 /**
88 * Get Users Donations
89 *
90 * Returns a list of unique donation forms given to by a specific user.
91 *
92 * @param int $user User ID or email address
93 * @param string $status Donation Status.
94 *
95 * @since 1.0
96 *
97 * @return bool|object List of unique forms donated by user
98 */
99 function give_get_users_completed_donations( $user = 0, $status = 'complete' ) {
100 if ( empty( $user ) ) {
101 $user = get_current_user_id();
102 }
103
104 if ( empty( $user ) ) {
105 return false;
106 }
107
108 $by_user_id = is_numeric( $user ) ? true : false;
109
110 $donor = new Give_Donor( $user, $by_user_id );
111
112 if ( empty( $donor->payment_ids ) ) {
113 return false;
114 }
115
116 // Get all the items donated.
117 $payment_ids = array_reverse( explode( ',', $donor->payment_ids ) );
118 $limit_payments = apply_filters( 'give_users_completed_donations_payments', 50 );
119 if ( ! empty( $limit_payments ) ) {
120 $payment_ids = array_slice( $payment_ids, 0, $limit_payments );
121 }
122 $donation_data = array();
123 foreach ( $payment_ids as $payment_id ) {
124 $donation_data[] = give_get_payment_meta( $payment_id );
125 }
126
127 if ( empty( $donation_data ) ) {
128 return false;
129 }
130
131 // Grab only the post ids "form_id" of the forms donated on this order.
132 $completed_donations_ids = array();
133 foreach ( $donation_data as $donation_meta ) {
134 $completed_donations_ids[] = isset( $donation_meta['form_id'] ) ? $donation_meta['form_id'] : '';
135 }
136
137 if ( empty( $completed_donations_ids ) ) {
138 return false;
139 }
140
141 // Only include each donation once.
142 $form_ids = array_unique( $completed_donations_ids );
143
144 // Make sure we still have some products and a first item.
145 if ( empty( $form_ids ) || ! isset( $form_ids[0] ) ) {
146 return false;
147 }
148
149 $post_type = get_post_type( $form_ids[0] );
150
151 $args = apply_filters( 'give_get_users_completed_donations_args', array(
152 'include' => $form_ids,
153 'post_type' => $post_type,
154 'posts_per_page' => - 1,
155 ) );
156
157 return apply_filters( 'give_users_completed_donations_list', get_posts( $args ) );
158 }
159
160
161 /**
162 * Has donations
163 *
164 * Checks to see if a user has donated to at least one form.
165 *
166 * @param int $user_id The ID of the user to check.
167 *
168 * @access public
169 * @since 1.0
170 *
171 * @return bool True if has donated, false other wise.
172 */
173 function give_has_donations( $user_id = null ) {
174 if ( empty( $user_id ) ) {
175 $user_id = get_current_user_id();
176 }
177
178 if ( give_get_users_donations( $user_id, 1 ) ) {
179 return true; // User has at least one donation.
180 }
181
182 // User has never donated anything.
183 return false;
184 }
185
186
187 /**
188 * Get Donation Status for User.
189 *
190 * Retrieves the donation count and the total amount spent for a specific user.
191 *
192 * @param int|string $user The ID or email of the donor to retrieve stats for.
193 *
194 * @access public
195 * @since 1.0
196 *
197 * @return array
198 */
199 function give_get_donation_stats_by_user( $user = '' ) {
200
201 $field = '';
202
203 if ( is_email( $user ) ) {
204 $field = 'email';
205 } elseif ( is_numeric( $user ) ) {
206 $field = 'user_id';
207 }
208
209 $stats = array();
210 $donor = Give()->donors->get_donor_by( $field, $user );
211
212 if ( $donor ) {
213 $donor = new Give_Donor( $donor->id );
214 $stats['purchases'] = absint( $donor->purchase_count );
215 $stats['total_spent'] = give_maybe_sanitize_amount( $donor->get_total_donation_amount() );
216 }
217
218 /**
219 * Filter the donation stats.
220 *
221 * @since 1.7
222 */
223 $stats = (array) apply_filters( 'give_donation_stats_by_user', $stats, $user );
224
225 return $stats;
226 }
227
228
229 /**
230 * Count number of donations of a donor.
231 *
232 * Returns total number of donations a donor has made.
233 *
234 * @param int|string $user The ID or email of the donor.
235 *
236 * @access public
237 * @since 1.0
238 *
239 * @return int The total number of donations.
240 */
241 function give_count_donations_of_donor( $user = null ) {
242
243 // Logged in?
244 if ( empty( $user ) ) {
245 $user = get_current_user_id();
246 }
247
248 // Email access?
249 if ( empty( $user ) && Give()->email_access->token_email ) {
250 $user = Give()->email_access->token_email;
251 }
252
253 $stats = ! empty( $user ) ? give_get_donation_stats_by_user( $user ) : false;
254
255 return isset( $stats['purchases'] ) ? $stats['purchases'] : 0;
256 }
257
258 /**
259 * Calculates the total amount spent by a user.
260 *
261 * @param int|string $user The ID or email of the donor.
262 *
263 * @access public
264 * @since 1.0
265 *
266 * @return float The total amount the user has spent
267 */
268 function give_donation_total_of_user( $user = null ) {
269
270 $stats = give_get_donation_stats_by_user( $user );
271
272 return $stats['total_spent'];
273 }
274
275
276 /**
277 * Validate a potential username.
278 *
279 * @param string $username The username to validate.
280 * @param int $form_id Donation Form ID.
281 *
282 * @since 1.0
283 *
284 * @return bool
285 */
286 function give_validate_username( $username, $form_id = 0 ) {
287 $valid = true;
288
289 // Validate username.
290 if ( ! empty( $username ) ) {
291
292 // Sanitize username.
293 $sanitized_user_name = sanitize_user( $username, false );
294
295 // We have an user name, check if it already exists.
296 if ( username_exists( $username ) ) {
297 // Username already registered.
298 give_set_error( 'username_unavailable', __( 'Username already taken.', 'give' ) );
299 $valid = false;
300
301 // Check if it's valid.
302 } elseif ( $sanitized_user_name !== $username ) {
303 // Invalid username.
304 if ( is_multisite() ) {
305 give_set_error( 'username_invalid', __( 'Invalid username. Only lowercase letters (a-z) and numbers are allowed.', 'give' ) );
306 $valid = false;
307 } else {
308 give_set_error( 'username_invalid', __( 'Invalid username.', 'give' ) );
309 $valid = false;
310 }
311 }
312 } else {
313 // Username is empty.
314 give_set_error( 'username_empty', __( 'Enter a username.', 'give' ) );
315 $valid = false;
316
317 // Check if guest checkout is disable for form.
318 if ( $form_id && give_logged_in_only( $form_id ) ) {
319 give_set_error( 'registration_required', __( 'You must register or login to complete your donation.', 'give' ) );
320 $valid = false;
321 }
322 }
323
324 /**
325 * Filter the username validation result.
326 *
327 * @param bool $valid Username is valid or not.
328 * @param string $username Username to check.
329 * @param bool $form_id Donation Form ID.
330 *
331 * @since 1.8
332 */
333 $valid = (bool) apply_filters( 'give_validate_username', $valid, $username, $form_id );
334
335 return $valid;
336 }
337
338
339 /**
340 * Validate user email.
341 *
342 * @param string $email User email.
343 * @param bool $registering_new_user Flag to check user register or not.
344 *
345 * @since 1.8
346 *
347 * @return bool
348 */
349 function give_validate_user_email( $email, $registering_new_user = false ) {
350 $valid = true;
351
352 if ( empty( $email ) ) {
353 // No email.
354 give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
355 $valid = false;
356
357 } elseif ( email_exists( $email ) ) {
358 // Email already exists.
359 give_set_error( 'email_exists', __( 'Email already exists.', 'give' ) );
360 $valid = false;
361
362 } elseif ( ! is_email( $email ) ) {
363 // Validate email.
364 give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
365 $valid = false;
366
367 } elseif ( $registering_new_user ) {
368
369 // If donor email is not primary.
370 if ( ! email_exists( $email ) && give_donor_email_exists( $email ) && give_is_additional_email( $email ) ) {
371 // Check if email exists.
372 give_set_error( 'email_used', __( 'The email address provided is already active for another user.', 'give' ) );
373 $valid = false;
374 }
375 }
376
377 /**
378 * Filter the email validation result.
379 *
380 * @param bool $valid Email is valid or not.
381 * @param string $email Email to check.
382 * @param bool $registering_new_user Registering New or Existing User.
383 *
384 * @since 1.8
385 */
386 $valid = (bool) apply_filters( 'give_validate_user_email', $valid, $email, $registering_new_user );
387
388 return $valid;
389 }
390
391 /**
392 * Validate password.
393 *
394 * @param string $password Password to Validate.
395 * @param string $confirm_password Password to Confirm Validation.
396 * @param bool $registering_new_user Registering New or Existing User.
397 *
398 * @since 1.8
399 *
400 * @return bool
401 */
402 function give_validate_user_password( $password = '', $confirm_password = '', $registering_new_user = false ) {
403 $valid = true;
404
405 // Passwords Validation For New Donors Only.
406 if ( $registering_new_user ) {
407 // Password or confirmation missing.
408 if ( ! $password ) {
409 // The password is invalid.
410 give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
411 $valid = false;
412 } elseif ( ! $confirm_password ) {
413 // Confirmation password is invalid.
414 give_set_error( 'confirmation_empty', __( 'Enter the password confirmation.', 'give' ) );
415 $valid = false;
416 }
417 }
418 // Passwords Validation For New Donors as well as Existing Donors.
419 if ( $password || $confirm_password ) {
420 if ( strlen( $password ) < 6 || strlen( $confirm_password ) < 6 ) {
421 // Seems Weak Password.
422 give_set_error( 'password_weak', __( 'Passwords should have at least 6 characters.', 'give' ) );
423 $valid = false;
424 }
425 if ( $password && $confirm_password ) {
426 // Verify confirmation matches.
427 if ( $password !== $confirm_password ) {
428 // Passwords do not match.
429 give_set_error( 'password_mismatch', __( 'Passwords you entered do not match. Please try again.', 'give' ) );
430 $valid = false;
431 }
432 }
433 }
434
435 /**
436 * Filter the password validation result.
437 *
438 * @param bool $valid Password is Valid or not.
439 * @param string $password Password to check validation.
440 * @param string $confirm_password Password to confirm validation.
441 * @param bool $registering_new_user Registering New or Existing User.
442 *
443 * @since 1.8
444 */
445 $valid = (bool) apply_filters( 'give_validate_user_email', $valid, $password, $confirm_password, $registering_new_user );
446
447 return $valid;
448 }
449
450 /**
451 * Counts the total number of donors.
452 *
453 * @access public
454 * @since 1.0
455 *
456 * @return int The total number of donors.
457 */
458 function give_count_total_donors() {
459 return Give()->donors->count();
460 }
461
462 /**
463 * Returns the saved address for a donor
464 *
465 * @access public
466 * @since 1.0
467 *
468 * @param int/null $donor_id Donor ID.
469 * @param array $args donor args.
470 *
471 * @return array The donor's address, if any
472 */
473 function give_get_donor_address( $donor_id = null, $args = array() ) {
474 if ( empty( $donor_id ) ) {
475 $donor_id = get_current_user_id();
476 }
477
478 $address = array();
479 $args = wp_parse_args(
480 $args,
481 array(
482 'address_type' => 'billing',
483 )
484 );
485 $default_address = array(
486 'line1' => '',
487 'line2' => '',
488 'city' => '',
489 'state' => '',
490 'country' => '',
491 'zip' => '',
492 );
493
494
495 // Backward compatibility for user id param.
496 $by_user_id = get_user_by( 'id', $donor_id ) ? true : false;
497
498 // Backward compatibility.
499 if ( ! give_has_upgrade_completed( 'v20_upgrades_user_address' ) && $by_user_id ) {
500 return wp_parse_args(
501 (array) get_user_meta( $donor_id, '_give_user_address', true ),
502 $default_address
503 );
504 }
505
506 $donor = new Give_Donor( $donor_id, $by_user_id );
507
508 if (
509 ! $donor->id ||
510 empty( $donor->address ) ||
511 ! array_key_exists( $args['address_type'], $donor->address )
512 ) {
513 return $default_address;
514 }
515
516 switch ( true ) {
517 case is_string( end( $donor->address[ $args['address_type'] ] ) ):
518 $address = wp_parse_args( $donor->address[ $args['address_type'] ], $default_address );
519 break;
520
521 case is_array( end( $donor->address[ $args['address_type'] ] ) ):
522 $address = wp_parse_args( array_shift( $donor->address[ $args['address_type'] ] ), $default_address );
523 break;
524 }
525
526 return $address;
527 }
528
529 /**
530 * Give New User Notification
531 *
532 * Sends the new user notification email when a user registers within the donation form
533 *
534 * @param int $donation_id Donation ID.
535 * @param array $donation_data An Array of Donation Data.
536 *
537 * @access public
538 * @since 1.0
539 *
540 * @return void
541 */
542 function give_new_user_notification( $donation_id = 0, $donation_data = array() ) {
543 // Bailout.
544 if (
545 empty( $donation_id )
546 || empty( $donation_data )
547 || ! isset( $_POST['give_create_account'] )
548 || 'on' !== give_clean( $_POST['give_create_account'] )
549 ) {
550 return;
551 }
552
553 // For backward compatibility
554 $user = get_user_by( 'ID', $donation_data['user_info']['id'] );
555
556 $donation_data['user_info'] = array_merge(
557 $donation_data['user_info'],
558 array(
559 'user_id' => $donation_data['user_info']['id'],
560 'user_first' => $donation_data['user_info']['first_name'],
561 'user_last' => $donation_data['user_info']['last_name'],
562 'user_email' => $donation_data['user_info']['email'],
563 'user_login' => $user->user_login,
564 )
565 );
566
567 do_action( 'give_new-donor-register_email_notification', $donation_data['user_info']['id'], $donation_data['user_info'], $donation_id );
568 do_action( 'give_donor-register_email_notification', $donation_data['user_info']['id'], $donation_data['user_info'], $donation_id );
569 }
570
571 add_action( 'give_insert_payment', 'give_new_user_notification', 10, 2 );
572
573
574 /**
575 * Get Donor Name By
576 *
577 * Retrieves the donor name based on the id and the name of the user or donation
578 *
579 * @param int $id The ID of donation or donor.
580 * @param string $from From will be a string to be passed as donation or donor.
581 *
582 * @access public
583 * @since 1.8.9
584 *
585 * @return string
586 */
587 function give_get_donor_name_by( $id = 0, $from = 'donation' ) {
588
589 // ID shouldn't be empty.
590 if ( empty( $id ) ) {
591 return '';
592 }
593
594 $name = '';
595 $title_prefix = '';
596
597 switch ( $from ) {
598
599 case 'donation':
600 $title_prefix = give_get_meta( $id, '_give_payment_donor_title_prefix', true );
601 $first_name = give_get_meta( $id, '_give_donor_billing_first_name', true );
602 $last_name = give_get_meta( $id, '_give_donor_billing_last_name', true );
603
604 $name = "{$first_name} {$last_name}";
605
606 break;
607
608 case 'donor':
609 $name = Give()->donors->get_column( 'name', $id );
610 $title_prefix = Give()->donor_meta->get_meta( $id, '_give_donor_title_prefix', true );
611
612 break;
613
614 }
615
616 // If title prefix is set then prepend it to name.
617 $name = give_get_donor_name_with_title_prefixes( $title_prefix, $name );
618
619 return $name;
620
621 }
622
623 /**
624 * Checks whether the given donor email exists in users as well as additional_email of donors.
625 *
626 * @param string $email Donor Email.
627 *
628 * @since 1.8.9
629 *
630 * @return boolean The user's ID on success, and false on failure.
631 */
632 function give_donor_email_exists( $email ) {
633 if ( Give()->donors->get_donor_by( 'email', $email ) ) {
634 return true;
635 }
636 return false;
637 }
638
639 /**
640 * This function will check whether the donor email is primary or additional.
641 *
642 * @param string $email Donor Email.
643 *
644 * @since 1.8.13
645 *
646 * @return bool
647 */
648 function give_is_additional_email( $email ) {
649 global $wpdb;
650
651 $meta_table = Give()->donor_meta->table_name;
652 $meta_type = Give()->donor_meta->meta_type;
653 $donor_id = $wpdb->get_var( $wpdb->prepare( "SELECT {$meta_type}_id FROM {$meta_table} WHERE meta_key = 'additional_email' AND meta_value = %s LIMIT 1", $email ) );
654
655 if ( empty( $donor_id ) ) {
656 return false;
657 }
658
659 return true;
660 }
661