Easy Digital Downloads - Version 3.0.4

Version Description

Download this release

Release Info

Developer cklosows
Plugin Icon 128x128 Easy Digital Downloads
Version 3.0.4
Comparing to
See all releases

Code changes from version 3.0.3 to 3.0.4

easy-digital-downloads.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: The easiest way to sell digital products with WordPress.
6
  * Author: Easy Digital Downloads
7
  * Author URI: https://easydigitaldownloads.com
8
- * Version: 3.0.3
9
  * Text Domain: easy-digital-downloads
10
  * Domain Path: languages
11
  * Requires PHP: 5.6
@@ -26,7 +26,7 @@
26
  * @package EDD
27
  * @category Core
28
  * @author Easy Digital Downloads
29
- * @version 3.0.3
30
  */
31
 
32
  // Exit if accessed directly.
5
  * Description: The easiest way to sell digital products with WordPress.
6
  * Author: Easy Digital Downloads
7
  * Author URI: https://easydigitaldownloads.com
8
+ * Version: 3.0.4
9
  * Text Domain: easy-digital-downloads
10
  * Domain Path: languages
11
  * Requires PHP: 5.6
26
  * @package EDD
27
  * @category Core
28
  * @author Easy Digital Downloads
29
+ * @version 3.0.4
30
  */
31
 
32
  // Exit if accessed directly.
