Performance: generate two Woocommerce order CSV files based on a url query


I wrote this code about a year ago. I'm looking to refactor it to be solid SOLID and secure, since this is generated from a custom endpoint.

The original flow that I had was like this:

  • Enable errors
  • Check if the correct query string is established
  • If not, leave, if not continue
  • Load WordPress / Woocommerce
  • Disinfect the GET variables and set interpolate things as date ranges from string values.
  • Create a collection matrix and scroll through all orders, excluding those that do not comply with the search parameters.
  • Sort by category
  • If there are no orders, leave
  • Otherwise, write to CSV, send an email to CSV and unlink files

I'm waiting for comments

  • The way I'm handling the search parameters is not SOLID.
  • get_product_purchases () is not SOLID, I think I need to better separate the classification of the process of obtaining orders.
  • Too much abstraction in the email.

Is it too much to divide this into several classes or if this

PD This is the url cron

"no-check-certificate >> log.txt)

// Set INI values ​​for tests
ini_set (& # 39; display_errors & # 39 ;, 1);
ini_set (& # 39; display_startup_errors & # 39 ;, 1);
error_reporting (E_ALL);

// Quit if the export type is not configured (correctly)
yes (! isset ($ _ GET[ 'export' ]) || $ _GET['export'] ! == & # 39; GET & # 39;)
exit;

// load WordPress
define (& # 39; WP_USE_THEMES & # 39;, false);
requires ($ _ SERVER['DOCUMENT_ROOT'] . "/wp-load.php");

// Sanititze GET data
$ search_data = sanitize_get ();

// Obtain ordered orders
$ orders = get_product_purchases ($ search_data);
$ orders = sort_orders_by (& # 39; category & # 39 ;, & # 39; DESC & # 39 ;, $ orders);


// Exit if there are no orders
yes (account ($ orders) == 0) {
echo "There were no orders given the parameters";
exit;
}

write_to_csv_get ([
    'search_data' => $search_data,
    'orders'      => $orders,
]);
echo "Successful export";
exit;


/ **
* get_product_purchases
* Return order matrix
* /
get_product_purchases ($ search_data) {function
// Destruction search data
$ cat_data = $ search_data['categories'];
$ sku_data = $ search_data['skus'];
$ period = $ search_data['period'];
$ unit_data = $ search_data['units'];

// See set_order_args () doc-block for more details
$ args = set_order_args ($ search_data);
$ WC_Orders = wc_get_orders ($ args);
$ results = [];

foreach ($ WC_Orders as $ WC_Order) {
if (empty ($ WC_Order)) continue;

$ order_data = $ WC_Order-> get_data ();

$ my_order[ 'order_id' ]          = $ WC_Order-> get_id ();
$ my_order['order_date']          = $ order_data['date_created']-> date (& # 39; Y-m-d & # 39;);
$ my_order['shipping_first_name'] = $ order_data['shipping']['first_name'];
$ my_order['shipping_last_name']  = $ order_data['shipping']['last_name'];
$ my_order['shipping_address_1']  = $ order_data['shipping']['address_1'];
$ my_order['shipping_address_2']  = $ order_data['shipping']['address_2'];
$ my_order['shipping_city']       = $ order_data['shipping']['city'];
$ my_order['shipping_state']      = $ order_data['shipping']['state'];
$ my_order['shipping_postcode']   = $ order_data['shipping']['postcode'];

foreach ($ WC_Order-> get_items () as $ item_key => $ item_values) {
$ my_order_copy = $ my_order;

## Using the methods of WC_Order_Item ##
$ my_item['id'] = $ item_values-> get_id (); // You can directly access the article ID from the $ item_key in the foreach loop or

## Access the data properties of the order elements (in an array of values) ##
$ item_data = $ item_values-> get_data ();

$ product_id = $ item_data['product_id'];
$ product['product_name']      = $ item_data['name'];
$ product['quantity']          = $ item_data['quantity'];

// Get data from the WC_product object using methods (examples)
$ WC_Product = $ item_values-> get_product (); // the WC_Product object
if (empty ($ WC_Product)) {
continue;
};

$ item['item_name'] = preg_replace (& # 39; /[x00-x1Fx7F-xFF]/ & # 39;, & # 39; & # 39 ;, $ item_values-> get_name ()); // Product name
$ product['sku']    = $ WC_Product-> get_sku ();
$ product['price']  = ($ WC_Product-> get_price ())
? sprintf (& # 39;% .2f & # 39 ;, $ WC_Product-> get_price ())
: & # 39; & # 39 ;;

// Labels = business units
$ product['tag']     = strtolower (get_tag_name ($ product_id));

// The names of the terms are categories
$ Terms = get_the_terms ($ product_id, & # 39; product_cat & # 39;);
$ cats = [];

foreach ($ terms like $ term) {
array_push ($ cats, strtolower ($ term-> name));
}

$ product['category']    = $ cats[0];

/ *
Carry out the verification of the condition of whether to push to export

If a list of filters is established, verify the ownership of the product
The list of filters and see if it matches. If you do not,
exclude it from the CSV
* /
$ push = check_against_list ($ cat_data, $ product, & # 39; category & # 39;);
if ($ push == 0) continues;

$ push = check_against_list ($ unit_data, $ product, & # 39; tag & # 39;);
if ($ push == 0) continues;

$ push = check_against_list ($ sku_data, $ product, & # 39; sku & # 39;);
if ($ push == 0) continues;

yes ($ push == 1) {
$ row = array_merge ($ my_order_copy, $ product);
array_push ($ results, $ row);
}
}
}

returns $ results;
}

/ **
* @param array $ params [search_data & orders]
 * @he came back [void]
 * /
function write_to_csv_get ($ params) {
// destruction params
$ period = $ params['search_data']['period'];
$ orders = $ params['orders'];

$ date_summary = ($ period['all'] == 0)
? "from {$ period['range']['start_date']} to {$ period['range']['end_date']} "
: "From the beginning";

$ breakdown_filename = "company - {$ period['type']} -order-details.csv ";
$ path = "/ tmp";
$ fp = fopen ("$ path / $ breakdown_filename", & # 39; w & # 39;);

if (fopen ("$ path / $ breakdown_filename", "w +")) {
$ total = []; // Sum of quantities
$ placed_encabezado = false;

foreach ($ orders such as $ index => $ row) {
$ total = sum ($ row, $ total);

// Old code to write all the details of the orders.
yes (! $ placed_header)
{
fputcsv ($ fp, array_keys ($ row));
$ classified_header = true;
}

// If the row is set, write it to CSV
yes (account ($ row)! = 0)
fputcsv ($ fp, $ row);
}
} else {
fclose ($ fp);
unlink ("$ path / $ breakdown_filename");
error_log ("Automatic report: CSV breakdown: CSV could not be opened");
}

notify ($ breakdown_filename, $ path, & # 39; Download details of the export order & # 39 ;, & # 39; detailed & # 39 ;, $ params);

fclose ($ fp);
unlink ("$ path / $ file name");

$ totals_filename = "company - {$ period['type']} -orders-totals.csv ";
$ fp = fopen ("$ path / $ totals_filename", & # 39; w & # 39;);

if (fopen ("$ path / $ totals_filename", "w +")) {
// Send email totals
fputcsv ($ fp, [ "Orders - {$date_summary}"] );
fputcsv ($ fp, [ 'SKU', 'Name', 'Totals' ] );

// Output of two total columns (name | total)
foreach ($ totals as $ name => $ details) {
$ num = $ details[0];
$ sku = $ details[1];
/ *
Excel does not like some of the ASCII characters, use 7-bit ASCII
https://stackoverflow.com/questions/1176904/php-how-to-remove-all-non-printable-characters-in-a-string
* /
fputcsv ($ fp, [ $sku, $name, $num ]);
}

} else {
fclose ($ fp);
unlink ("$ path / $ totals_filename");
error_log ("Automatic report: CSV of totals: CSV could not be opened");
}

// Send CSV breakdown
notify ($ totals_filename, $ path, & # 39; Download Totals Export & # 39 ;, & # 39; totals for & # 39 ;, $ params);

fclose ($ fp);
unlink ("$ path / $ totals_filename");

he came back;
}

sort_orders_by_date function ($ results, $ order = & # 39; DESC & # 39;) {
foreach ($ results as $ key => $ part) {
$ order[$key] = strtotime ($ part['order_date']);
}

($ order == & # 39; DESC & # 39;)
? array_multisort ($ sort, SORT_DESC, $ results)
: array_multisort ($ sort, SORT_ASC, $ results);

returns $ results;
}

sort_orders_by function ($ field, $ order = & # 39; DESC & # 39 ;, $ results) {
yes (account ($ results)> 0)
{
foreach ($ results as $ key => $ part) {
$ order[$key] = $ part[ $field ];
}

($ order == & # 39; DESC & # 39;)
? array_multisort ($ sort, SORT_DESC, $ results)
: array_multisort ($ sort, SORT_ASC, $ results);
}

returns $ results;
}

function sanitize_get () {
/ * ---------------------------------------------
Filter / disinfect dates
--------------------------------------------- * /
yes (isset ($ _GET['period']))
{
$ period['all'] = 0;

switch ($ _GET['period'])
{
case (& # 39; week & # 39;):
$ period['type'] = & # 39; weekly & # 39 ;;
$ previous_week = strtotime ("- 1 week +1 day");

$ start_week = strtotime ("last Sunday", $ previous_week);
$ end_week = strtotime ("next Saturday", $ start_week);

$ period['range']['start_date']    = filter_var (date ("Y-m-d", $ start_week), FILTER_SANITIZE_STRING);
$ period['range']['end_date']            = filter_var (date ("Y-m-d", $ end_week), FILTER_SANITIZE_STRING);
break;
case (& # 39; month & # 39;):
$ period['type'] = & # 39; monthly & # 39 ;;

$ period['range']['start_date']    = date (& # 39; Y-m-d & # 39 ;, strtotime (& # 39; first day of last month & # 39;));
$ period['range']['end_date']            = date (& # 39; Y-m-d & # 39 ;, strtotime (& last day of last month & # 39;));
break;
case (& # 39; year & # 39;):
$ year = date (& # 39; Y & # 39;) - 1;

$ period['type'] = & # 39; annual & # 39 ;;
$ period['range']['start_date']    = "{$ year} -01-01";
$ period['range']['end_date']            = "{$ year} -12-31";
break;
Case (& # 39; Forever & # 39;):
$ period['type'] = & # 39; full & # 39 ;;
$ period[ 'all' ] = 1;
break;
}
}
plus
{
error_log (& # 39; Self-export: there is no given period for automatic export & # 39;);
exit;
}

/ * ---------------------------------------------
Filter / Reset Categories
--------------------------------------------- * /
yes (isset ($ _GET['filter_categories']))
{
$ categories = [];
$ categories['all'] = 0;

yes ($ _GET['filter_categories'] == & # 39; all & # 39;)
{
$ categories['all'] = 1;
}
plus
{
$ categories['list'] = explode (& # 39;, & # 39 ;, $ _GET['filter_categories']);

foreach ($ categories['list'] like $ i => $ cat)
{
$ categories['list'][$i]    = str_replace (& # 39; - & # 39 ;, & # 39; & # 39 ;, strtolower (filter_var ($ cat, FILTER_SANITIZE_STRING)));
}


yes ($ categories['all'] === 0 && count ($ categories['list'] ) < 1 )
                 error_log( 'Empty value for categories was passed' );
         }
     }
     else
     {
         error_log( 'Autoexport: Empty value for categories was passed' );
         exit;
     }

     /*---------------------------------------------
             Filter / Sanitize Business Units
      ---------------------------------------------*/
     if ( isset( $_GET['filter_units']) )
     {
         if ( $_GET['filter_units'] == 'all' )
         {
             $units['all'] = 1;
         }
         else
         {
             $units = [];
             $units['list'] = explode( ',', $_GET['filter_units']);

             foreach( $units['list'] as $i => $ unit)
{
$ units['list'][$i]    = str_replace (& # 39; - & # 39 ;, & # 39; & # 39 ;, strtolower (filter_var ($ unit, FILTER_SANITIZE_STRING)));
}

yes ($ units['all'] == 0 && account ($ units['list'] ) < 1 )
                 error_log( 'Empty value for business units was passed' );
         }
     }
     else
     {
         error_log( 'Autoexport: Empty value for business units was passed' );
         exit;
     }

     /*---------------------------------------------
             Filter / Sanitize Skus
      ---------------------------------------------*/
     if ( isset( $_GET['filter_skus']) )
     {
         $skus = [];

         if ( $_GET['filter_skus'] == 'all' )
         {
             $skus['all'] = 1;
         }
         else
         {
             $skus['list'] = explode( ',', $_GET['filter_skus'] );

             // Filter unit string and push it to the search list
             foreach( $skus['list'] as $i => $ sku)
{
$ skus['list'][$i]    = str_replace (& # 39; - & # 39 ;, & # 39; & # 39 ;, filter_var ($ sku, FILTER_SANITIZE_STRING));
}

yes ($ skus['all'] === 0 && count ($ skus['list'] ) < 1 )
                 error_log( 'Autoexport: Empty value for skus was passed' );
         }
     }
     else
     {
         error_log( 'Autoexport: Empty value for skus was passed' );
         exit;
     }

      /*---------------------------------------------
              Filter / Sanitize Emails
      --------------------------------------------- */
      // Optionally pass in string of double pipe separated emails to send to
      if ( isset( $_GET['email_list']))
      {
          $email_list = explode( ',', $_GET['email_list'] );

          foreach ( $email_list as $i => $ email)
{
$ email_list[ $i ] = filter_var ($ email, FILTER_SANITIZE_EMAIL);
}

$ email_list = implode (& # 39;, & # 39 ;, $ email_list);
}
plus
{
error_log (& # 39; Self-export: email given to automatic export & # 39;);
exit;
}

$ search_data = [
         'validated'  => 1,
         'period'     => $period,
         'categories' => $categories,
         'units'      => $units,
         'skus'       => $skus,
         'email_list' => $email_list,
     ];

yes ($ search_data['validated'] ! = 1)
die (& # 39; Sorry, the data you entered is not valid & # 39;);

returns $ search_data;
}

/ *
More information about the wc_order arguments
https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
* /
function set_order_args ($ search_data) {
$ period = $ search_data['period'];

$ args = [
     // 'status' => [ 'completed' ],
& # 39; status & # 39; => & # 39; completed & # 39 ;,
& # 39; order_by & # 39; => & # 39; date & # 39 ;,
& # 39; order & # 39; => & # 39; DESC & # 39 ;,
];

yes (isset ($ period['range'] )) {
yes (isset ($ period['range']['start_date']) && isset ($ period['range']['end_date'])) {
$ args['date_before'] = $ period['range']['end_date'];
$ args['date_after']  = $ period['range']['start_date'];
// Ancient road WC worked
// Format of WC date range (2018-08-01 ... 2018-08-31)
// $ range = implode (& # 39; ... & # 39 ;, $ period['range'] );
// $ args[ 'date_created'] = $ rank;
}
}

returns $ args;
}

get_term_names () {function
$ tags = get_terms (array (& # 39; product_tag & # 39;), "hide_empty = 1");
$ tag_list = [];

if (! empty ($ tags) &&! is_wp_error ($ tags)) {
foreach ($ tags as $ tag) {
$ tag_list[] = $ tag-> name;
}
}

returns $ tag_list;
}

/ *
Read more here:
https://stackoverflow.com/questions/21858431/woocommerce-get-a-list-for-all-sku-product
* /
get_sku_list () {function
$ skus = [];
$ args = array (& # 39; post_type & # 39; => & # 39; product & # 39 ;, & # 39; posts_per_page & # 39; => -1);

query_posts ($ args);

if (have_posts ()):
while (have_posts ()): the_post ();
global $ post;
$ product = wc_get_product ($ post-> ID);
$ sku = $ product-> get_sku ();

yes ($ sku! = & # 39; & # 39;)
{
array_push ($ skus, $ sku);
}
in the end
it will end yes;

returns $ skus;
}

get_tag_name ($ product_id) {function
$ tags = wp_get_post_terms ($ product_id, & # 39; product_tag & # 39;);

if (count ($ tags)> 0) {
foreach ($ tags as $ tag) {
returns $ tag-> name;
}
} else {
returns & # 39; blank & # 39 ;;
}
}

check_against_list function ($ data, $ product, $ property) {
$ push = (int) true;

yes ($ data['all'] == 0) {
if (is_array ($ data)['list'])) {
if (! in_array (htmlspecialchars_decode ($ product['tag']), $ data['list'] )) {
$ push = 0;
}
} else {
$ push = 0;
}
}

returns $ push;
}

sum of functions ($ row, $ total) {
(empty (total $[$row['product_name' ]]))
? $ total[$row['product_name' ]]=[(int)1$row[(int)1$row[(int)1$fila[(int)1$row['sku']]: $ total[$row['product_name' ]][0]++;

returns $ total
}

function check_in_range ($ start_date, $ end_date, $ order_date) {
// Convert to timestamp
$ start_ts = strtotime ($ start_date);
$ end_ts = strtotime ($ end_date);
$ user_ts = strtotime ($ order_date);

// Verify that the user's date is between start and end
return (($ user_ts> = $ start_ts) && ($ user_ts <= $ end_ts));
}

// EMAIL
mail_attachment function ($ file name, $ path, $ mailto,
$ from_mail, $ from_name, $ replyto,
$ subject, $ message)
{
$ file = $ path. "/". $ filename;
$ file_size = filesize ($ file);
$ handle = fopen ($ file, "r");
$ content = fread ($ handle, $ file_size);
fclose ($ handle);
$ content = chunk_split (base64_encode ($ content));
$ uid = md5 (uniqid (time ()));
$ header = "From:". $ from_name " <".$from_mail."> r  n ";
$ header = "Reply to:". $ Replyto. " r  n"
$ header = "MIME version: 1.0  r  n";
$ header = "Content-Type: multipart / mixed; boundary = " ". $ Uid."  " r  n"

$ my_message = $ message;

$ message = "";
$ message = "This is a multi-part message in MIME format.  R  n";
$ message. = "-". $ uid. " r  n"
$ message = "Type of content: text / without format; set of characters = iso-8859-1  r  n";
$ message = "Content-Transfer-Encoding: 7bit  r  n  r  n";
$ message = $ my_message " r  n  r  n"
$ message. = "-". $ uid. " r  n"
$ message = "Content type: application / octet-stream; name = " ". $ Filename."  " r  n" // use different types of content here
$ message = "Content transfer encoding: base64  r  n";
$ message = "Content-Layout: attachment; file_name = " ". $ File_name."  " r  n  r  n"
$ message. = $ content. " r  n  r  n"
$ message. = "-". $ uid. "-";

mail ($ mailto, $ subject, $ message, $ header);
}

Notification function ($ file name, $ path,
$ subject = & # 39; Export & # 39 ;,
$ report_type, $ params)
{
$ subject = $ params['period']['type']    . & # 39; Export & # 39 ;;
$ recipients = $ params['search_data']['email_list'];

$ sender_address = "web@thecompanydomain.com";
$ sender_name = "Company website";
$ reply_to = "web@thecompanydomain.com";
$ subject = "Brand $ subject";
$ message = "Attached is the order list for $ report_type.";


mail_attachment ($ file name, $ path, $ recipients,
$ sender_address, $ sender_name,
$ reply_to, $ subject, $ message);

returns 0;
}

if (! function_exists (& # 39; pre & # 39;)) {
pre function ($ var = & # 39; & # 39;) {
echo "
";
print_r ($ var);
echo "

north";
}
}