includes/admin/customers/class-customer-email-addresses-table.php CHANGED
@@ -337,15 +337,24 @@ class EDD_Customer_Email_Addresses_Table extends List_Table {
337
  $search = $this->get_search();
338
  $args = array( 'status' => $this->get_status() );
339
 
340
- // Email
 
 
 
 
 
 
 
 
 
341
  if ( is_email( $search ) ) {
342
  $args['email'] = $search;
343
 
344
- // Address ID
345
  } elseif ( is_numeric( $search ) ) {
346
  $args['id'] = $search;
347
 
348
- // Customer ID
349
  } elseif ( strpos( $search, 'c:' ) !== false ) {
350
  $args['customer_id'] = trim( str_replace( 'c:', '', $search ) );
351
 
@@ -355,10 +364,10 @@ class EDD_Customer_Email_Addresses_Table extends List_Table {
355
  $args['search_columns'] = array( 'email' );
356
  }
357
 
358
- // Parse pagination
359
  $this->args = $this->parse_pagination_args( $args );
360
 
361
- // Get the data
362
  $emails = edd_get_customer_email_addresses( $this->args );
363
 
364
  if ( ! empty( $emails ) ) {
337
  $search = $this->get_search();
338
  $args = array( 'status' => $this->get_status() );
339
 
340
+ // Account for search stripping the "+" from emails.
341
+ if ( strpos( $search, ' ' ) ) {
342
+ $original_query = $search;
343
+ $search = str_replace( ' ', '+', $search );
344
+ if ( ! is_email( $search ) ) {
345
+ $search = $original_query;
346
+ }
347
+ }
348
+
349
+ // Email.
350
  if ( is_email( $search ) ) {
351
  $args['email'] = $search;
352
 
353
+ // Address ID.
354
  } elseif ( is_numeric( $search ) ) {
355
  $args['id'] = $search;
356
 
357
+ // Customer ID.
358
  } elseif ( strpos( $search, 'c:' ) !== false ) {
359
  $args['customer_id'] = trim( str_replace( 'c:', '', $search ) );
360
 
364
  $args['search_columns'] = array( 'email' );
365
  }
366
 
367
+ // Parse pagination.
368
  $this->args = $this->parse_pagination_args( $args );
369
 
370
+ // Get the data.
371
  $emails = edd_get_customer_email_addresses( $this->args );
372
 
373
  if ( ! empty( $emails ) ) {
includes/admin/customers/class-customer-table.php CHANGED
@@ -298,17 +298,26 @@ class EDD_Customer_Reports_Table extends List_Table {
298
  $search = $this->get_search();
299
  $args = array( 'status' => $this->get_status() );
300
 
301
- // Email search
 
 
 
 
 
 
 
 
 
302
  if ( is_email( $search ) ) {
303
  $args['email'] = $search;
304
 
305
- // Customer ID
306
  } elseif ( is_numeric( $search ) ) {
307
  $args['id'] = $search;
308
  } elseif ( strpos( $search, 'c:' ) !== false ) {
309
  $args['id'] = trim( str_replace( 'c:', '', $search ) );
310
 
311
- // User ID
312
  } elseif ( strpos( $search, 'user:' ) !== false ) {
313
  $args['user_id'] = trim( str_replace( 'u:', '', $search ) );
314
  } elseif ( strpos( $search, 'u:' ) !== false ) {
@@ -323,9 +332,25 @@ class EDD_Customer_Reports_Table extends List_Table {
323
  // Parse pagination
324
  $this->args = $this->parse_pagination_args( $args );
325
 
326
- // Get the data
327
- $customers = edd_get_customers( $this->args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
 
329
  if ( ! empty( $customers ) ) {
330
  foreach ( $customers as $customer ) {
331
  $data[] = array(
298
  $search = $this->get_search();
299
  $args = array( 'status' => $this->get_status() );
300
 
301
+ // Account for search stripping the "+" from emails.
302
+ if ( strpos( $search, ' ' ) ) {
303
+ $original_query = $search;
304
+ $search = str_replace( ' ', '+', $search );
305
+ if ( ! is_email( $search ) ) {
306
+ $search = $original_query;
307
+ }
308
+ }
309
+
310
+ // Email search.
311
  if ( is_email( $search ) ) {
312
  $args['email'] = $search;
313
 
314
+ // Customer ID.
315
  } elseif ( is_numeric( $search ) ) {
316
  $args['id'] = $search;
317
  } elseif ( strpos( $search, 'c:' ) !== false ) {
318
  $args['id'] = trim( str_replace( 'c:', '', $search ) );
319
 
320
+ // User ID.
321
  } elseif ( strpos( $search, 'user:' ) !== false ) {
322
  $args['user_id'] = trim( str_replace( 'u:', '', $search ) );
323
  } elseif ( strpos( $search, 'u:' ) !== false ) {
332
  // Parse pagination
333
  $this->args = $this->parse_pagination_args( $args );
334
 
335
+ if ( is_email( $search ) ) {
336
+ $customer_emails = new EDD\Database\Queries\Customer_Email_Address();
337
+ $customer_ids = $customer_emails->query(
338
+ array(
339
+ 'fields' => 'customer_id',
340
+ 'email' => $search,
341
+ )
342
+ );
343
+
344
+ $customers = edd_get_customers(
345
+ array(
346
+ 'id__in' => $customer_ids,
347
+ )
348
+ );
349
+ } else {
350
+ $customers = edd_get_customers( $this->args );
351
+ }
352
 
353
+ // Get the data
354
  if ( ! empty( $customers ) ) {
355
  foreach ( $customers as $customer ) {
356
  $data[] = array(
includes/admin/payments/actions.php CHANGED
@@ -177,10 +177,11 @@ function edd_update_payment_details( $data = array() ) {
177
  $order_update_args['user_id'] = $customer->user_id;
178
  $order_update_args['email'] = $customer->email;
179
 
180
- // Address
181
  $address = $data['edd_order_address'];
182
 
183
- edd_update_order_address( absint( $address['address_id'] ), array(
 
184
  'name' => $customer->name,
185
  'address' => $address['address'],
186
  'address2' => $address['address2'],
@@ -188,7 +189,20 @@ function edd_update_payment_details( $data = array() ) {
188
  'region' => $address['region'],
189
  'postal_code' => $address['postal_code'],
190
  'country' => $address['country'],
191
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
  // Unlimited downloads.
194
  if ( 1 === (int) $unlimited ) {
177
  $order_update_args['user_id'] = $customer->user_id;
178
  $order_update_args['email'] = $customer->email;
179
 
180
+ // Address.
181
  $address = $data['edd_order_address'];
182
 
183
+ $order_address_id = absint( $address['address_id'] );
184
+ $order_address_details = array(
185
  'name' => $customer->name,
186
  'address' => $address['address'],
187
  'address2' => $address['address2'],
189
  'region' => $address['region'],
190
  'postal_code' => $address['postal_code'],
191
  'country' => $address['country'],
192
+ );
193
+
194
+ if ( empty( $order_address_id ) ) {
195
+
196
+ // Unset the address_id which is 0.
197
+ unset( $address['address_id'] );
198
+
199
+ // Add the $order_id to the arguments to create this order address.
200
+ $order_address_details['order_id'] = $order_id;
201
+
202
+ edd_add_order_address( $order_address_details );
203
+ } else {
204
+ edd_update_order_address( $order_address_id, $order_address_details );
205
+ }
206
 
207
  // Unlimited downloads.
208
  if ( 1 === (int) $unlimited ) {
includes/admin/payments/orders.php CHANGED
@@ -481,7 +481,7 @@ function edd_order_details_addresses( $order ) {
481
  ); // WPCS: XSS ok.
482
  } else {
483
  ?>
484
- <input type="text" name="edd_order_address[region]" class="edd-form-group__input" value="<?php echo esc_attr( $address->region ); ?>" />
485
  <?php
486
  }
487
  ?>
481
  ); // WPCS: XSS ok.
482
  } else {
483
  ?>
484
+ <input type="text" id="edd_order_address_region" name="edd_order_address[region]" class="edd-form-group__input" value="<?php echo esc_attr( $address->region ); ?>" />
485
  <?php
486
  }
487
  ?>
includes/admin/tools/class-edd-tools-recount-store-earnings.php CHANGED
@@ -93,7 +93,7 @@ class EDD_Tools_Recount_Store_Earnings extends EDD_Batch_Export {
93
 
94
  }
95
 
96
- update_option( 'edd_earnings_total', $total );
97
  set_transient( 'edd_earnings_total', $total, 86400 );
98
 
99
  return false;
93
 
94
  }
95
 
96
+ update_option( 'edd_earnings_total', $total, false );
97
  set_transient( 'edd_earnings_total', $total, 86400 );
98
 
99
  return false;
includes/admin/tools/class-edd-tools-reset-stats.php CHANGED
@@ -127,8 +127,10 @@ class EDD_Tools_Reset_Stats extends EDD_Batch_Export {
127
  $this->done = false;
128
  return true;
129
  } else {
130
- update_option( 'edd_earnings_total', 0 );
 
131
  delete_transient( 'edd_earnings_total' );
 
132
  delete_transient( 'edd_estimated_monthly_stats' . true );
133
  delete_transient( 'edd_estimated_monthly_stats' . false );
134
  $this->delete_data( 'edd_reset_tables_to_truncate' );
127
  $this->done = false;
128
  return true;
129
  } else {
130
+ update_option( 'edd_earnings_total', 0, false );
131
+ update_option( 'edd_earnings_total_without_tax', 0, false );
132
  delete_transient( 'edd_earnings_total' );
133
+ delete_transient( 'edd_earnings_total_without_tax' );
134
  delete_transient( 'edd_estimated_monthly_stats' . true );
135
  delete_transient( 'edd_estimated_monthly_stats' . false );
136
  $this->delete_data( 'edd_reset_tables_to_truncate' );
includes/admin/upgrades/v3/class-data-migrator.php CHANGED
@@ -639,9 +639,6 @@ class Data_Migrator {
639
  'date_created' => $date_created_gmt,
640
  );
641
 
642
- // Remove empty data.
643
- $order_address_data = array_filter( $order_address_data );
644
-
645
  $tax_rate_id = null;
646
  $tax_rate = isset( $meta['_edd_payment_tax_rate'][0] )
647
  ? (float) $meta['_edd_payment_tax_rate'][0]
@@ -757,6 +754,8 @@ class Data_Migrator {
757
 
758
  }
759
 
 
 
760
  if ( ! empty( $order_address_data ) ) {
761
  // Add to edd_order_addresses table.
762
  $order_address_data['order_id'] = $order_id;
639
  'date_created' => $date_created_gmt,
640
  );
641
 
 
 
 
642
  $tax_rate_id = null;
643
  $tax_rate = isset( $meta['_edd_payment_tax_rate'][0] )
644
  ? (float) $meta['_edd_payment_tax_rate'][0]
754
 
755
  }
756
 
757
+ // Remove empty data.
758
+ $order_address_data = array_filter( $order_address_data );
759
  if ( ! empty( $order_address_data ) ) {
760
  // Add to edd_order_addresses table.
761
  $order_address_data['order_id'] = $order_id;
includes/api/class-edd-api.php CHANGED
@@ -13,11 +13,15 @@
13
  * @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
14
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
15
  * @since 1.5
 
16
  */
17
 
18
  // Exit if accessed directly
19
  defined( 'ABSPATH' ) || exit;
20
 
 
 
 
21
  /**
22
  * EDD_API Class
23
  *
@@ -156,7 +160,6 @@ class EDD_API {
156
 
157
  // Setup EDD_Stats instance
158
  $this->stats = new EDD_Payment_Stats;
159
-
160
  }
161
 
162
  /**
@@ -1245,72 +1248,94 @@ class EDD_API {
1245
  $start_date = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day_start'];
1246
  $end_date = $dates['year_end'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
1247
 
1248
- $stats = EDD()->payment_stats->get_sales_by_range( 'other', true, $start_date, $end_date );
 
 
 
1249
 
1250
- foreach ( $stats as $sale ) {
1251
- $key = $sale['y'] . $sale['m'] . $sale['d'];
1252
- $sales['sales'][ $key ] = (int) $sale['count'];
1253
- }
 
 
1254
 
1255
- $start_date = date( 'Y-m-d', strtotime( $start_date ) );
1256
- $end_date = date( 'Y-m-d', strtotime( $end_date ) );
 
 
 
 
 
 
 
1257
 
1258
  while ( strtotime( $start_date ) <= strtotime( $end_date ) ) {
1259
- $d = date( 'd', strtotime( $start_date ) );
1260
- $m = date( 'm', strtotime( $start_date ) );
1261
- $y = date( 'Y', strtotime( $start_date ) );
1262
 
1263
- $key = $y . $m . $d;
 
 
 
 
 
 
1264
 
1265
  if ( ! isset( $sales['sales'][ $key ] ) ) {
1266
- $sales['sales'][ $key ] = 0;
 
 
 
 
 
1267
  }
1268
 
1269
- $start_date = date( 'Y-m-d', strtotime( '+1 day', strtotime( $start_date ) ) );
1270
  }
1271
 
1272
  ksort( $sales['sales'] );
1273
 
1274
- $sales['totals'] = array_sum( $sales['sales'] );
1275
- } else {
1276
- $start_date = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day'];
1277
- $end_date = $dates['year'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
1278
-
1279
- $stats = EDD()->payment_stats->get_sales_by_range( $args['date'], false, $start_date, $end_date );
1280
- if ( $stats instanceof WP_Error ) {
1281
-
1282
- $error_message = __( 'There was an error retrieving earnings.', 'easy-digital-downloads' );
1283
 
1284
- foreach ( $stats->errors as $error_key => $error_array ) {
1285
- if ( ! empty( $error_array[0] ) ) {
1286
- $error_message = $error_array[0];
1287
- }
1288
- }
 
 
1289
 
1290
- $error['error'] = sprintf( '%s %s', $error_message, $args['date'] );
1291
- } else {
1292
- if ( empty( $stats ) ) {
1293
- $sales['sales'][ $args['date'] ] = 0;
1294
- } else {
1295
- $total_sales = 0;
1296
- foreach ( $stats as $date ) {
1297
- $total_sales += (int) $date['count'];
1298
- }
1299
- $sales['sales'][ $args['date'] ] = $total_sales;
1300
- }
1301
- }
1302
  }
1303
  } elseif ( $args['product'] == 'all' ) {
1304
  $products = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) );
1305
  $i = 0;
 
 
1306
  foreach ( $products as $product_info ) {
1307
- $sales['sales'][ $i ] = array( $product_info->post_name => edd_get_download_sales_stats( $product_info->ID ) );
 
 
 
 
 
 
 
 
1308
  $i ++;
1309
  }
1310
  } else {
1311
- if ( get_post_type( $args['product'] ) == 'download' ) {
1312
- $product_info = get_post( $args['product'] );
1313
- $sales['sales'][0] = array( $product_info->post_name => edd_get_download_sales_stats( $args['product'] ) );
 
 
 
 
 
 
 
 
 
1314
  } else {
1315
  $error['error'] = sprintf( __( 'Product %s not found!', 'easy-digital-downloads' ), $args['product'] );
1316
  }
@@ -1321,7 +1346,7 @@ class EDD_API {
1321
  }
1322
 
1323
  return apply_filters( 'edd_api_stats_sales', $sales, $this );
1324
- } elseif ( $args['type'] == 'earnings' ) {
1325
  if ( $args['product'] == null ) {
1326
  if ( $args['date'] == null ) {
1327
  $earnings = $this->get_default_earnings_stats( $args );
@@ -1338,96 +1363,102 @@ class EDD_API {
1338
  $error['error'] = __( 'Invalid or no date range specified!', 'easy-digital-downloads' );
1339
  }
1340
 
1341
- $total = (float) 0.00;
1342
-
1343
- // Loop through the years
1344
- if ( ! isset( $earnings['earnings'] ) ) {
1345
- $earnings['earnings'] = array();
1346
- }
1347
-
1348
- if ( cal_days_in_month( CAL_GREGORIAN, $dates['m_start'], $dates['year'] ) < $dates['day_start'] ) {
1349
- $next_day = mktime( 0, 0, 0, $dates['m_start'] + 1, 1, $dates['year'] );
1350
- $day = date( 'd', $next_day );
1351
- $month = date( 'm', $next_day );
1352
- $year = date( 'Y', $next_day );
1353
- $date_start = $year . '-' . $month . '-' . $day;
1354
- } else {
1355
- $date_start = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day_start'];
1356
- }
1357
-
1358
- if ( cal_days_in_month( CAL_GREGORIAN, $dates['m_end'], $dates['year'] ) < $dates['day_end'] ) {
1359
- $date_end = $dates['year_end'] . '-' . $dates['m_end'] . '-' . cal_days_in_month( CAL_GREGORIAN, $dates['m_end'], $dates['year'] );
1360
- } else {
1361
- $date_end = $dates['year_end'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
1362
- }
1363
-
1364
- $earnings = EDD()->payment_stats->get_earnings_by_range( 'other', true, $date_start, $date_end, $args['include_tax'] );
1365
 
1366
- $total = 0;
 
 
 
1367
 
1368
- foreach ( $earnings as $earning ) {
1369
- $temp_data['earnings'][ $earning['y'] . $earning['m'] . $earning['d'] ] = (float) $earning['total'];
1370
- $total += (float) $earning['total'];
1371
- }
 
 
 
 
1372
 
1373
- $date_start = date( 'Y-m-d', strtotime( $date_start ) );
1374
- $date_end = date( 'Y-m-d', strtotime( $date_end ) );
 
 
 
 
1375
 
1376
- while ( strtotime( $date_start ) <= strtotime( $date_end ) ) {
1377
- $d = date( 'd', strtotime( $date_start ) );
1378
- $m = date( 'm', strtotime( $date_start ) );
1379
- $y = date( 'Y', strtotime( $date_start ) );
1380
 
1381
- $key = $y . $m . $d;
 
1382
 
1383
- if ( ! isset( $temp_data['earnings'][ $key ] ) ) {
1384
- $temp_data['earnings'][ $key ] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
1385
  }
1386
 
1387
- $date_start = date( 'Y-m-d', strtotime( '+1 day', strtotime( $date_start ) ) );
1388
  }
1389
 
1390
- ksort( $temp_data['earnings'] );
1391
-
1392
- $earnings = $temp_data;
1393
 
1394
- $earnings['totals'] = $total;
1395
  } else {
1396
- $date_start = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day'];
1397
- $date_end = $dates['year'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
1398
-
1399
- $results = EDD()->payment_stats->get_earnings_by_range( $args['date'], false, $date_start, $date_end, $args['include_tax'] );
1400
- if ( $results instanceof WP_Error ) {
1401
- $error_message = __( 'There was an error retrieving earnings.', 'easy-digital-downloads' );
1402
-
1403
- foreach ( $results->errors as $error_key => $error_array ) {
1404
- if ( ! empty( $error_array[0] ) ) {
1405
- $error_message = $error_array[0];
1406
- }
1407
- }
1408
-
1409
- $error['error'] = sprintf( '%s %s', $error_message, $args['date'] );
1410
- } else {
1411
- $total_earnings = 0;
1412
- foreach ( $results as $result ) {
1413
- $total_earnings += $result['total'];
1414
- }
1415
-
1416
- $earnings['earnings'][ $args['date'] ] = edd_format_amount( $total_earnings );
1417
- }
1418
  }
1419
  } elseif ( $args['product'] == 'all' ) {
1420
  $products = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) );
 
1421
 
1422
- $i = 0;
1423
  foreach ( $products as $product_info ) {
1424
- $earnings['earnings'][ $i ] = array( $product_info->post_name => edd_get_download_earnings_stats( $product_info->ID ) );
 
 
 
 
 
 
 
 
 
1425
  $i ++;
1426
  }
1427
  } else {
1428
- if ( get_post_type( $args['product'] ) == 'download' ) {
1429
- $product_info = get_post( $args['product'] );
1430
- $earnings['earnings'][0] = array( $product_info->post_name => edd_get_download_earnings_stats( $args['product'] ) );
 
 
 
 
 
 
 
 
 
 
1431
  } else {
1432
  $error['error'] = sprintf( __( 'Product %s not found!', 'easy-digital-downloads' ), $args['product'] );
1433
  }
@@ -1439,18 +1470,9 @@ class EDD_API {
1439
 
1440
  return apply_filters( 'edd_api_stats_earnings', $earnings, $this );
1441
  } elseif ( $args['type'] == 'customers' ) {
1442
- if ( version_compare( $edd_version, '2.3', '<' ) || ! edd_has_upgrade_completed( 'upgrade_customer_payments_association' ) ) {
1443
- global $wpdb;
1444
- $stats = array();
1445
- $count = $wpdb->get_col( "SELECT COUNT(DISTINCT meta_value) FROM $wpdb->postmeta WHERE meta_key = '_edd_payment_user_email'" );
1446
- $stats['customers']['total_customers'] = $count[0];
1447
-
1448
- return apply_filters( 'edd_api_stats_customers', $stats, $this );
1449
- } else {
1450
- $stats['customers']['total_customers'] = edd_count_customers();
1451
 
1452
- return apply_filters( 'edd_api_stats_customers', $stats, $this );
1453
- }
1454
  } elseif ( empty( $args['type'] ) ) {
1455
  $stats = array_merge( $stats, $this->get_default_sales_stats() );
1456
  $stats = array_merge( $stats, $this->get_default_earnings_stats( $args ) );
@@ -2241,12 +2263,31 @@ class EDD_API {
2241
  */
2242
  private function get_default_sales_stats() {
2243
 
2244
- // Default sales return
2245
- $sales = array();
2246
- $sales['sales']['today'] = $this->stats->get_sales( 0, 'today' );
2247
- $sales['sales']['current_month'] = $this->stats->get_sales( 0, 'this_month' );
2248
- $sales['sales']['last_month'] = $this->stats->get_sales( 0, 'last_month' );
2249
- $sales['sales']['totals'] = edd_get_total_sales();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2250
 
2251
  return $sales;
2252
  }
@@ -2260,12 +2301,37 @@ class EDD_API {
2260
  */
2261
  private function get_default_earnings_stats( $args ) {
2262
 
2263
- // Default earnings return
2264
- $earnings = array();
2265
- $earnings['earnings']['today'] = $this->stats->get_earnings( 0, 'today', null, $args['include_tax'] );
2266
- $earnings['earnings']['current_month'] = $this->stats->get_earnings( 0, 'this_month', null, $args['include_tax'] );
2267
- $earnings['earnings']['last_month'] = $this->stats->get_earnings( 0, 'last_month', null, $args['include_tax'] );
2268
- $earnings['earnings']['totals'] = edd_get_total_earnings( $args['include_tax'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2269
 
2270
  return $earnings;
2271
  }
13
  * @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
14
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
15
  * @since 1.5
16
+ * @since 3.0.4 Refactored to use the new stats API, returns same formatting as 2.x API.
17
  */
18
 
19
  // Exit if accessed directly
20
  defined( 'ABSPATH' ) || exit;
21
 
22
+ use EDD\Reports;
23
+ use EDD\Stats;
24
+
25
  /**
26
  * EDD_API Class
27
  *
160
 
161
  // Setup EDD_Stats instance
162
  $this->stats = new EDD_Payment_Stats;
 
163
  }
164
 
165
  /**
1248
  $start_date = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day_start'];
1249
  $end_date = $dates['year_end'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
1250
 
1251
+ // Force the data for the reports API.
1252
+ $_GET['filter_from'] = $start_date;
1253
+ $_GET['filter_to'] = $end_date;
1254
+ $_GET['range'] = 'other';
1255
 
1256
+ $stats = new EDD\Stats(
1257
+ array(
1258
+ 'revenue_type' => 'net',
1259
+ )
1260
+ );
1261
+ $dates = EDD\Reports\parse_dates_for_range();
1262
 
1263
+ $total_sales = $stats->get_order_count(
1264
+ array(
1265
+ 'start' => $dates['start']->format( 'Y-m-d H:i:s' ),
1266
+ 'end' => $dates['end']->format( 'Y-m-d H:i:s' ),
1267
+ )
1268
+ );
1269
+
1270
+ $start_date = $dates['start']->format( 'Y-m-d' );
1271
+ $end_date = $dates['end']->format( 'Y-m-d' );
1272
 
1273
  while ( strtotime( $start_date ) <= strtotime( $end_date ) ) {
 
 
 
1274
 
1275
+ // Force the data for the reports API.
1276
+ $_GET['filter_from'] = $start_date;
1277
+ $_GET['filter_to'] = $start_date;
1278
+ $_GET['range'] = 'other';
1279
+
1280
+ $key = str_replace( '-', '', $start_date );
1281
+ $dates = EDD\Reports\parse_dates_for_range();
1282
 
1283
  if ( ! isset( $sales['sales'][ $key ] ) ) {
1284
+ $sales['sales'][ $key ] = $stats->get_order_count(
1285
+ array(
1286
+ 'start' => $dates['start']->startOfDay()->format( 'Y-m-d H:i:s' ),
1287
+ 'end' => $dates['end']->endOfDay()->format( 'Y-m-d H:i:s' ),
1288
+ )
1289
+ );
1290
  }
1291
 
1292
+ $start_date = $dates['start']->addDays( 1 )->format( 'Y-m-d' );
1293
  }
1294
 
1295
  ksort( $sales['sales'] );
1296
 
1297
+ $sales['totals'] = $total_sales;
 
 
 
 
 
 
 
 
1298
 
1299
+ } else {
1300
+ $stats = new EDD\Stats(
1301
+ array(
1302
+ 'range' => $args['date'],
1303
+ 'revenue_type' => 'net',
1304
+ )
1305
+ );
1306
 
1307
+ $sales['sales'][ $args['date'] ] = $stats->get_order_count();
 
 
 
 
 
 
 
 
 
 
 
1308
  }
1309
  } elseif ( $args['product'] == 'all' ) {
1310
  $products = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) );
1311
  $i = 0;
1312
+
1313
+ $stats = new EDD\Stats();
1314
  foreach ( $products as $product_info ) {
1315
+ $product_order_count = $stats->get_order_item_count(
1316
+ array(
1317
+ 'product_id' => $product_info->ID,
1318
+ )
1319
+ );
1320
+
1321
+ $sales['sales'][ $i ] = array(
1322
+ $product_info->post_name => $product_order_count,
1323
+ );
1324
  $i ++;
1325
  }
1326
  } else {
1327
+ if ( get_post_type( $args['product'] ) === 'download' ) {
1328
+ $stats = new EDD\Stats();
1329
+ $product_info = get_post( $args['product'] );
1330
+ $order_item_count = $stats->get_order_item_count(
1331
+ array(
1332
+ 'product_id' => $args['product'],
1333
+ )
1334
+ );
1335
+
1336
+ $sales['sales'][0] = array(
1337
+ $product_info->post_name => $order_item_count,
1338
+ );
1339
  } else {
1340
  $error['error'] = sprintf( __( 'Product %s not found!', 'easy-digital-downloads' ), $args['product'] );
1341
  }
1346
  }
1347
 
1348
  return apply_filters( 'edd_api_stats_sales', $sales, $this );
1349
+ } elseif ( $args['type'] === 'earnings' ) {
1350
  if ( $args['product'] == null ) {
1351
  if ( $args['date'] == null ) {
1352
  $earnings = $this->get_default_earnings_stats( $args );
1363
  $error['error'] = __( 'Invalid or no date range specified!', 'easy-digital-downloads' );
1364
  }
1365
 
1366
+ $start_date = $dates['year'] . '-' . $dates['m_start'] . '-' . $dates['day_start'];
1367
+ $end_date = $dates['year_end'] . '-' . $dates['m_end'] . '-' . $dates['day_end'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1368
 
1369
+ // Force the data for the reports API.
1370
+ $_GET['filter_from'] = $start_date;
1371
+ $_GET['filter_to'] = $end_date;
1372
+ $_GET['range'] = 'other';
1373
 
1374
+ $stats = new EDD\Stats(
1375
+ array(
1376
+ 'revenue_type' => 'net',
1377
+ 'exclude_taxes' => ! $args['include_tax'],
1378
+ 'output' => 'typed',
1379
+ )
1380
+ );
1381
+ $dates = EDD\Reports\parse_dates_for_range();
1382
 
1383
+ $total_earnings = $stats->get_order_earnings(
1384
+ array(
1385
+ 'start' => $dates['start']->format( 'Y-m-d H:i:s' ),
1386
+ 'end' => $dates['end']->format( 'Y-m-d H:i:s' ),
1387
+ )
1388
+ );
1389
 
1390
+ $start_date = $dates['start']->format( 'Y-m-d' );
1391
+ $end_date = $dates['end']->format( 'Y-m-d' );
 
 
1392
 
1393
+ $earnings['earnings'] = array();
1394
+ while ( strtotime( $start_date ) <= strtotime( $end_date ) ) {
1395
 
1396
+ // Force the data for the reports API.
1397
+ $_GET['filter_from'] = $start_date;
1398
+ $_GET['filter_to'] = $start_date;
1399
+ $_GET['range'] = 'other';
1400
+
1401
+ $key = str_replace( '-', '', $start_date );
1402
+ $dates = EDD\Reports\parse_dates_for_range();
1403
+
1404
+ if ( ! isset( $sales['earnings'][ $key ] ) ) {
1405
+ $earnings['earnings'][ $key ] = $stats->get_order_earnings(
1406
+ array(
1407
+ 'start' => $dates['start']->format( 'Y-m-d H:i:s' ),
1408
+ 'end' => $dates['end']->format( 'Y-m-d H:i:s' ),
1409
+ )
1410
+ );
1411
  }
1412
 
1413
+ $start_date = $dates['start']->addDays( 1 )->format( 'Y-m-d' );
1414
  }
1415
 
1416
+ ksort( $earnings['earnings'] );
 
 
1417
 
1418
+ $earnings['totals'] = $total_earnings;
1419
  } else {
1420
+ $stats = new EDD\Stats(
1421
+ array(
1422
+ 'range' => $args['date'],
1423
+ 'revenue_type' => 'net',
1424
+ 'exclude_tax' => ! $args['include_tax'],
1425
+ 'output' => 'typed',
1426
+ )
1427
+ );
1428
+ $earnings['earnings'][ $args['date'] ] = $stats->get_order_earnings();
 
 
 
 
 
 
 
 
 
 
 
 
 
1429
  }
1430
  } elseif ( $args['product'] == 'all' ) {
1431
  $products = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) );
1432
+ $i = 0;
1433
 
1434
+ $stats = new EDD\Stats();
1435
  foreach ( $products as $product_info ) {
1436
+ $product_earnings = $stats->get_order_item_earnings(
1437
+ array(
1438
+ 'product_id' => $product_info->ID,
1439
+ 'output' => 'typed',
1440
+ )
1441
+ );
1442
+
1443
+ $earnings['earnings'][ $i ] = array(
1444
+ $product_info->post_name => $product_earnings,
1445
+ );
1446
  $i ++;
1447
  }
1448
  } else {
1449
+ if ( get_post_type( $args['product'] ) === 'download' ) {
1450
+ $stats = new EDD\Stats();
1451
+ $product_info = get_post( $args['product'] );
1452
+ $order_item_earnings = $stats->get_order_item_earnings(
1453
+ array(
1454
+ 'product_id' => $args['product'],
1455
+ 'output' => 'typed',
1456
+ )
1457
+ );
1458
+
1459
+ $earnings['earnings'][0] = array(
1460
+ $product_info->post_name => $order_item_earnings,
1461
+ );
1462
  } else {
1463
  $error['error'] = sprintf( __( 'Product %s not found!', 'easy-digital-downloads' ), $args['product'] );
1464
  }
1470
 
1471
  return apply_filters( 'edd_api_stats_earnings', $earnings, $this );
1472
  } elseif ( $args['type'] == 'customers' ) {
1473
+ $stats['customers']['total_customers'] = edd_count_customers();
 
 
 
 
 
 
 
 
1474
 
1475
+ return apply_filters( 'edd_api_stats_customers', $stats, $this );
 
1476
  } elseif ( empty( $args['type'] ) ) {
1477
  $stats = array_merge( $stats, $this->get_default_sales_stats() );
1478
  $stats = array_merge( $stats, $this->get_default_earnings_stats( $args ) );
2263
  */
2264
  private function get_default_sales_stats() {
2265
 
2266
+ $stats = new EDD\Stats(
2267
+ array(
2268
+ 'range' => 'today',
2269
+ 'revenue_type' => 'net',
2270
+ )
2271
+ );
2272
+ $sales['sales']['today'] = $stats->get_order_count();
2273
+
2274
+ $stats = new EDD\Stats(
2275
+ array(
2276
+ 'range' => 'this_month',
2277
+ 'revenue_type' => 'net',
2278
+ )
2279
+ );
2280
+ $sales['sales']['current_month'] = $stats->get_order_count();
2281
+
2282
+ $stats = new EDD\Stats(
2283
+ array(
2284
+ 'range' => 'last_month',
2285
+ 'revenue_type' => 'net',
2286
+ )
2287
+ );
2288
+ $sales['sales']['last_month'] = $stats->get_order_count();
2289
+
2290
+ $sales['sales']['totals'] = edd_get_total_sales();
2291
 
2292
  return $sales;
2293
  }
2301
  */
2302
  private function get_default_earnings_stats( $args ) {
2303
 
2304
+ $stats = new EDD\Stats(
2305
+ array(
2306
+ 'range' => 'today',
2307
+ 'exclude_taxes' => ! $args['include_tax'],
2308
+ 'revenue_type' => 'net',
2309
+ 'output' => 'typed',
2310
+ )
2311
+ );
2312
+ $earnings['earnings']['today'] = $stats->get_order_earnings();
2313
+
2314
+ $stats = new EDD\Stats(
2315
+ array(
2316
+ 'range' => 'this_month',
2317
+ 'exclude_taxes' => ! $args['include_tax'],
2318
+ 'revenue_type' => 'net',
2319
+ 'output' => 'typed',
2320
+ )
2321
+ );
2322
+ $earnings['earnings']['current_month'] = $stats->get_order_earnings();
2323
+
2324
+ $stats = new EDD\Stats(
2325
+ array(
2326
+ 'range' => 'last_month',
2327
+ 'exclude_taxes' => ! $args['include_tax'],
2328
+ 'revenue_type' => 'net',
2329
+ 'output' => 'typed',
2330
+ )
2331
+ );
2332
+ $earnings['earnings']['last_month'] = $stats->get_order_earnings();
2333
+
2334
+ $earnings['earnings']['totals'] = edd_get_total_earnings( $args['include_tax'] );
2335
 
2336
  return $earnings;
2337
  }
includes/class-easy-digital-downloads.php CHANGED
@@ -315,7 +315,7 @@ final class Easy_Digital_Downloads {
315
 
316
  // Plugin version.
317
  if ( ! defined( 'EDD_VERSION' ) ) {
318
- define( 'EDD_VERSION', '3.0.3' );
319
  }
320
 
321
  // Plugin Root File.
315
 
316
  // Plugin version.
317
  if ( ! defined( 'EDD_VERSION' ) ) {
318
+ define( 'EDD_VERSION', '3.0.4' );
319
  }
320
 
321
  // Plugin Root File.
includes/class-edd-cache-helper.php CHANGED
@@ -75,18 +75,6 @@ class EDD_Cache_Helper {
75
  }
76
  }
77
  }
78
-
79
- add_action( 'edd_pre_update_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
80
- add_action( 'edd_pre_insert_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
81
- add_action( 'edd_pre_delete_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
82
- add_action( 'edd_pre_update_discount_status', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
83
- add_action( 'edd_pre_remove_cart_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
84
-
85
- add_action( 'edd_post_update_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
86
- add_action( 'edd_post_insert_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
87
- add_action( 'edd_post_delete_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
88
- add_action( 'edd_post_update_discount_status', array( $this, 'w3tc_suspend_cache_addition_post' ) );
89
- add_action( 'edd_post_remove_cart_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
90
  }
91
 
92
  /**
@@ -138,17 +126,19 @@ class EDD_Cache_Helper {
138
  * Prevents W3TC from adding to the cache prior to modifying data.
139
  *
140
  * @since 1.7
 
141
  */
142
  public function w3tc_suspend_cache_addition_pre() {
143
- wp_suspend_cache_addition( true );
144
  }
145
 
146
  /**
147
  * Prevents W3TC from adding to the cache after modifying data.
148
  *
149
  * @since 1.7
 
150
  */
151
  public function w3tc_suspend_cache_addition_post() {
152
- wp_suspend_cache_addition();
153
  }
154
  }
75
  }
76
  }
77
  }
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
 
80
  /**
126
  * Prevents W3TC from adding to the cache prior to modifying data.
127
  *
128
  * @since 1.7
129
+ * @since 3.0.4 Removed the cache suspend call.
130
  */
131
  public function w3tc_suspend_cache_addition_pre() {
132
+ // This function does nothing as of EDD 3.0.4, it is only left here to prevent fatal errors in case it was used.
133
  }
134
 
135
  /**
136
  * Prevents W3TC from adding to the cache after modifying data.
137
  *
138
  * @since 1.7
139
+ * @since 3.0.4 Removed the cache suspend call.
140
  */
141
  public function w3tc_suspend_cache_addition_post() {
142
+ // This function does nothing as of EDD 3.0.4, it is only left here to prevent fatal errors in case it was used.
143
  }
144
  }
includes/class-edd-customer.php CHANGED
@@ -276,7 +276,6 @@ class EDD_Customer extends \EDD\Database\Rows\Customer {
276
  // Add the customer
277
  $customer_id = edd_add_customer( $args );
278
 
279
- // The DB class 'add' implies an update if the customer being asked to be created already exists
280
  if ( ! empty( $customer_id ) ) {
281
 
282
  // Add the primary email address for this customer
@@ -334,25 +333,12 @@ class EDD_Customer extends \EDD\Database\Rows\Customer {
334
 
335
  do_action( 'edd_customer_pre_update', $this->id, $data );
336
 
337
- $updated = false;
338
- $previous_user_id = $this->user_id;
339
 
340
  if ( edd_update_customer( $this->id, $data ) ) {
341
  $customer = edd_get_customer( $this->id );
342
  $this->setup_customer( $customer );
343
 
344
- // If the user ID changed, we need to update all the orders associated with this customer and change the user ID.
345
- if ( intval( $previous_user_id ) !== intval( $this->user_id ) ) {
346
-
347
- // Update some payment meta if we need to
348
- $order_ids = edd_get_orders( array( 'customer_id' => $this->id, 'number' => 9999999 ) );
349
-
350
- foreach ( $order_ids as $order_id ) {
351
- edd_update_order( $order_id, array( 'user_id' => $this->user_id ) );
352
- }
353
-
354
- }
355
-
356
  $updated = true;
357
  }
358
 
@@ -660,40 +646,43 @@ class EDD_Customer extends \EDD\Database\Rows\Customer {
660
  *
661
  * @since 2.3
662
  *
663
- * @param int $payment_id The payment ID to attach to the customer.
664
  * @param bool $update_stats For backwards compatibility, if we should increase the stats or not.
665
  *
666
  * @return bool True if the attachment was successfully, false otherwise.
667
  */
668
- public function attach_payment( $payment_id = 0, $update_stats = true ) {
669
 
670
- // Bail if no payment ID
671
- if ( empty( $payment_id ) ) {
672
  return false;
673
  }
674
 
675
- // Get payment
676
- $order = edd_get_order( $payment_id );
677
 
678
- // Bail if payment does not exist
679
  if ( empty( $order ) ) {
680
  return false;
681
  }
682
 
683
- // Bail if already attached
684
- if ( (int) $order->customer_id === (int) $this->id ) {
685
- return true;
686
- }
687
-
688
  do_action( 'edd_customer_pre_attach_payment', $order->id, $this->id, $this );
689
 
690
- // Update the order
691
- $success = (bool) edd_update_order( $payment_id, array(
692
- 'customer_id' => $this->id,
693
- 'email' => $this->email
694
- ) );
 
 
 
 
 
 
 
 
695
 
696
- // Maybe update stats
697
  if ( ! empty( $success ) && ! empty( $update_stats ) ) {
698
  $this->recalculate_stats();
699
  }
276
  // Add the customer
277
  $customer_id = edd_add_customer( $args );
278
 
 
279
  if ( ! empty( $customer_id ) ) {
280
 
281
  // Add the primary email address for this customer
333
 
334
  do_action( 'edd_customer_pre_update', $this->id, $data );
335
 
336
+ $updated = false;
 
337
 
338
  if ( edd_update_customer( $this->id, $data ) ) {
339
  $customer = edd_get_customer( $this->id );
340
  $this->setup_customer( $customer );
341
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  $updated = true;
343
  }
344
 
646
  *
647
  * @since 2.3
648
  *
649
+ * @param int $order_id The Order ID to attach to the customer.
650
  * @param bool $update_stats For backwards compatibility, if we should increase the stats or not.
651
  *
652
  * @return bool True if the attachment was successfully, false otherwise.
653
  */
654
+ public function attach_payment( $order_id = 0, $update_stats = true ) {
655
 
656
+ // Bail if no payment ID.
657
+ if ( empty( $order_id ) ) {
658
  return false;
659
  }
660
 
661
+ // Get order.
662
+ $order = edd_get_order( $order_id );
663
 
664
+ // Bail if payment does not exist.
665
  if ( empty( $order ) ) {
666
  return false;
667
  }
668
 
 
 
 
 
 
669
  do_action( 'edd_customer_pre_attach_payment', $order->id, $this->id, $this );
670
 
671
+ $success = (int) $order->customer_id === (int) $this->id;
672
+
673
+ // Update the order if it isn't already attached.
674
+ if ( ! $success ) {
675
+ // Update the order.
676
+ $success = (bool) edd_update_order(
677
+ $order_id,
678
+ array(
679
+ 'customer_id' => $this->id,
680
+ 'email' => $this->email,
681
+ )
682
+ );
683
+ }
684
 
685
+ // Maybe update stats.
686
  if ( ! empty( $success ) && ! empty( $update_stats ) ) {
687
  $this->recalculate_stats();
688
  }
includes/class-edd-license-handler.php CHANGED
@@ -141,6 +141,9 @@ class EDD_License {
141
 
142
  // Add the EDD version to the API parameters.
143
  add_filter( 'edd_sl_plugin_updater_api_params', array( $this, 'filter_sl_api_params' ), 10, 3 );
 
 
 
144
  }
145
 
146
  /**
@@ -564,6 +567,31 @@ class EDD_License {
564
 
565
  return $api_params;
566
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  }
568
 
569
  endif; // end class_exists check
141
 
142
  // Add the EDD version to the API parameters.
143
  add_filter( 'edd_sl_plugin_updater_api_params', array( $this, 'filter_sl_api_params' ), 10, 3 );
144
+
145
+ // Fix missing Stripe keys due to option name change.
146
+ add_action( 'admin_init', array( $this, 'fix_stripe_key' ) );
147
  }
148
 
149
  /**
567
 
568
  return $api_params;
569
  }
570
+
571
+ /**
572
+ * If the original Stripe gateway key is set and the new one is not,
573
+ * update the license key to fix automatic updates.
574
+ *
575
+ * @since 3.0.4
576
+ * @return void
577
+ */
578
+ public function fix_stripe_key() {
579
+ $license_key = edd_get_option( 'edd_stripe_pro_payment_gateway_license_key' );
580
+ if ( $license_key ) {
581
+ return;
582
+ }
583
+ $old_key = edd_get_option( 'edd_stripe_payment_gateway_license_key' );
584
+ if ( $old_key ) {
585
+ edd_update_option( 'edd_stripe_pro_payment_gateway_license_key', sanitize_text_field( $old_key ) );
586
+ edd_delete_option( 'edd_stripe_payment_gateway_license_key' );
587
+ }
588
+
589
+ $old_license_status = get_option( 'edd_stripe_payment_gateway_license_key_active' );
590
+ if ( $old_license_status ) {
591
+ update_option( 'edd_stripe_pro_payment_gateway_license_key_active', santize_text_field( $old_license_status ) );
592
+ delete_option( 'edd_stripe_payment_gateway_license_key_active' );
593
+ }
594
+ }
595
  }
596
 
597
  endif; // end class_exists check
includes/class-stats.php CHANGED
@@ -238,7 +238,7 @@ class Stats {
238
  * This may be overridden in $query parameters that get passed through.
239
  */
240
  $this->query_vars['type'] = $this->get_revenue_type_order_types();
241
- $this->query_vars['status'] = $this->get_revenue_type_statuses();
242
 
243
  /**
244
  * Filters Order statuses that should be included when calculating stats.
@@ -2842,7 +2842,7 @@ class Stats {
2842
  return $data;
2843
  }
2844
 
2845
- $allowed_output_formats = array( 'raw', 'formatted' );
2846
 
2847
  // Output format. Default raw.
2848
  $output = isset( $this->query_vars['output'] ) && in_array( $this->query_vars['output'], $allowed_output_formats, true )
@@ -2862,18 +2862,30 @@ class Stats {
2862
  if ( is_object( $data ) ) {
2863
  foreach ( array_keys( get_object_vars( $data ) ) as $field ) {
2864
  if ( is_numeric( $data->{$field} ) ) {
2865
- $data->{$field} = edd_currency_filter( edd_format_amount( $data->{$field} ), $currency );
 
 
 
 
2866
  }
2867
  }
2868
  } elseif ( is_array( $data ) ) {
2869
  foreach ( array_keys( $data ) as $field ) {
2870
  if ( is_numeric( $data[ $field ] ) ) {
2871
- $data[ $field ] = edd_currency_filter( edd_format_amount( $data[ $field ] ), $currency );
 
 
 
 
2872
  }
2873
  }
2874
  } else {
2875
  if ( is_numeric( $data ) ) {
2876
- $data = edd_currency_filter( edd_format_amount( $data ), $currency );
 
 
 
 
2877
  }
2878
  }
2879
 
238
  * This may be overridden in $query parameters that get passed through.
239
  */
240
  $this->query_vars['type'] = $this->get_revenue_type_order_types();
241
+ $this->query_vars['status'] = edd_get_gross_order_statuses();
242
 
243
  /**
244
  * Filters Order statuses that should be included when calculating stats.
2842
  return $data;
2843
  }
2844
 
2845
+ $allowed_output_formats = array( 'raw', 'typed', 'formatted' );
2846
 
2847
  // Output format. Default raw.
2848
  $output = isset( $this->query_vars['output'] ) && in_array( $this->query_vars['output'], $allowed_output_formats, true )
2862
  if ( is_object( $data ) ) {
2863
  foreach ( array_keys( get_object_vars( $data ) ) as $field ) {
2864
  if ( is_numeric( $data->{$field} ) ) {
2865
+ $data->{$field} = edd_format_amount( $data->{$field}, true, $currency, $output );
2866
+
2867
+ if ( 'formatted' === $output ) {
2868
+ $data->{$field} = edd_currency_filter( $data->{$field}, $currency );
2869
+ }
2870
  }
2871
  }
2872
  } elseif ( is_array( $data ) ) {
2873
  foreach ( array_keys( $data ) as $field ) {
2874
  if ( is_numeric( $data[ $field ] ) ) {
2875
+ $data[ $field ] = edd_format_amount( $data[ $field ], true, $currency, $output );
2876
+
2877
+ if ( 'formatted' === $output ) {
2878
+ $data[ $field ] = edd_currency_filter( $data[ $field ], $currency );
2879
+ }
2880
  }
2881
  }
2882
  } else {
2883
  if ( is_numeric( $data ) ) {
2884
+ $data = edd_format_amount( $data, true, $currency, $output );
2885
+
2886
+ if ( 'formatted' === $output ) {
2887
+ $data = edd_currency_filter( $data, $currency );
2888
+ }
2889
  }
2890
  }
2891
 
includes/compat/class-template.php CHANGED
@@ -55,6 +55,14 @@ class Template extends Base {
55
  public function update_receipt_template() {
56
  $access_type = get_filesystem_method();
57
 
 
 
 
 
 
 
 
 
58
  // Retrieve the path to the template being used.
59
  $template = edd_locate_template( 'shortcode-receipt.php' );
60
 
@@ -86,16 +94,20 @@ class Template extends Base {
86
 
87
  $get_post_call_exists = strstr( $contents, 'get_post( $edd_receipt_args[\'id\'] )' );
88
 
 
 
 
 
89
  $contents = str_replace( 'get_post( $edd_receipt_args[\'id\'] )', 'edd_get_payment( $edd_receipt_args[\'id\'] )', $contents );
90
  $updated = $wp_filesystem->put_contents( $template, $contents );
91
 
92
- // Only display a notice if a `get_post()` call exists.
93
- if ( ! $updated && $get_post_call_exists ) {
94
  add_action( 'admin_notices', function() use ( $template ) {
95
  ?>
96
  <div class="notice notice-error">
97
  <p><?php esc_html_e( 'Easy Digital Downloads failed to automatically update your purchase receipt template. This update is necessary for the purchase receipt to display correctly.', 'easy-digital-downloads' ); ?></p>
98
- <p><?php printf( __( 'This update must be completed manually. Please click %shere%s for more information.', 'easy-digital-downloads' ), '<a href="https://docs.easydigitaldownloads.com/article/2061-template-update-for-3-0">', '</a>' ); ?></p>
99
  <p><?php esc_html_e( 'The file that needs to be updated is located at:', 'easy-digital-downloads' ); ?> <code><?php echo esc_html( $template ); ?></code></p>
100
  </div>
101
  <?php
55
  public function update_receipt_template() {
56
  $access_type = get_filesystem_method();
57
 
58
+ $last_checked = get_transient( 'edd-sc-receipt-check' );
59
+ if ( false !== $last_checked ) {
60
+ return false;
61
+ }
62
+
63
+ // Only run this once a day.
64
+ set_transient( 'edd-sc-receipt-check', DAY_IN_SECONDS );
65
+
66
  // Retrieve the path to the template being used.
67
  $template = edd_locate_template( 'shortcode-receipt.php' );
68
 
94
 
95
  $get_post_call_exists = strstr( $contents, 'get_post( $edd_receipt_args[\'id\'] )' );
96
 
97
+ if ( false === $get_post_call_exists ) {
98
+ return;
99
+ }
100
+
101
  $contents = str_replace( 'get_post( $edd_receipt_args[\'id\'] )', 'edd_get_payment( $edd_receipt_args[\'id\'] )', $contents );
102
  $updated = $wp_filesystem->put_contents( $template, $contents );
103
 
104
+ // Only display a notice if we could not update the file.
105
+ if ( ! $updated ) {
106
  add_action( 'admin_notices', function() use ( $template ) {
107
  ?>
108
  <div class="notice notice-error">
109
  <p><?php esc_html_e( 'Easy Digital Downloads failed to automatically update your purchase receipt template. This update is necessary for the purchase receipt to display correctly.', 'easy-digital-downloads' ); ?></p>
110
+ <p><?php printf( __( 'This update must be completed manually. Please click %shere%s for more information.', 'easy-digital-downloads' ), '<a href="https://easydigitaldownloads.com/development/2018/06/21/breaking-changes-to-orders-in-easy-digital-downloads-3-0/">', '</a>' ); ?></p>
111
  <p><?php esc_html_e( 'The file that needs to be updated is located at:', 'easy-digital-downloads' ); ?> <code><?php echo esc_html( $template ); ?></code></p>
112
  </div>
113
  <?php
includes/currency/class-money-formatter.php CHANGED
@@ -19,6 +19,11 @@ class Money_Formatter {
19
  */
20
  public $amount;
21
 
 
 
 
 
 
22
  /**
23
  * @var int|float Original, unmodified amount passed in via constructor.
24
  */
@@ -36,8 +41,10 @@ class Money_Formatter {
36
  * @param Currency $currency
37
  */
38
  public function __construct( $amount, Currency $currency ) {
39
- $this->amount = $this->original_amount = $amount;
40
- $this->currency = $currency;
 
 
41
  }
42
 
43
  /**
@@ -49,7 +56,7 @@ class Money_Formatter {
49
  * @return float|int
50
  */
51
  private function unformat() {
52
- $amount = $this->amount;
53
 
54
  $sep_found = strpos( $amount, $this->currency->decimal_separator );
55
  if ( ',' === $this->currency->decimal_separator && false !== $sep_found ) {
@@ -68,11 +75,38 @@ class Money_Formatter {
68
  return $amount;
69
  }
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * Formats the amount for display.
73
  * Does not apply the currency code.
74
  *
75
  * @since 3.0
 
 
 
76
  * @return Money_Formatter
77
  */
78
  public function format_for_display( $decimals = true ) {
@@ -82,18 +116,9 @@ class Money_Formatter {
82
  $amount = 0;
83
  }
84
 
85
- /**
86
- * Filter number of decimals to use for formatted amount
87
- *
88
- * @since unknown
89
- *
90
- * @param int $number Default 2. Number of decimals.
91
- * @param int|string $amount Amount being formatted.
92
- * @param string $currency_code Currency code being formatted.
93
- */
94
- $decimals = apply_filters( 'edd_format_amount_decimals', $decimals ? $this->currency->number_decimals : 0, $amount, $this->currency->code );
95
 
96
- // Format amount using decimals and separators (also rounds up or down)
97
  $formatted = number_format( (float) $amount, $decimals, $this->currency->decimal_separator, $this->currency->thousands_separator );
98
 
99
  /**
@@ -113,6 +138,41 @@ class Money_Formatter {
113
  return $this;
114
  }
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  /**
117
  * Applies the currency prefix/suffix to the amount.
118
  *
19
  */
20
  public $amount;
21
 
22
+ /**
23
+ * @var float Typed amount.
24
+ */
25
+ public $typed_amount;
26
+
27
  /**
28
  * @var int|float Original, unmodified amount passed in via constructor.
29
  */
41
  * @param Currency $currency
42
  */
43
  public function __construct( $amount, Currency $currency ) {
44
+ $this->original_amount = $amount;
45
+ $this->amount = $amount;
46
+ $this->typed_amount = $amount;
47
+ $this->currency = $currency;
48
  }
49
 
50
  /**
56
  * @return float|int
57
  */
58
  private function unformat() {
59
+ $amount = $this->original_amount;
60
 
61
  $sep_found = strpos( $amount, $this->currency->decimal_separator );
62
  if ( ',' === $this->currency->decimal_separator && false !== $sep_found ) {
75
  return $amount;
76
  }
77
 
78
+ /**
79
+ * Returns the number of decimals ot use for the formatted amount.
80
+ *
81
+ * Based on the currency code used when instantiating the class, determines how many
82
+ * decimal points the value should have once formatted.
83
+ *
84
+ * @param bool $decimals If we should include decimals or not in the formatted amount.
85
+ * @param float $amount The amount to format.
86
+ *
87
+ * @return int The number of decimals places to use when formatting the amount.
88
+ */
89
+ private function get_decimals( $decimals, $amount ) {
90
+ /**
91
+ * Filter number of decimals to use for formatted amount
92
+ *
93
+ * @since unknown
94
+ *
95
+ * @param int $number Default 2. Number of decimals.
96
+ * @param int|string $amount Amount being formatted.
97
+ * @param string $currency_code Currency code being formatted.
98
+ */
99
+ return apply_filters( 'edd_format_amount_decimals', $decimals ? $this->currency->number_decimals : 0, $amount, $this->currency->code );
100
+ }
101
+
102
  /**
103
  * Formats the amount for display.
104
  * Does not apply the currency code.
105
  *
106
  * @since 3.0
107
+ *
108
+ * @param bool $decimals If we should include decimal places or not when formatting.
109
+ *
110
  * @return Money_Formatter
111
  */
112
  public function format_for_display( $decimals = true ) {
116
  $amount = 0;
117
  }
118
 
119
+ $decimals = $this->get_decimals( $decimals, $amount );
 
 
 
 
 
 
 
 
 
120
 
121
+ // Format amount using decimals and separators (also rounds up or down).
122
  $formatted = number_format( (float) $amount, $decimals, $this->currency->decimal_separator, $this->currency->thousands_separator );
123
 
124
  /**
138
  return $this;
139
  }
140
 
141
+ /**
142
+ * Formats the amount for typed data returns.
143
+ * Does not apply the currency code and returns a foat instead of a string.
144
+ *
145
+ * @since 3.0
146
+ *
147
+ * @param bool $decimals If we should include decimal places or not when formatting.
148
+ *
149
+ * @return Money_Formatter
150
+ */
151
+ public function format_for_typed( $decimals = true ) {
152
+ $amount = $this->unformat();
153
+
154
+ if ( empty( $amount ) ) {
155
+ $amount = 0;
156
+ }
157
+
158
+ $decimals = $this->get_decimals( $decimals, $amount );
159
+
160
+ /**
161
+ * Since we want to return a float value here, intentionally only supply a decimal separator.
162
+ *
163
+ * The separators here are hard coded intentionally as we're looking to get truncated, raw format of float
164
+ * which requires '.' for decimal separators and no thousands separator.
165
+ *
166
+ * This is also intentionally not filtered for the time being.
167
+ */
168
+ $formatted = floatval( number_format( (float) $amount, $decimals, '.', '' ) );
169
+
170
+ // Set the amount to $this->amount.
171
+ $this->typed_amount = $formatted;
172
+
173
+ return $this;
174
+ }
175
+
176
  /**
177
  * Applies the currency prefix/suffix to the amount.
178
  *
includes/customer-functions.php CHANGED
@@ -51,9 +51,22 @@ function edd_add_customer( $data = array() ) {
51
  return false;
52
  }
53
 
54
- $customers = new EDD\Database\Queries\Customer();
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- return $customers->add_item( $data );
57
  }
58
 
59
  /**
@@ -67,7 +80,20 @@ function edd_add_customer( $data = array() ) {
67
  function edd_delete_customer( $customer_id = 0 ) {
68
  $customers = new EDD\Database\Queries\Customer();
69
 
70
- return $customers->delete_item( $customer_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
 
73
  /**
@@ -114,7 +140,22 @@ function edd_destroy_customer( $customer_id = 0 ) {
114
  }
115
 
116
  // Delete the customer.
117
- return edd_delete_customer( $customer_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
 
120
  /**
@@ -148,7 +189,23 @@ function edd_destroy_customer( $customer_id = 0 ) {
148
  function edd_update_customer( $customer_id = 0, $data = array() ) {
149
  $customers = new EDD\Database\Queries\Customer();
150
 
151
- return $customers->update_item( $customer_id, $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
  /**
@@ -199,7 +256,17 @@ function edd_get_customer_by( $field = '', $value = '' ) {
199
  }
200
 
201
  $customers = new EDD\Database\Queries\Customer();
202
- $customer = $customers->get_item_by( $field, $value );
 
 
 
 
 
 
 
 
 
 
203
 
204
  /**
205
  * Filters the single Customer retrieved from the database based on field.
51
  return false;
52
  }
53
 
54
+ $customers = new EDD\Database\Queries\Customer();
55
+ $customer_id = $customers->add_item( $data );
56
+
57
+ if ( ! empty( $customer_id ) ) {
58
+ /**
59
+ * Action that runs when a customer is added with the edd_add_customer function.
60
+ *
61
+ * @since 3.0.4
62
+ *
63
+ * @param int $customer_id Customer ID added.
64
+ * @param array $data Array of arguments sent to create the customer with.
65
+ */
66
+ do_action( 'edd_customer_added', $customer_id, $data );
67
+ }
68
 
69
+ return $customer_id;
70
  }
71
 
72
  /**
80
  function edd_delete_customer( $customer_id = 0 ) {
81
  $customers = new EDD\Database\Queries\Customer();
82
 
83
+ $customer_deleted = $customers->delete_item( $customer_id );
84
+
85
+ if ( ! empty( $customer_deleted ) ) {
86
+ /**
87
+ * Action that runs when a customer is deleted with the edd_delete_customer function.
88
+ *
89
+ * @since 3.0.4
90
+ *
91
+ * @param int $customer_id Customer ID being deleted.
92
+ */
93
+ do_action( 'edd_customer_deleted', $customer_id );
94
+ }
95
+
96
+ return $customer_deleted;
97
  }
98
 
99
  /**
140
  }
141
 
142
  // Delete the customer.
143
+ $customer_destroyed = edd_delete_customer( $customer_id );
144
+ if ( ! empty( $customer_destroyed ) ) {
145
+ /**
146
+ * Action that runs when a customer is destroyed with the edd_destroy_customer function.
147
+ *
148
+ * This action is similar to edd_customer_deleted and includes running that action,
149
+ * but also includes deleting all customer addresses and email addresses.
150
+ *
151
+ * @since 3.0.4
152
+ *
153
+ * @param int $customer_id Customer ID being destroyed.
154
+ */
155
+ do_action( 'edd_customer_destroyed', $customer_id );
156
+ }
157
+
158
+ return $customer_destroyed;
159
  }
160
 
161
  /**
189
  function edd_update_customer( $customer_id = 0, $data = array() ) {
190
  $customers = new EDD\Database\Queries\Customer();
191
 
192
+ $previous_customer_data = edd_get_customer( $customer_id );
193
+ $customer_updated = $customers->update_item( $customer_id, $data );
194
+
195
+ if ( ! empty( $customer_updated ) ) {
196
+ /**
197
+ * Action that runs when a customer is updated with the edd_update_customer function.
198
+ *
199
+ * @since 3.0.4
200
+ *
201
+ * @param int $customer_id Customer ID updated.
202
+ * @param array $data Array of arguments sent to create the customer with.
203
+ * @param EDD_Customer $previous_customer_data The customer row before it was updated.
204
+ */
205
+ do_action( 'edd_customer_updated', $customer_id, $data, $previous_customer_data );
206
+ }
207
+
208
+ return $customer_updated;
209
  }
210
 
211
  /**
256
  }
257
 
258
  $customers = new EDD\Database\Queries\Customer();
259
+ if ( 'email' === $field ) {
260
+ $customer_emails = new EDD\Database\Queries\Customer_Email_Address();
261
+ $customer_email = $customer_emails->get_item_by( 'email', $value );
262
+
263
+ $customer = false;
264
+ if ( ! empty( $customer_email->customer_id ) ) {
265
+ $customer = $customers->get_item_by( 'id', $customer_email->customer_id );
266
+ }
267
+ } else {
268
+ $customer = $customers->get_item_by( $field, $value );
269
+ }
270
 
271
  /**
272
  * Filters the single Customer retrieved from the database based on field.
includes/customers/customer-actions.php CHANGED
@@ -11,6 +11,148 @@
11
  * @since 3.0
12
  */
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
  * When a new primary address is added to the database, any other primary addresses should be demoted.
16
  *
11
  * @since 3.0
12
  */
13
 
14
+ /**
15
+ * Is intended to be used when adding a customer directly with edd_add_customer function.
16
+ *
17
+ * Because the edd_add_customer function only directly interacts with the customers DB table, we may
18
+ * need to do some additional actions like adding items to the customer email addresses table.
19
+ *
20
+ * @since 3.0.4
21
+ *
22
+ * @param int $customer_id The customer ID that was added.
23
+ * @param array $data The data passed in to add the customer.
24
+ */
25
+ function edd_process_customer_added( $customer_id, $data ) {
26
+ // Make sure we add a new primary email address to the email addresses table.
27
+ edd_add_customer_email_address(
28
+ array(
29
+ 'customer_id' => $customer_id,
30
+ 'email' => $data['email'],
31
+ 'type' => 'primary',
32
+ )
33
+ );
34
+ }
35
+ add_action( 'edd_customer_added', 'edd_process_customer_added', 10, 2 );
36
+
37
+ /**
38
+ * Is intended to be used when updating a customer directly with edd_add_customer function.
39
+ *
40
+ * Because the edd_update_customer function only directly interacts with the customers DB table, we may
41
+ * need to do some additional actions like managing email addresses.
42
+ *
43
+ * @since 3.0.4
44
+ *
45
+ * @param int $customer_id The customer ID being updated.
46
+ * @param array $data The data passed in to update the customer with.
47
+ * @param EDD_Customer $prev_customer_obj The customer object, prior to these updates.
48
+ */
49
+ function edd_process_customer_updated( $customer_id, $data, $prev_customer_obj ) {
50
+ $customer = edd_get_customer( $customer_id );
51
+ $email_updated = false;
52
+
53
+ // Process a User ID change.
54
+ if ( intval( $customer->user_id ) !== intval( $prev_customer_obj->user_id ) ) {
55
+ // Attach the User Email to the customer as well.
56
+ $user = new WP_User( $customer->user_id );
57
+ if ( $user instanceof WP_User ) {
58
+
59
+ // Only update this if it doesn't match already.
60
+ if ( $customer->email !== $user->user_email ) {
61
+ $customers = new EDD\Database\Queries\Customer();
62
+ $customers->update_item( $customer_id, array( 'email' => $user->user_email ) );
63
+ }
64
+
65
+ // Our transition hook for the type will handle demoting any other email addresses.
66
+ edd_add_customer_email_address(
67
+ array(
68
+ 'customer_id' => $customer->id,
69
+ 'email' => $user->user_email,
70
+ 'type' => 'primary',
71
+ )
72
+ );
73
+
74
+ $email_updated = true;
75
+ }
76
+
77
+ // Remove the old user email from this account.
78
+ $previous_user = new WP_User( $prev_customer_obj->user_id );
79
+ if ( $previous_user instanceof WP_User ) {
80
+ $existing_email_addresses = edd_get_customer_email_addresses(
81
+ array(
82
+ 'customer_id' => $customer->id,
83
+ 'email' => $previous_user->user_email,
84
+ )
85
+ );
86
+
87
+ if ( ! empty( $existing_email_addresses ) ) {
88
+ // Should only be one, but let's foreach to be safe.
89
+ foreach ( $existing_email_addresses as $existing_address ) {
90
+ edd_delete_customer_email_address( $existing_address->id );
91
+ }
92
+ }
93
+ }
94
+
95
+ // Update some payment meta if we need to.
96
+ $order_ids = edd_get_orders( array( 'customer_id' => $customer->id, 'number' => 9999999 ) );
97
+
98
+ foreach ( $order_ids as $order_id ) {
99
+ edd_update_order( $order_id, array( 'user_id' => $customer->user_id ) );
100
+ }
101
+ }
102
+
103
+ // If the email address changed, set the new one as primary.
104
+ if ( false === $email_updated && $prev_customer_obj->email !== $customer->email ) {
105
+
106
+ // Our transition hook for the type will handle demoting any other email addresses.
107
+ edd_add_customer_email_address(
108
+ array(
109
+ 'customer_id' => $customer->id,
110
+ 'email' => $customer->email,
111
+ 'type' => 'primary',
112
+ )
113
+ );
114
+ }
115
+ }
116
+ add_action( 'edd_customer_updated', 'edd_process_customer_updated', 10, 3 );
117
+
118
+ /**
119
+ * When a new primary email address is added to the database, any other primary email addresses should be demoted.
120
+ *
121
+ * @param string $old_value The previous value of `type`.
122
+ * @param string $new_value The new value of `type`.
123
+ * @param int $item_id The address ID in the edd_customer_email_addresses table.
124
+ * @return void
125
+ */
126
+ function edd_demote_customer_primary_email_addresses( $old_value, $new_value, $item_id ) {
127
+ if ( ! $new_value ) {
128
+ return;
129
+ }
130
+
131
+ // If we're not setting the `type` to `primary` we do not need to make any adjustments.
132
+ if ( 'primary' !== $new_value ) {
133
+ return;
134
+ }
135
+
136
+ $email_address = edd_get_customer_email_address( $item_id );
137
+ $previous_primary_email_addresses = edd_get_customer_email_addresses(
138
+ array(
139
+ 'id__not_in' => array( $item_id ),
140
+ 'fields' => 'ids',
141
+ 'customer_id' => $email_address->customer_id,
142
+ 'type' => 'primary',
143
+ )
144
+ );
145
+
146
+ if ( empty( $previous_primary_email_addresses ) ) {
147
+ return;
148
+ }
149
+
150
+ foreach ( $previous_primary_email_addresses as $previous ) {
151
+ edd_update_customer_email_address( $previous, array( 'type' => 'secondary' ) );
152
+ }
153
+ }
154
+ add_action( 'edd_transition_customer_email_address_type', 'edd_demote_customer_primary_email_addresses', 10, 3 );
155
+
156
  /**
157
  * When a new primary address is added to the database, any other primary addresses should be demoted.
158
  *
includes/formatting.php CHANGED
@@ -115,17 +115,28 @@ function edd_sanitize_amount( $amount = 0 ) {
115
  * @param string $decimals Default true. Whether or not to use decimals. Useful when set to false for non-currency numbers.
116
  * @param string $currency Currency code to format the amount for. This determines how many decimals are used.
117
  * If omitted, site-wide currency is used.
 
118
  *
119
  * @return string $amount Newly formatted amount or Price Not Available
120
  */
121
- function edd_format_amount( $amount = 0, $decimals = true, $currency = '' ) {
122
  if ( empty( $currency ) ) {
123
  $currency = edd_get_currency();
124
  }
125
 
126
  $formatter = new \EDD\Currency\Money_Formatter( $amount, new \EDD\Currency\Currency( $currency ) );
127
 
128
- return $formatter->format_for_display( $decimals )->amount;
 
 
 
 
 
 
 
 
 
 
129
  }
130
 
131
  /**
115
  * @param string $decimals Default true. Whether or not to use decimals. Useful when set to false for non-currency numbers.
116
  * @param string $currency Currency code to format the amount for. This determines how many decimals are used.
117
  * If omitted, site-wide currency is used.
118
+ * @param string $context Defines the context in which we are formatting the data (formatted), for display or for data useage like API (typed).
119
  *
120
  * @return string $amount Newly formatted amount or Price Not Available
121
  */
122
+ function edd_format_amount( $amount = 0, $decimals = true, $currency = '', $context = 'display' ) {
123
  if ( empty( $currency ) ) {
124
  $currency = edd_get_currency();
125
  }
126
 
127
  $formatter = new \EDD\Currency\Money_Formatter( $amount, new \EDD\Currency\Currency( $currency ) );
128
 
129
+ switch ( $context ) {
130
+ case 'typed':
131
+ $return_value = $formatter->format_for_typed( $decimals )->typed_amount;
132
+ break;
133
+ case 'display':
134
+ default:
135
+ $return_value = $formatter->format_for_display( $decimals )->amount;
136
+ break;
137
+ }
138
+
139
+ return $return_value;
140
  }
141
 
142
  /**
includes/gateways/stripe/vendor/composer/installed.php CHANGED
@@ -3,7 +3,7 @@
3
  'name' => 'easy-digital-downloads/edd-stripe',
4
  'pretty_version' => 'dev-master',
5
  'version' => 'dev-master',
6
- 'reference' => '9f03119172fb91371f1a53d7e596334f381552a8',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
@@ -22,7 +22,7 @@
22
  'easy-digital-downloads/edd-stripe' => array(
23
  'pretty_version' => 'dev-master',
24
  'version' => 'dev-master',
25
- 'reference' => '9f03119172fb91371f1a53d7e596334f381552a8',
26
  'type' => 'wordpress-plugin',
27
  'install_path' => __DIR__ . '/../../',
28
  'aliases' => array(),
3
  'name' => 'easy-digital-downloads/edd-stripe',
4
  'pretty_version' => 'dev-master',
5
  'version' => 'dev-master',
6
+ 'reference' => '6074197356ec25c976dc8d5b8e328ecbb7362364',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
22
  'easy-digital-downloads/edd-stripe' => array(
23
  'pretty_version' => 'dev-master',
24
  'version' => 'dev-master',
25
+ 'reference' => '6074197356ec25c976dc8d5b8e328ecbb7362364',
26
  'type' => 'wordpress-plugin',
27
  'install_path' => __DIR__ . '/../../',
28
  'aliases' => array(),
includes/orders/classes/class-order.php CHANGED
@@ -274,13 +274,8 @@ class Order extends Rows\Order {
274
  'no_found_rows' => true,
275
  'order' => 'ASC',
276
  ) );
277
- } elseif ( 'items' === $key && null === $this->items ) {
278
- $this->items = edd_get_order_items( array(
279
- 'order_id' => $this->id,
280
- 'orderby' => 'cart_index',
281
- 'order' => 'ASC',
282
- 'no_found_rows' => true,
283
- ) );
284
  }
285
 
286
  return parent::__get( $key );
@@ -349,6 +344,7 @@ class Order extends Rows\Order {
349
  'orderby' => 'cart_index',
350
  'order' => 'ASC',
351
  'no_found_rows' => true,
 
352
  ) );
353
  }
354
 
274
  'no_found_rows' => true,
275
  'order' => 'ASC',
276
  ) );
277
+ } elseif ( 'items' === $key ) {
278
+ $this->get_items();
 
 
 
 
 
279
  }
280
 
281
  return parent::__get( $key );
344
  'orderby' => 'cart_index',
345
  'order' => 'ASC',
346
  'no_found_rows' => true,
347
+ 'number' => 200,
348
  ) );
349
  }
350
 
includes/orders/functions/actions.php CHANGED
@@ -62,7 +62,7 @@ function edd_add_manual_order( $args = array() ) {
62
 
63
  /** Customer data *********************************************************/
64
 
65
- // Defaults
66
  $customer_id = 0;
67
  $user_id = 0;
68
  $email = '';
@@ -71,37 +71,46 @@ function edd_add_manual_order( $args = array() ) {
71
  // Create a new customer record.
72
  if ( isset( $order_data['edd-new-customer'] ) && 1 === absint( $order_data['edd-new-customer'] ) ) {
73
 
74
- // Sanitize first name
75
  $first_name = isset( $order_data['edd-new-customer-first-name'] )
76
  ? sanitize_text_field( $order_data['edd-new-customer-first-name'] )
77
  : '';
78
 
79
- // Sanitize last name
80
  $last_name = isset( $order_data['edd-new-customer-last-name'] )
81
  ? sanitize_text_field( $order_data['edd-new-customer-last-name'] )
82
  : '';
83
 
84
- // Combine
85
  $name = trim( $first_name . ' ' . $last_name );
86
 
87
- // Sanitize the email address
88
  $email = isset( $order_data['edd-new-customer-email'] )
89
  ? sanitize_email( $order_data['edd-new-customer-email'] )
90
  : '';
91
 
92
- // Save to database.
93
- $customer_id = edd_add_customer( array(
94
  'name' => $name,
95
  'email' => $email,
96
- ) );
 
 
 
 
 
 
 
 
 
 
 
97
 
98
  $customer = edd_get_customer( $customer_id );
99
 
100
  // Existing customer.
101
  } elseif ( isset( $order_data['edd-new-customer'] ) && 0 === absint( $order_data['edd-new-customer'] ) && isset( $order_data['customer-id'] ) ) {
102
  $customer_id = absint( $order_data['customer-id'] );
103
-
104
- $customer = edd_get_customer( $customer_id );
105
 
106
  if ( $customer ) {
107
  $email = $customer->email;
62
 
63
  /** Customer data *********************************************************/
64
 
65
+ // Defaults.
66
  $customer_id = 0;
67
  $user_id = 0;
68
  $email = '';
71
  // Create a new customer record.
72
  if ( isset( $order_data['edd-new-customer'] ) && 1 === absint( $order_data['edd-new-customer'] ) ) {
73
 
74
+ // Sanitize first name.
75
  $first_name = isset( $order_data['edd-new-customer-first-name'] )
76
  ? sanitize_text_field( $order_data['edd-new-customer-first-name'] )
77
  : '';
78
 
79
+ // Sanitize last name.
80
  $last_name = isset( $order_data['edd-new-customer-last-name'] )
81
  ? sanitize_text_field( $order_data['edd-new-customer-last-name'] )
82
  : '';
83
 
84
+ // Combine.
85
  $name = trim( $first_name . ' ' . $last_name );
86
 
87
+ // Sanitize the email address.
88
  $email = isset( $order_data['edd-new-customer-email'] )
89
  ? sanitize_email( $order_data['edd-new-customer-email'] )
90
  : '';
91
 
92
+ $new_customer_args = array(
 
93
  'name' => $name,
94
  'email' => $email,
95
+ );
96
+
97
+ // Determine if there is an existing user with this email address.
98
+ $possible_user = get_user_by( 'email', $email );
99
+ if ( $possible_user instanceof WP_User ) {
100
+ $new_customer_args['user_id'] = $possible_user->ID;
101
+ }
102
+
103
+ // Save to database.
104
+ $customer_id = edd_add_customer(
105
+ $new_customer_args
106
+ );
107
 
108
  $customer = edd_get_customer( $customer_id );
109
 
110
  // Existing customer.
111
  } elseif ( isset( $order_data['edd-new-customer'] ) && 0 === absint( $order_data['edd-new-customer'] ) && isset( $order_data['customer-id'] ) ) {
112
  $customer_id = absint( $order_data['customer-id'] );
113
+ $customer = edd_get_customer( $customer_id );
 
114
 
115
  if ( $customer ) {
116
  $email = $customer->email;
includes/payments/actions.php CHANGED
@@ -137,6 +137,7 @@ function edd_complete_purchase( $order_id, $new_status, $old_status ) {
137
 
138
  // Clear the total earnings cache
139
  delete_transient( 'edd_earnings_total' );
 
140
 
141
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
142
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
137
 
138
  // Clear the total earnings cache
139
  delete_transient( 'edd_earnings_total' );
140
+ delete_transient( 'edd_earnings_total_without_tax' );
141
 
142
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
143
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
includes/payments/functions.php CHANGED
@@ -603,39 +603,41 @@ function edd_get_total_sales() {
603
  * Calculate the total earnings of the store.
604
  *
605
  * @since 1.2
606
- * @since 3.0 Refactored to work with new tables.
 
607
  *
608
  * @param bool $include_taxes Whether taxes should be included. Default true.
 
609
  * @return float $total Total earnings.
610
  */
611
- function edd_get_total_earnings( $include_taxes = true ) {
612
  global $wpdb;
613
 
614
- $total = get_option( 'edd_earnings_total', false );
 
 
615
 
616
  // If no total stored in the database, use old method of calculating total earnings.
617
  if ( false === $total ) {
618
- $total = get_transient( 'edd_earnings_total' );
619
-
620
- if ( false === $total ) {
621
- $exclude_taxes_sql = false === $include_taxes
622
- ? ' - SUM(tax)'
623
- : '';
624
 
625
- $total = $wpdb->get_var( "
626
- SELECT SUM(total) {$exclude_taxes_sql} AS total
627
- FROM {$wpdb->edd_orders}
628
- WHERE status IN ('complete', 'revoked')
629
- " );
630
 
631
- $total = (float) edd_number_not_negative( (float) $total );
 
 
 
 
 
 
632
 
633
- // Cache results for 1 day. This cache is cleared automatically when a payment is made
634
- set_transient( 'edd_earnings_total', $total, 86400 );
635
 
636
- // Store the total for the first time
637
- update_option( 'edd_earnings_total', $total );
638
- }
 
 
639
  }
640
 
641
  // Don't ever show negative earnings.
@@ -643,7 +645,9 @@ function edd_get_total_earnings( $include_taxes = true ) {
643
  $total = 0;
644
  }
645
 
646
- return apply_filters( 'edd_total_earnings', round( $total, edd_currency_decimal_filter() ) );
 
 
647
  }
648
 
649
  /**
@@ -655,11 +659,9 @@ function edd_get_total_earnings( $include_taxes = true ) {
655
  * @return float $total Total earnings
656
  */
657
  function edd_increase_total_earnings( $amount = 0 ) {
658
- $total = floatval( edd_get_total_earnings() );
659
  $total += floatval( $amount );
660
 
661
- update_option( 'edd_earnings_total', $total );
662
-
663
  return $total;
664
  }
665
 
@@ -672,15 +674,13 @@ function edd_increase_total_earnings( $amount = 0 ) {
672
  * @return float $total Total earnings.
673
  */
674
  function edd_decrease_total_earnings( $amount = 0 ) {
675
- $total = edd_get_total_earnings();
676
  $total -= $amount;
677
 
678
  if ( $total < 0 ) {
679
  $total = 0;
680
  }
681
 
682
- update_option( 'edd_earnings_total', $total );
683
-
684
  return $total;
685
  }
686
 
603
  * Calculate the total earnings of the store.
604
  *
605
  * @since 1.2
606
+ * @since 3.0 Refactored to work with new tables.
607
+ * @since 3.0.4 Added the $force argument, to force querying again.
608
  *
609
  * @param bool $include_taxes Whether taxes should be included. Default true.
610
+ * @param bool $force If we should force a new calculation.
611
  * @return float $total Total earnings.
612
  */
613
+ function edd_get_total_earnings( $include_taxes = true, $force = true ) {
614
  global $wpdb;
615
 
616
+ $key = $include_taxes ? 'edd_earnings_total' : 'edd_earnings_total_without_tax';
617
+
618
+ $total = $force ? false : get_transient( $key );
619
 
620
  // If no total stored in the database, use old method of calculating total earnings.
621
  if ( false === $total ) {
 
 
 
 
 
 
622
 
623
+ $stats = new EDD\Stats();
 
 
 
 
624
 
625
+ $total = $stats->get_order_earnings(
626
+ array(
627
+ 'output' => 'typed',
628
+ 'exclude_taxes' => ! $include_taxes,
629
+ 'revenue_type' => 'net',
630
+ )
631
+ );
632
 
633
+ // Cache results for 1 day. This cache is cleared automatically when a payment is made.
634
+ set_transient( $key, $total, 86400 );
635
 
636
+ // Store as an option for backwards compatibility.
637
+ update_option( $key, $total, false );
638
+ } else {
639
+ // Always ensure that we're working with a float, since the transient comes back as a string.
640
+ $total = (float) $total;
641
  }
642
 
643
  // Don't ever show negative earnings.
645
  $total = 0;
646
  }
647
 
648
+ $total = edd_format_amount( $total, true, edd_get_currency(), 'typed' );
649
+
650
+ return apply_filters( 'edd_total_earnings', $total );
651
  }
652
 
653
  /**
659
  * @return float $total Total earnings
660
  */
661
  function edd_increase_total_earnings( $amount = 0 ) {
662
+ $total = floatval( edd_get_total_earnings( true, true ) );
663
  $total += floatval( $amount );
664
 
 
 
665
  return $total;
666
  }
667
 
674
  * @return float $total Total earnings.
675
  */
676
  function edd_decrease_total_earnings( $amount = 0 ) {
677
+ $total = edd_get_total_earnings( true, true );
678
  $total -= $amount;
679
 
680
  if ( $total < 0 ) {
681
  $total = 0;
682
  }
683
 
 
 
684
  return $total;
685
  }
686
 
includes/reports/reports-functions.php CHANGED
@@ -795,18 +795,34 @@ function get_dates_filter_day_by_day() {
795
  * Given a function and column, make a timezone converted groupby query.
796
  *
797
  * @since 3.0
 
 
798
  *
799
- * @param string $function The function to run the value through, like DATE, HOUR, MONTH
800
  * @param string $column The column to group by.
801
  *
802
  * @return string
803
  */
804
  function get_groupby_date_string( $function = 'DATE', $column = 'date_created' ) {
 
805
  $date = EDD()->utils->date( 'now', edd_get_timezone_id(), false );
806
  $gmt_offset = $date->getOffset();
807
 
808
  if ( empty( $gmt_offset ) ) {
809
- return "{$function}({$column})";
 
 
 
 
 
 
 
 
 
 
 
 
 
810
  }
811
 
812
  // Output the offset in the proper format.
@@ -816,7 +832,20 @@ function get_groupby_date_string( $function = 'DATE', $column = 'date_created' )
816
 
817
  $formatted_offset = ! empty( $minutes ) ? "{$hours}:{$minutes}" : $hours . ':00';
818
 
819
- return "{$function}(CONVERT_TZ({$column}, '+0:00', '{$math}{$formatted_offset}'))";
 
 
 
 
 
 
 
 
 
 
 
 
 
820
  }
821
 
822
  /**
795
  * Given a function and column, make a timezone converted groupby query.
796
  *
797
  * @since 3.0
798
+ * @since 3.0.4 If MONTH is passed as the function, always add YEAR and MONTH
799
+ * to avoid issues with spanning multiple years.
800
  *
801
+ * @param string $function The function to run the value through, like DATE, HOUR, MONTH.
802
  * @param string $column The column to group by.
803
  *
804
  * @return string
805
  */
806
  function get_groupby_date_string( $function = 'DATE', $column = 'date_created' ) {
807
+ $function = strtoupper( $function );
808
  $date = EDD()->utils->date( 'now', edd_get_timezone_id(), false );
809
  $gmt_offset = $date->getOffset();
810
 
811
  if ( empty( $gmt_offset ) ) {
812
+
813
+ switch ( $function ) {
814
+ case 'HOUR':
815
+ $group_by_string = "DAY({$column}), HOUR({$column})";
816
+ break;
817
+ case 'MONTH':
818
+ $group_by_string = "YEAR({$column}), MONTH({$column})";
819
+ break;
820
+ default:
821
+ $group_by_string = "{$function}({$column})";
822
+ break;
823
+ }
824
+
825
+ return $group_by_string;
826
  }
827
 
828
  // Output the offset in the proper format.
832
 
833
  $formatted_offset = ! empty( $minutes ) ? "{$hours}:{$minutes}" : $hours . ':00';
834
 
835
+ $column_conversion = "CONVERT_TZ({$column}, '+0:00', '{$math}{$formatted_offset}')";
836
+ switch ( $function ) {
837
+ case 'HOUR':
838
+ $group_by_string = "DAY({$column_conversion}), HOUR({$column_conversion})";
839
+ break;
840
+ case 'MONTH':
841
+ $group_by_string = "YEAR({$column_conversion}), MONTH({$column_conversion})";
842
+ break;
843
+ default:
844
+ $group_by_string = "{$function}({$column_conversion})";
845
+ break;
846
+ }
847
+
848
+ return $group_by_string;
849
  }
850
 
851
  /**
includes/user-functions.php CHANGED
@@ -385,37 +385,42 @@ function edd_validate_username( $username ) {
385
  }
386
 
387
  /**
388
- * Attach the customer to an existing user account when completing guest purchase
389
  *
390
  * This only runs when a user account already exists and a guest purchase is made
391
- * with the account's email address
392
  *
393
- * After attaching the customer to the user ID, the account is set to pending
394
  *
395
  * @since 2.8
396
- * @param bool $success True if payment was added successfully, false otherwise
397
- * @param int $payment_id The ID of the EDD_Payment that was added
398
- * @param int $customer_id The ID of the EDD_Customer object
399
- * @param object $customer The EDD_Customer object
400
  * @return void
401
  */
402
  function edd_connect_guest_customer_to_existing_user( $success, $payment_id, $customer_id, $customer ) {
403
 
404
- if( ! empty( $customer->user_id ) ) {
 
 
 
 
 
405
  return;
406
  }
407
 
408
  $user = get_user_by( 'email', $customer->email );
409
 
410
- if( ! $user ) {
411
  return;
412
  }
413
 
414
  $customer->update( array( 'user_id' => $user->ID ) );
415
 
416
- // Set a flag to force the account to be verified before purchase history can be accessed
417
- edd_set_user_to_pending( $user->ID );
418
- edd_send_user_verification_email( $user->ID );
419
 
420
  }
421
  add_action( 'edd_customer_post_attach_payment', 'edd_connect_guest_customer_to_existing_user', 10, 4 );
385
  }
386
 
387
  /**
388
+ * Attach the customer to an existing user account when completing guest purchase.
389
  *
390
  * This only runs when a user account already exists and a guest purchase is made
391
+ * with the account's email address.
392
  *
393
+ * After attaching the customer to the user ID, the account is set to pending.
394
  *
395
  * @since 2.8
396
+ * @param bool $success True if payment was added successfully, false otherwise.
397
+ * @param int $payment_id The ID of the EDD_Payment that was added.
398
+ * @param int $customer_id The ID of the EDD_Customer object.
399
+ * @param object $customer The EDD_Customer object.
400
  * @return void
401
  */
402
  function edd_connect_guest_customer_to_existing_user( $success, $payment_id, $customer_id, $customer ) {
403
 
404
+ // If for some reason we don't get a customer object here, return.
405
+ if ( ! $customer instanceof EDD_Customer ) {
406
+ return;
407
+ }
408
+
409
+ if ( ! empty( $customer->user_id ) ) {
410
  return;
411
  }
412
 
413
  $user = get_user_by( 'email', $customer->email );
414
 
415
+ if ( ! $user instanceof WP_User ) {
416
  return;
417
  }
418
 
419
  $customer->update( array( 'user_id' => $user->ID ) );
420
 
421
+ // Set a flag to force the account to be verified before purchase history can be accessed.
422
+ edd_set_user_to_pending( $user->ID );
423
+ edd_send_user_verification_email( $user->ID );
424
 
425
  }
426
  add_action( 'edd_customer_post_attach_payment', 'edd_connect_guest_customer_to_existing_user', 10, 4 );
languages/easy-digital-downloads.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the Easy Digital Downloads package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Easy Digital Downloads 3.0.3\n"
6
  "Report-Msgid-Bugs-To: https://easydigitaldownloads.com/\n"
7
- "POT-Creation-Date: 2022-08-16 03:37:29+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -95,10 +95,10 @@ msgstr ""
95
  #: includes/admin/import/class-batch-import.php:188
96
  #: includes/admin/payments/actions.php:72
97
  #: includes/admin/payments/actions.php:77
98
- #: includes/admin/payments/actions.php:208
99
- #: includes/admin/payments/actions.php:242
100
- #: includes/admin/payments/actions.php:274
101
- #: includes/admin/payments/actions.php:304
102
  #: includes/admin/payments/add-order.php:63
103
  #: includes/admin/payments/add-order.php:67
104
  #: includes/admin/payments/view-order-details.php:23
@@ -129,10 +129,10 @@ msgstr ""
129
  #: includes/admin/upgrades/upgrade-functions.php:1148
130
  #: includes/admin/upgrades/upgrade-functions.php:1230
131
  #: includes/admin/upgrades/v3/class-base.php:117
132
- #: includes/api/class-edd-api.php:2014 includes/api/class-edd-api.php:2018
133
- #: includes/api/class-edd-api.php:2030 includes/api/class-edd-api.php:2032
134
  #: includes/cart/class-edd-cart.php:1451 includes/cart/class-edd-cart.php:1465
135
- #: includes/class-edd-license-handler.php:385
136
  #: includes/deprecated-functions.php:488 includes/deprecated-functions.php:505
137
  #: includes/deprecated-functions.php:513 includes/deprecated-functions.php:915
138
  #: includes/download-functions.php:1553 includes/emails/actions.php:59
@@ -145,8 +145,8 @@ msgstr ""
145
  #: includes/gateways/stripe/includes/admin/upgrade-functions.php:80
146
  #: includes/gateways/stripe/includes/payment-actions.php:1408
147
  #: includes/process-download.php:280 includes/process-download.php:874
148
- #: includes/query-filters.php:51 includes/user-functions.php:886
149
- #: includes/user-functions.php:911 includes/user-functions.php:963
150
  msgid "Error"
151
  msgstr ""
152
 
@@ -287,8 +287,8 @@ msgstr ""
287
  #: includes/admin/admin-deprecated-functions.php:67
288
  #: includes/admin/payments/actions.php:72
289
  #: includes/admin/payments/actions.php:77
290
- #: includes/admin/payments/actions.php:274
291
- #: includes/admin/payments/actions.php:304 includes/emails/actions.php:59
292
  msgid "You do not have permission to edit this payment record"
293
  msgstr ""
294
 
@@ -940,7 +940,7 @@ msgid "An error has occured. Please try again."
940
  msgstr ""
941
 
942
  #: includes/admin/customers/customer-actions.php:215
943
- #: includes/user-functions.php:911
944
  msgid "Nonce verification failed."
945
  msgstr ""
946
 
@@ -976,8 +976,8 @@ msgstr ""
976
  #: includes/admin/import/import-functions.php:31
977
  #: includes/admin/import/import-functions.php:104
978
  #: includes/admin/reporting/export/export-actions.php:24
979
- #: includes/api/class-edd-api.php:2014
980
- #: includes/class-edd-license-handler.php:385
981
  msgid "Nonce verification failed"
982
  msgstr ""
983
 
@@ -2011,7 +2011,7 @@ msgstr ""
2011
  #: includes/admin/reporting/reports.php:2796
2012
  #: includes/admin/reporting/reports.php:2865
2013
  #: includes/admin/reporting/reports.php:2931
2014
- #: includes/reports/reports-functions.php:1086
2015
  #. translators: the plural post type label
2016
  msgid "All %s"
2017
  msgstr ""
@@ -2610,57 +2610,57 @@ msgid ""
2610
  "assign this payment to them."
2611
  msgstr ""
2612
 
2613
- #: includes/admin/payments/actions.php:208
2614
  msgid "Error updating order."
2615
  msgstr ""
2616
 
2617
- #: includes/admin/payments/actions.php:242
2618
  msgid "You do not have permission to edit this order."
2619
  msgstr ""
2620
 
2621
- #: includes/admin/payments/actions.php:383
2622
- #: includes/admin/payments/actions.php:480
2623
  msgid "You must be logged in to perform this action."
2624
  msgstr ""
2625
 
2626
- #: includes/admin/payments/actions.php:393
2627
- #: includes/admin/payments/actions.php:485
2628
  msgid "Your account does not have permission to perform this action."
2629
  msgstr ""
2630
 
2631
- #: includes/admin/payments/actions.php:404
2632
  msgid "Invalid order ID"
2633
  msgstr ""
2634
 
2635
- #: includes/admin/payments/actions.php:414
2636
  msgid "Invalid order"
2637
  msgstr ""
2638
 
2639
- #: includes/admin/payments/actions.php:423
2640
  msgid "Order is already refunded"
2641
  msgstr ""
2642
 
2643
- #: includes/admin/payments/actions.php:432
2644
  msgid "Cannot refund an order that is already refunded."
2645
  msgstr ""
2646
 
2647
- #: includes/admin/payments/actions.php:443
2648
  msgid "View Refund"
2649
  msgstr ""
2650
 
2651
- #: includes/admin/payments/actions.php:489
2652
  msgid "Missing form data or order ID."
2653
  msgstr ""
2654
 
2655
- #: includes/admin/payments/actions.php:498
2656
  msgid "Nonce validation failed when submitting refund."
2657
  msgstr ""
2658
 
2659
- #: includes/admin/payments/actions.php:545
2660
  msgid "Refund successfully processed."
2661
  msgstr ""
2662
 
2663
- #: includes/admin/payments/actions.php:556
2664
  msgid "Unable to process refund."
2665
  msgstr ""
2666
 
@@ -2737,7 +2737,7 @@ msgstr ""
2737
  #: includes/admin/payments/class-payments-table.php:296
2738
  #: includes/admin/reporting/class-base-logs-list-table.php:506
2739
  #: includes/admin/tools/logs.php:258
2740
- #: includes/reports/reports-functions.php:1400
2741
  msgid "Filter"
2742
  msgstr ""
2743
 
@@ -4408,8 +4408,8 @@ msgstr ""
4408
  msgid "Export File Download Log Dates"
4409
  msgstr ""
4410
 
4411
- #: includes/admin/reporting/reports.php:3042 includes/user-functions.php:915
4412
- #: includes/user-functions.php:919
4413
  msgid "Notice"
4414
  msgstr ""
4415
 
@@ -6042,7 +6042,7 @@ msgstr ""
6042
  msgid "Store earnings successfully recounted."
6043
  msgstr ""
6044
 
6045
- #: includes/admin/tools/class-edd-tools-reset-stats.php:142
6046
  msgid "Your store has been successfully reset."
6047
  msgstr ""
6048
 
@@ -7111,93 +7111,89 @@ msgstr ""
7111
  msgid "Unable to find download. Please refresh the page and try again."
7112
  msgstr ""
7113
 
7114
- #: includes/api/class-edd-api-v2.php:166 includes/api/class-edd-api.php:1128
7115
- #: includes/api/class-edd-api.php:1315 includes/api/class-edd-api.php:1432
7116
  msgid "Product %s not found!"
7117
  msgstr ""
7118
 
7119
- #: includes/api/class-edd-api-v2.php:240 includes/api/class-edd-api.php:1237
7120
- #: includes/api/class-edd-api.php:1333
7121
  msgid "The end date must be later than the start date!"
7122
  msgstr ""
7123
 
7124
- #: includes/api/class-edd-api-v2.php:341 includes/api/class-edd-api.php:1070
7125
  msgid "Customer %s not found!"
7126
  msgstr ""
7127
 
7128
- #: includes/api/class-edd-api-v2.php:346 includes/api/class-edd-api.php:1076
7129
  msgid "No customers found!"
7130
  msgstr ""
7131
 
7132
- #: includes/api/class-edd-api.php:458
7133
  msgid "You must specify both a token and API key!"
7134
  msgstr ""
7135
 
7136
- #: includes/api/class-edd-api.php:475
7137
  msgid "Your request could not be authenticated!"
7138
  msgstr ""
7139
 
7140
- #: includes/api/class-edd-api.php:493
7141
  msgid "Invalid API key!"
7142
  msgstr ""
7143
 
7144
- #: includes/api/class-edd-api.php:509
7145
  msgid "Invalid API version!"
7146
  msgstr ""
7147
 
7148
- #: includes/api/class-edd-api.php:685
7149
  msgid "Invalid query!"
7150
  msgstr ""
7151
 
7152
- #: includes/api/class-edd-api.php:1242 includes/api/class-edd-api.php:1338
7153
  msgid "Invalid or no date range specified!"
7154
  msgstr ""
7155
 
7156
- #: includes/api/class-edd-api.php:1282 includes/api/class-edd-api.php:1401
7157
- msgid "There was an error retrieving earnings."
7158
- msgstr ""
7159
-
7160
- #: includes/api/class-edd-api.php:1597
7161
  msgid "No discounts found!"
7162
  msgstr ""
7163
 
7164
- #: includes/api/class-edd-api.php:1643
7165
  msgid "Discount %s not found!"
7166
  msgstr ""
7167
 
7168
- #: includes/api/class-edd-api.php:1714
7169
  msgid "No download logs found!"
7170
  msgstr ""
7171
 
7172
- #: includes/api/class-edd-api.php:1970 includes/user-functions.php:1081
7173
  msgid "Downloads API Keys"
7174
  msgstr ""
7175
 
7176
- #: includes/api/class-edd-api.php:1980 includes/user-functions.php:1088
7177
  msgid "Generate API Key"
7178
  msgstr ""
7179
 
7180
- #: includes/api/class-edd-api.php:1984
7181
  msgid "Public key:"
7182
  msgstr ""
7183
 
7184
- #: includes/api/class-edd-api.php:1987
7185
  msgid "Secret key:"
7186
  msgstr ""
7187
 
7188
- #: includes/api/class-edd-api.php:1990 includes/user-functions.php:1099
7189
  msgid "Token:"
7190
  msgstr ""
7191
 
7192
- #: includes/api/class-edd-api.php:1994 includes/user-functions.php:1105
7193
  msgid "Revoke API Keys"
7194
  msgstr ""
7195
 
7196
- #: includes/api/class-edd-api.php:2018
7197
  msgid "User ID Required"
7198
  msgstr ""
7199
 
7200
- #: includes/api/class-edd-api.php:2030 includes/api/class-edd-api.php:2032
7201
  msgid "You do not have permission to %s API keys for this user"
7202
  msgstr ""
7203
 
@@ -7542,7 +7538,7 @@ msgstr ""
7542
  msgid "Cheatin&#8217; huh?"
7543
  msgstr ""
7544
 
7545
- #: includes/class-edd-cache-helper.php:125
7546
  msgid ""
7547
  "In order for <strong>database caching</strong> to work with Easy Digital "
7548
  "Downloads you must add <code>_wp_session_</code> to the \"Ignored query "
@@ -7698,8 +7694,8 @@ msgstr ""
7698
  msgid "Customer User ID: %s"
7699
  msgstr ""
7700
 
7701
- #: includes/class-edd-cli.php:314 includes/user-functions.php:568
7702
- #: includes/user-functions.php:580
7703
  msgid "Username: %s"
7704
  msgstr ""
7705
 
@@ -8162,24 +8158,24 @@ msgstr ""
8162
  msgid "Enter Username"
8163
  msgstr ""
8164
 
8165
- #: includes/class-edd-license-handler.php:199
8166
  msgid "%1$s"
8167
  msgstr ""
8168
 
8169
- #: includes/class-edd-license-handler.php:227
8170
  msgid ""
8171
  "Enter your extension license keys here to receive updates for purchased "
8172
  "extensions. If your license key has expired, please <a href=\"%s\" "
8173
  "target=\"_blank\">renew your license</a>."
8174
  msgstr ""
8175
 
8176
- #: includes/class-edd-license-handler.php:502
8177
  msgid ""
8178
  "You have invalid or expired license keys for Easy Digital Downloads. <a "
8179
  "href=\"%s\">Fix this</a>"
8180
  msgstr ""
8181
 
8182
- #: includes/class-edd-license-handler.php:531
8183
  msgid "Enter valid license key for automatic updates."
8184
  msgstr ""
8185
 
@@ -8353,11 +8349,11 @@ msgstr ""
8353
  msgid "Saturday"
8354
  msgstr ""
8355
 
8356
- #: includes/class-stats.php:3091
8357
  msgid "No data to compare"
8358
  msgstr ""
8359
 
8360
- #: includes/class-stats.php:3094
8361
  msgid "No Change"
8362
  msgstr ""
8363
 
@@ -8392,20 +8388,20 @@ msgid ""
8392
  "%4$s. See %5$s for more information."
8393
  msgstr ""
8394
 
8395
- #: includes/compat/class-template.php:97
8396
  msgid ""
8397
  "Easy Digital Downloads failed to automatically update your purchase receipt "
8398
  "template. This update is necessary for the purchase receipt to display "
8399
  "correctly."
8400
  msgstr ""
8401
 
8402
- #: includes/compat/class-template.php:98
8403
  msgid ""
8404
  "This update must be completed manually. Please click %shere%s for more "
8405
  "information."
8406
  msgstr ""
8407
 
8408
- #: includes/compat/class-template.php:99
8409
  msgid "The file that needs to be updated is located at:"
8410
  msgstr ""
8411
 
@@ -8789,7 +8785,7 @@ msgstr ""
8789
  msgid "Angolan Kwanza"
8790
  msgstr ""
8791
 
8792
- #: includes/customer-functions.php:267
8793
  #: includes/payments/class-payments-query.php:626
8794
  msgid "Do not use -1 to retrieve all results."
8795
  msgstr ""
@@ -9205,7 +9201,7 @@ msgstr ""
9205
  msgid "Receipt"
9206
  msgstr ""
9207
 
9208
- #: includes/formatting.php:318
9209
  msgid "Billing"
9210
  msgstr ""
9211
 
@@ -11304,27 +11300,27 @@ msgstr ""
11304
  msgid "Invoice"
11305
  msgstr ""
11306
 
11307
- #: includes/payments/actions.php:250
11308
  msgid "After payment actions processed."
11309
  msgstr ""
11310
 
11311
- #: includes/payments/actions.php:492 includes/payments/actions.php:553
11312
  msgid "Error resuming payment."
11313
  msgstr ""
11314
 
11315
- #: includes/payments/actions.php:496
11316
  msgid "Payment recovery triggered URL"
11317
  msgstr ""
11318
 
11319
- #: includes/payments/actions.php:574 includes/payments/actions.php:608
11320
  msgid "To complete this payment, please login to your account."
11321
  msgstr ""
11322
 
11323
- #: includes/payments/actions.php:576
11324
  msgid "Lost Password"
11325
  msgstr ""
11326
 
11327
- #: includes/payments/actions.php:577 templates/shortcode-login.php:33
11328
  msgid "Lost Password?"
11329
  msgstr ""
11330
 
@@ -12059,7 +12055,7 @@ msgid "Global Rate"
12059
  msgstr ""
12060
 
12061
  #: includes/reports/reports-functions.php:328
12062
- #: includes/reports/reports-functions.php:1123
12063
  msgid "Exclude Taxes"
12064
  msgstr ""
12065
 
@@ -12089,15 +12085,15 @@ msgstr ""
12089
  msgid "Last 30 Days"
12090
  msgstr ""
12091
 
12092
- #: includes/reports/reports-functions.php:1015
12093
  msgid "Chart time zone: %s"
12094
  msgstr ""
12095
 
12096
- #: includes/reports/reports-functions.php:1292
12097
  msgid "%s - Converted"
12098
  msgstr ""
12099
 
12100
- #: includes/reports/reports-functions.php:1422
12101
  msgid "Try the Sales/Earnings iOS App!"
12102
  msgstr ""
12103
 
@@ -12363,51 +12359,51 @@ msgstr ""
12363
  msgid "Plain Text"
12364
  msgstr ""
12365
 
12366
- #: includes/user-functions.php:566
12367
  msgid "[%s] New User Registration"
12368
  msgstr ""
12369
 
12370
- #: includes/user-functions.php:567
12371
  msgid "New user registration"
12372
  msgstr ""
12373
 
12374
- #: includes/user-functions.php:569
12375
  msgid "E-mail: %s"
12376
  msgstr ""
12377
 
12378
- #: includes/user-functions.php:578
12379
  msgid "[%s] Your username and password"
12380
  msgstr ""
12381
 
12382
- #: includes/user-functions.php:579
12383
  msgid "Your account info"
12384
  msgstr ""
12385
 
12386
- #: includes/user-functions.php:583
12387
  msgid "Password entered at checkout"
12388
  msgstr ""
12389
 
12390
- #: includes/user-functions.php:585
12391
  msgid "Password entered at registration"
12392
  msgstr ""
12393
 
12394
- #: includes/user-functions.php:588
12395
  msgid "Password: %s"
12396
  msgstr ""
12397
 
12398
- #: includes/user-functions.php:593
12399
  msgid "Click here to log in"
12400
  msgstr ""
12401
 
12402
- #: includes/user-functions.php:597
12403
  msgid "To log in, visit: %s"
12404
  msgstr ""
12405
 
12406
- #: includes/user-functions.php:751 includes/user-functions.php:752
12407
  msgid "Verify your account"
12408
  msgstr ""
12409
 
12410
- #: includes/user-functions.php:754
12411
  msgid ""
12412
  "Hello %1$s,\n"
12413
  "\n"
@@ -12417,37 +12413,37 @@ msgid ""
12417
  "\t\tLink missing? Visit the following URL: %3$s"
12418
  msgstr ""
12419
 
12420
- #: includes/user-functions.php:882
12421
  msgid ""
12422
  "Sorry but your account verification link has expired. <a href=\"%s\">Click "
12423
  "here</a> to request a new verification URL."
12424
  msgstr ""
12425
 
12426
- #: includes/user-functions.php:915
12427
  msgid "You must be logged in to verify your account."
12428
  msgstr ""
12429
 
12430
- #: includes/user-functions.php:919
12431
  msgid "Your account has already been verified."
12432
  msgstr ""
12433
 
12434
- #: includes/user-functions.php:963
12435
  msgid "Invalid verification token provided."
12436
  msgstr ""
12437
 
12438
- #: includes/user-functions.php:1093
12439
  msgid "Public Key:"
12440
  msgstr ""
12441
 
12442
- #: includes/user-functions.php:1096
12443
  msgid "Secret Key:"
12444
  msgstr ""
12445
 
12446
- #: includes/user-functions.php:1120
12447
  msgid "Easy Digital Downloads <a href=\"%s\">iOS App</a>"
12448
  msgstr ""
12449
 
12450
- #: includes/user-functions.php:1127
12451
  msgid "Add to iOS App"
12452
  msgstr ""
12453
 
@@ -12765,7 +12761,7 @@ msgstr ""
12765
  #: includes/admin/reporting/reports.php:2823
12766
  #: includes/admin/reporting/reports.php:2892
12767
  #: includes/admin/reporting/reports.php:2946
12768
- #: includes/reports/reports-functions.php:1052
12769
  msgctxt "date filter"
12770
  msgid "From"
12771
  msgstr ""
@@ -12778,7 +12774,7 @@ msgstr ""
12778
  #: includes/admin/reporting/reports.php:2834
12779
  #: includes/admin/reporting/reports.php:2903
12780
  #: includes/admin/reporting/reports.php:2957
12781
- #: includes/reports/reports-functions.php:1060
12782
  msgctxt "date filter"
12783
  msgid "To"
12784
  msgstr ""
2
  # This file is distributed under the same license as the Easy Digital Downloads package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Easy Digital Downloads 3.0.4\n"
6
  "Report-Msgid-Bugs-To: https://easydigitaldownloads.com/\n"
7
+ "POT-Creation-Date: 2022-09-06 18:22:09+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
95
  #: includes/admin/import/class-batch-import.php:188
96
  #: includes/admin/payments/actions.php:72
97
  #: includes/admin/payments/actions.php:77
98
+ #: includes/admin/payments/actions.php:222
99
+ #: includes/admin/payments/actions.php:256
100
+ #: includes/admin/payments/actions.php:288
101
+ #: includes/admin/payments/actions.php:318
102
  #: includes/admin/payments/add-order.php:63
103
  #: includes/admin/payments/add-order.php:67
104
  #: includes/admin/payments/view-order-details.php:23
129
  #: includes/admin/upgrades/upgrade-functions.php:1148
130
  #: includes/admin/upgrades/upgrade-functions.php:1230
131
  #: includes/admin/upgrades/v3/class-base.php:117
132
+ #: includes/api/class-edd-api.php:2036 includes/api/class-edd-api.php:2040
133
+ #: includes/api/class-edd-api.php:2052 includes/api/class-edd-api.php:2054
134
  #: includes/cart/class-edd-cart.php:1451 includes/cart/class-edd-cart.php:1465
135
+ #: includes/class-edd-license-handler.php:388
136
  #: includes/deprecated-functions.php:488 includes/deprecated-functions.php:505
137
  #: includes/deprecated-functions.php:513 includes/deprecated-functions.php:915
138
  #: includes/download-functions.php:1553 includes/emails/actions.php:59
145
  #: includes/gateways/stripe/includes/admin/upgrade-functions.php:80
146
  #: includes/gateways/stripe/includes/payment-actions.php:1408
147
  #: includes/process-download.php:280 includes/process-download.php:874
148
+ #: includes/query-filters.php:51 includes/user-functions.php:891
149
+ #: includes/user-functions.php:916 includes/user-functions.php:968
150
  msgid "Error"
151
  msgstr ""
152
 
287
  #: includes/admin/admin-deprecated-functions.php:67
288
  #: includes/admin/payments/actions.php:72
289
  #: includes/admin/payments/actions.php:77
290
+ #: includes/admin/payments/actions.php:288
291
+ #: includes/admin/payments/actions.php:318 includes/emails/actions.php:59
292
  msgid "You do not have permission to edit this payment record"
293
  msgstr ""
294
 
940
  msgstr ""
941
 
942
  #: includes/admin/customers/customer-actions.php:215
943
+ #: includes/user-functions.php:916
944
  msgid "Nonce verification failed."
945
  msgstr ""
946
 
976
  #: includes/admin/import/import-functions.php:31
977
  #: includes/admin/import/import-functions.php:104
978
  #: includes/admin/reporting/export/export-actions.php:24
979
+ #: includes/api/class-edd-api.php:2036
980
+ #: includes/class-edd-license-handler.php:388
981
  msgid "Nonce verification failed"
982
  msgstr ""
983
 
2011
  #: includes/admin/reporting/reports.php:2796
2012
  #: includes/admin/reporting/reports.php:2865
2013
  #: includes/admin/reporting/reports.php:2931
2014
+ #: includes/reports/reports-functions.php:1115
2015
  #. translators: the plural post type label
2016
  msgid "All %s"
2017
  msgstr ""
2610
  "assign this payment to them."
2611
  msgstr ""
2612
 
2613
+ #: includes/admin/payments/actions.php:222
2614
  msgid "Error updating order."
2615
  msgstr ""
2616
 
2617
+ #: includes/admin/payments/actions.php:256
2618
  msgid "You do not have permission to edit this order."
2619
  msgstr ""
2620
 
2621
+ #: includes/admin/payments/actions.php:397
2622
+ #: includes/admin/payments/actions.php:494
2623
  msgid "You must be logged in to perform this action."
2624
  msgstr ""
2625
 
2626
+ #: includes/admin/payments/actions.php:407
2627
+ #: includes/admin/payments/actions.php:499
2628
  msgid "Your account does not have permission to perform this action."
2629
  msgstr ""
2630
 
2631
+ #: includes/admin/payments/actions.php:418
2632
  msgid "Invalid order ID"
2633
  msgstr ""
2634
 
2635
+ #: includes/admin/payments/actions.php:428
2636
  msgid "Invalid order"
2637
  msgstr ""
2638
 
2639
+ #: includes/admin/payments/actions.php:437
2640
  msgid "Order is already refunded"
2641
  msgstr ""
2642
 
2643
+ #: includes/admin/payments/actions.php:446
2644
  msgid "Cannot refund an order that is already refunded."
2645
  msgstr ""
2646
 
2647
+ #: includes/admin/payments/actions.php:457
2648
  msgid "View Refund"
2649
  msgstr ""
2650
 
2651
+ #: includes/admin/payments/actions.php:503
2652
  msgid "Missing form data or order ID."
2653
  msgstr ""
2654
 
2655
+ #: includes/admin/payments/actions.php:512
2656
  msgid "Nonce validation failed when submitting refund."
2657
  msgstr ""
2658
 
2659
+ #: includes/admin/payments/actions.php:559
2660
  msgid "Refund successfully processed."
2661
  msgstr ""
2662
 
2663
+ #: includes/admin/payments/actions.php:570
2664
  msgid "Unable to process refund."
2665
  msgstr ""
2666
 
2737
  #: includes/admin/payments/class-payments-table.php:296
2738
  #: includes/admin/reporting/class-base-logs-list-table.php:506
2739
  #: includes/admin/tools/logs.php:258
2740
+ #: includes/reports/reports-functions.php:1429
2741
  msgid "Filter"
2742
  msgstr ""
2743
 
4408
  msgid "Export File Download Log Dates"
4409
  msgstr ""
4410
 
4411
+ #: includes/admin/reporting/reports.php:3042 includes/user-functions.php:920
4412
+ #: includes/user-functions.php:924
4413
  msgid "Notice"
4414
  msgstr ""
4415
 
6042
  msgid "Store earnings successfully recounted."
6043
  msgstr ""
6044
 
6045
+ #: includes/admin/tools/class-edd-tools-reset-stats.php:144
6046
  msgid "Your store has been successfully reset."
6047
  msgstr ""
6048
 
7111
  msgid "Unable to find download. Please refresh the page and try again."
7112
  msgstr ""
7113
 
7114
+ #: includes/api/class-edd-api-v2.php:166 includes/api/class-edd-api.php:1131
7115
+ #: includes/api/class-edd-api.php:1340 includes/api/class-edd-api.php:1463
7116
  msgid "Product %s not found!"
7117
  msgstr ""
7118
 
7119
+ #: includes/api/class-edd-api-v2.php:240 includes/api/class-edd-api.php:1240
7120
+ #: includes/api/class-edd-api.php:1358
7121
  msgid "The end date must be later than the start date!"
7122
  msgstr ""
7123
 
7124
+ #: includes/api/class-edd-api-v2.php:341 includes/api/class-edd-api.php:1073
7125
  msgid "Customer %s not found!"
7126
  msgstr ""
7127
 
7128
+ #: includes/api/class-edd-api-v2.php:346 includes/api/class-edd-api.php:1079
7129
  msgid "No customers found!"
7130
  msgstr ""
7131
 
7132
+ #: includes/api/class-edd-api.php:461
7133
  msgid "You must specify both a token and API key!"
7134
  msgstr ""
7135
 
7136
+ #: includes/api/class-edd-api.php:478
7137
  msgid "Your request could not be authenticated!"
7138
  msgstr ""
7139
 
7140
+ #: includes/api/class-edd-api.php:496
7141
  msgid "Invalid API key!"
7142
  msgstr ""
7143
 
7144
+ #: includes/api/class-edd-api.php:512
7145
  msgid "Invalid API version!"
7146
  msgstr ""
7147
 
7148
+ #: includes/api/class-edd-api.php:688
7149
  msgid "Invalid query!"
7150
  msgstr ""
7151
 
7152
+ #: includes/api/class-edd-api.php:1245 includes/api/class-edd-api.php:1363
7153
  msgid "Invalid or no date range specified!"
7154
  msgstr ""
7155
 
7156
+ #: includes/api/class-edd-api.php:1619
 
 
 
 
7157
  msgid "No discounts found!"
7158
  msgstr ""
7159
 
7160
+ #: includes/api/class-edd-api.php:1665
7161
  msgid "Discount %s not found!"
7162
  msgstr ""
7163
 
7164
+ #: includes/api/class-edd-api.php:1736
7165
  msgid "No download logs found!"
7166
  msgstr ""
7167
 
7168
+ #: includes/api/class-edd-api.php:1992 includes/user-functions.php:1086
7169
  msgid "Downloads API Keys"
7170
  msgstr ""
7171
 
7172
+ #: includes/api/class-edd-api.php:2002 includes/user-functions.php:1093
7173
  msgid "Generate API Key"
7174
  msgstr ""
7175
 
7176
+ #: includes/api/class-edd-api.php:2006
7177
  msgid "Public key:"
7178
  msgstr ""
7179
 
7180
+ #: includes/api/class-edd-api.php:2009
7181
  msgid "Secret key:"
7182
  msgstr ""
7183
 
7184
+ #: includes/api/class-edd-api.php:2012 includes/user-functions.php:1104
7185
  msgid "Token:"
7186
  msgstr ""
7187
 
7188
+ #: includes/api/class-edd-api.php:2016 includes/user-functions.php:1110
7189
  msgid "Revoke API Keys"
7190
  msgstr ""
7191
 
7192
+ #: includes/api/class-edd-api.php:2040
7193
  msgid "User ID Required"
7194
  msgstr ""
7195
 
7196
+ #: includes/api/class-edd-api.php:2052 includes/api/class-edd-api.php:2054
7197
  msgid "You do not have permission to %s API keys for this user"
7198
  msgstr ""
7199
 
7538
  msgid "Cheatin&#8217; huh?"
7539
  msgstr ""
7540
 
7541
+ #: includes/class-edd-cache-helper.php:113
7542
  msgid ""
7543
  "In order for <strong>database caching</strong> to work with Easy Digital "
7544
  "Downloads you must add <code>_wp_session_</code> to the \"Ignored query "
7694
  msgid "Customer User ID: %s"
7695
  msgstr ""
7696
 
7697
+ #: includes/class-edd-cli.php:314 includes/user-functions.php:573
7698
+ #: includes/user-functions.php:585
7699
  msgid "Username: %s"
7700
  msgstr ""
7701
 
8158
  msgid "Enter Username"
8159
  msgstr ""
8160
 
8161
+ #: includes/class-edd-license-handler.php:202
8162
  msgid "%1$s"
8163
  msgstr ""
8164
 
8165
+ #: includes/class-edd-license-handler.php:230
8166
  msgid ""
8167
  "Enter your extension license keys here to receive updates for purchased "
8168
  "extensions. If your license key has expired, please <a href=\"%s\" "
8169
  "target=\"_blank\">renew your license</a>."
8170
  msgstr ""
8171
 
8172
+ #: includes/class-edd-license-handler.php:505
8173
  msgid ""
8174
  "You have invalid or expired license keys for Easy Digital Downloads. <a "
8175
  "href=\"%s\">Fix this</a>"
8176
  msgstr ""
8177
 
8178
+ #: includes/class-edd-license-handler.php:534
8179
  msgid "Enter valid license key for automatic updates."
8180
  msgstr ""
8181
 
8349
  msgid "Saturday"
8350
  msgstr ""
8351
 
8352
+ #: includes/class-stats.php:3103
8353
  msgid "No data to compare"
8354
  msgstr ""
8355
 
8356
+ #: includes/class-stats.php:3106
8357
  msgid "No Change"
8358
  msgstr ""
8359
 
8388
  "%4$s. See %5$s for more information."
8389
  msgstr ""
8390
 
8391
+ #: includes/compat/class-template.php:109
8392
  msgid ""
8393
  "Easy Digital Downloads failed to automatically update your purchase receipt "
8394
  "template. This update is necessary for the purchase receipt to display "
8395
  "correctly."
8396
  msgstr ""
8397
 
8398
+ #: includes/compat/class-template.php:110
8399
  msgid ""
8400
  "This update must be completed manually. Please click %shere%s for more "
8401
  "information."
8402
  msgstr ""
8403
 
8404
+ #: includes/compat/class-template.php:111
8405
  msgid "The file that needs to be updated is located at:"
8406
  msgstr ""
8407
 
8785
  msgid "Angolan Kwanza"
8786
  msgstr ""
8787
 
8788
+ #: includes/customer-functions.php:334
8789
  #: includes/payments/class-payments-query.php:626
8790
  msgid "Do not use -1 to retrieve all results."
8791
  msgstr ""
9201
  msgid "Receipt"
9202
  msgstr ""
9203
 
9204
+ #: includes/formatting.php:329
9205
  msgid "Billing"
9206
  msgstr ""
9207
 
11300
  msgid "Invoice"
11301
  msgstr ""
11302
 
11303
+ #: includes/payments/actions.php:251
11304
  msgid "After payment actions processed."
11305
  msgstr ""
11306
 
11307
+ #: includes/payments/actions.php:493 includes/payments/actions.php:554
11308
  msgid "Error resuming payment."
11309
  msgstr ""
11310
 
11311
+ #: includes/payments/actions.php:497
11312
  msgid "Payment recovery triggered URL"
11313
  msgstr ""
11314
 
11315
+ #: includes/payments/actions.php:575 includes/payments/actions.php:609
11316
  msgid "To complete this payment, please login to your account."
11317
  msgstr ""
11318
 
11319
+ #: includes/payments/actions.php:577
11320
  msgid "Lost Password"
11321
  msgstr ""
11322
 
11323
+ #: includes/payments/actions.php:578 templates/shortcode-login.php:33
11324
  msgid "Lost Password?"
11325
  msgstr ""
11326
 
12055
  msgstr ""
12056
 
12057
  #: includes/reports/reports-functions.php:328
12058
+ #: includes/reports/reports-functions.php:1152
12059
  msgid "Exclude Taxes"
12060
  msgstr ""
12061
 
12085
  msgid "Last 30 Days"
12086
  msgstr ""
12087
 
12088
+ #: includes/reports/reports-functions.php:1044
12089
  msgid "Chart time zone: %s"
12090
  msgstr ""
12091
 
12092
+ #: includes/reports/reports-functions.php:1321
12093
  msgid "%s - Converted"
12094
  msgstr ""
12095
 
12096
+ #: includes/reports/reports-functions.php:1451
12097
  msgid "Try the Sales/Earnings iOS App!"
12098
  msgstr ""
12099
 
12359
  msgid "Plain Text"
12360
  msgstr ""
12361
 
12362
+ #: includes/user-functions.php:571
12363
  msgid "[%s] New User Registration"
12364
  msgstr ""
12365
 
12366
+ #: includes/user-functions.php:572
12367
  msgid "New user registration"
12368
  msgstr ""
12369
 
12370
+ #: includes/user-functions.php:574
12371
  msgid "E-mail: %s"
12372
  msgstr ""
12373
 
12374
+ #: includes/user-functions.php:583
12375
  msgid "[%s] Your username and password"
12376
  msgstr ""
12377
 
12378
+ #: includes/user-functions.php:584
12379
  msgid "Your account info"
12380
  msgstr ""
12381
 
12382
+ #: includes/user-functions.php:588
12383
  msgid "Password entered at checkout"
12384
  msgstr ""
12385
 
12386
+ #: includes/user-functions.php:590
12387
  msgid "Password entered at registration"
12388
  msgstr ""
12389
 
12390
+ #: includes/user-functions.php:593
12391
  msgid "Password: %s"
12392
  msgstr ""
12393
 
12394
+ #: includes/user-functions.php:598
12395
  msgid "Click here to log in"
12396
  msgstr ""
12397
 
12398
+ #: includes/user-functions.php:602
12399
  msgid "To log in, visit: %s"
12400
  msgstr ""
12401
 
12402
+ #: includes/user-functions.php:756 includes/user-functions.php:757
12403
  msgid "Verify your account"
12404
  msgstr ""
12405
 
12406
+ #: includes/user-functions.php:759
12407
  msgid ""
12408
  "Hello %1$s,\n"
12409
  "\n"
12413
  "\t\tLink missing? Visit the following URL: %3$s"
12414
  msgstr ""
12415
 
12416
+ #: includes/user-functions.php:887
12417
  msgid ""
12418
  "Sorry but your account verification link has expired. <a href=\"%s\">Click "
12419
  "here</a> to request a new verification URL."
12420
  msgstr ""
12421
 
12422
+ #: includes/user-functions.php:920
12423
  msgid "You must be logged in to verify your account."
12424
  msgstr ""
12425
 
12426
+ #: includes/user-functions.php:924
12427
  msgid "Your account has already been verified."
12428
  msgstr ""
12429
 
12430
+ #: includes/user-functions.php:968
12431
  msgid "Invalid verification token provided."
12432
  msgstr ""
12433
 
12434
+ #: includes/user-functions.php:1098
12435
  msgid "Public Key:"
12436
  msgstr ""
12437
 
12438
+ #: includes/user-functions.php:1101
12439
  msgid "Secret Key:"
12440
  msgstr ""
12441
 
12442
+ #: includes/user-functions.php:1125
12443
  msgid "Easy Digital Downloads <a href=\"%s\">iOS App</a>"
12444
  msgstr ""
12445
 
12446
+ #: includes/user-functions.php:1132
12447
  msgid "Add to iOS App"
12448
  msgstr ""
12449
 
12761
  #: includes/admin/reporting/reports.php:2823
12762
  #: includes/admin/reporting/reports.php:2892
12763
  #: includes/admin/reporting/reports.php:2946
12764
+ #: includes/reports/reports-functions.php:1081
12765
  msgctxt "date filter"
12766
  msgid "From"
12767
  msgstr ""
12774
  #: includes/admin/reporting/reports.php:2834
12775
  #: includes/admin/reporting/reports.php:2903
12776
  #: includes/admin/reporting/reports.php:2957
12777
+ #: includes/reports/reports-functions.php:1089
12778
  msgctxt "date filter"
12779
  msgid "To"
12780
  msgstr ""
readme.txt CHANGED
@@ -1,13 +1,12 @@
1
  === Easy Digital Downloads - Simple eCommerce for Selling Digital Files ===
2
  Author URI: https://easydigitaldownloads.com
3
  Plugin URI: https://easydigitaldownloads.com
4
- Contributors: easydigitaldownloads, mordauk, sunnyratilal, chriscct7, section214, sumobi, sdavis2702, cklosows, mindctrl, sksmatt, SpencerFinnell, johnstonphilip, brashrebel, drewapicture, johnjamesjacoby, nosegraze, littlerchicken, lisacee, zkawesome
5
- Donate link: https://easydigitaldownloads.com/donate/
6
  Tags: ecommerce, e-commerce, sell, digital store, stripe
7
  Requires at least: 4.9
8
  Tested up to: 6.0
9
  Requires PHP: 5.6
10
- Stable Tag: 3.0.3
11
  License: GNU Version 2 or Any Later Version
12
 
13
  Sell your digital products with the ecommerce plugin written for digital creators, by digital creators.
@@ -239,6 +238,21 @@ Yes, through the use of our commercial addon called [Recurring Payments](https:/
239
 
240
  == Changelog ==
241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  = 3.0.3, August 16, 2022 =
243
  * New: Added support for Global Tax rates as a fallback with the new Tax Rates UI.
244
  * Fix: The old 'fallback tax rate' was not imported as a new tax rate.
1
  === Easy Digital Downloads - Simple eCommerce for Selling Digital Files ===
2
  Author URI: https://easydigitaldownloads.com
3
  Plugin URI: https://easydigitaldownloads.com
4
+ Contributors: easydigitaldownloads, smub, am, mordauk, sunnyratilal, chriscct7, section214, sumobi, sdavis2702, cklosows, mindctrl, sksmatt, SpencerFinnell, johnstonphilip, brashrebel, drewapicture, johnjamesjacoby, nosegraze, littlerchicken, lisacee, zkawesome
 
5
  Tags: ecommerce, e-commerce, sell, digital store, stripe
6
  Requires at least: 4.9
7
  Tested up to: 6.0
8
  Requires PHP: 5.6
9
+ Stable Tag: 3.0.4
10
  License: GNU Version 2 or Any Later Version
11
 
12
  Sell your digital products with the ecommerce plugin written for digital creators, by digital creators.
238
 
239
  == Changelog ==
240
 
241
+ = 3.0.4, September 6, 2022 =
242
+ * Fix: Stripe Pro license key detection was not working on older versions of the Stripe Pro gateway.
243
+ * Fix: Hour by hour graphs that spanned more than one day would group all data into the first day.
244
+ * Fix: Reports that span more than one year would group stats by month only.
245
+ * Fix: Some of the report tiles were not accurately accounting for refunded orders.
246
+ * Fix: The purchase receipt was limited to only showing 30 items.
247
+ * Fix: When using persistent object caching, discount codes would not always update immediately.
248
+ * Fix: When manually adding a new order, region based tax rates were not updating.
249
+ * Fix: Improved migration of order address data when checking tax rates of previous orders.
250
+ * Fix: The `stats` API endpoint data did not match the reports data. This improves the iOS app accuracy.
251
+ * Fix: The template modification checks for 3.0 compatibility were checking for modifications too often.
252
+ * Fix: Guest customers using an email address associated with an existing user were not always connected.
253
+ * Fix: When editing an order's address, it was not always saving changes.
254
+ * Dev: Actions were added to the `edd_add_customer` and `edd_update_customer` functions.
255
+
256
  = 3.0.3, August 16, 2022 =
257
  * New: Added support for Global Tax rates as a fallback with the new Tax Rates UI.
258
  * Fix: The old 'fallback tax rate' was not imported as a new tax rate.
uninstall.php CHANGED
@@ -79,6 +79,7 @@ if( edd_get_option( 'uninstall_on_delete' ) ) {
79
  'edd_completed_upgrades',
80
  'edd_default_api_version',
81
  'edd_earnings_total',
 
82
  'edd_settings',
83
  'edd_tracking_notice',
84
  'edd_tax_rates',
79
  'edd_completed_upgrades',
80
  'edd_default_api_version',
81
  'edd_earnings_total',
82
+ 'edd_earnings_total_without_tax',
83
  'edd_settings',
84
  'edd_tracking_notice',
85
  'edd_tax_rates',