Jump to content
#StayAtHome ×
Mr_Ali

Woocommerce plugin help

Recommended Posts

Greetings!

I'm a newbie in php programming started with learning wordpress. I'm working on a local machine and trying to modifying a woocommerce order report plugin. The issue i'm facing is this order report plugin shows only 1 product name even though customer ordered multiple products. I want to show all product names. Your help will be much appreciated

 

<?php


// Add the Product Sales Report to the WordPress admin

add_action('admin_menu', 'hm_psrf_admin_menu');

function hm_psrf_admin_menu() {

	add_submenu_page('woocommerce', 'Custom Order Report', 'Custom Order Report', 'view_woocommerce_reports', 'hm_sbpf', 'hm_sbpf_page');

}



function hm_psrf_default_report_settings() {

	return array(

		'report_time' => '30d',

		'report_start' => date('Y-m-d', current_time('timestamp') - (86400 * 31)),

		'report_end' => date('Y-m-d', current_time('timestamp') - 86400),

		'order_statuses' => array('wc-processing', 'wc-on-hold', 'wc-completed'),

		'products' => 'all',

		'product_cats' => array(),

		'product_ids' => '',

		'variations' => 0,

		'orderby' => 'quantity',

		'orderdir' => 'desc',

		'fields' => array('product_id', 'product_sku', 'product_name', 'quantity_sold', 'gross_sales'),

		'limit_on' => 0,

		'limit' => 10,

		'include_header' => 1,

		'exclude_free' => 0

	);

}



// This function generates the Product Sales Report page HTML

function hm_sbpf_page() {



	$savedReportSettings = get_option('hm_psr_report_settings');

	if (isset($_POST['op']) && $_POST['op'] == 'preset-del' && !empty($_POST['r']) && isset($savedReportSettings[$_POST['r']])) {

		unset($savedReportSettings[$_POST['r']]);

		update_option('hm_psr_report_settings', $savedReportSettings);

		$_POST['r'] = 0;

		echo('<script type="text/javascript">location.href = location.href;</script>');

	}

	

	$reportSettings = (empty($savedReportSettings) ?

						hm_psrf_default_report_settings() :

						array_merge(hm_psrf_default_report_settings(),

								$savedReportSettings[

									isset($_POST['r']) && isset($savedReportSettings[$_POST['r']]) ? $_POST['r'] : 0

								]

						));

	

	// For backwards compatibility with pre-1.4 versions

	if (!empty($reportSettings['cat'])) {

		$reportSettings['products'] = 'cats';

		$reportSettings['product_cats'] = array($reportSettings['cat']);

	}

	

	$fieldOptions = array(
         
         'order_id' => 'Order ID',
		/*'product_id' => 'Product ID',*/
        'customer_name' => 'Customer Name',
		/*'variation_id' => 'Variation ID',*/
		'city' => 'City',
        'address' => 'Address',
        'product_name' => 'Product Name',
        'quantity_sold' => 'Quantity Sold',
		/*'product_sku' => 'Product SKU',*/
		'gross_sales' => 'Gross Sales',
		'product_categories' => 'Schools',
		/*'variation_attributes' => 'Variation Attributes',*/
		/*'gross_after_discount' => 'Gross Sales (After Discounts)'*/
        'ceremony_date' => 'Ceremony Date',
        'ceremony_time' => 'Ceremony Time',
        'customer_note' => 'Additional Information',
	);

		

	include(dirname(__FILE__).'/admin.php');

}



// Hook into WordPress init; this function performs report generation when

// the admin form is submitted

add_action('init', 'hm_sbpf_on_init', 9999);

function hm_sbpf_on_init() {

	global $pagenow;

	

	// Check if we are in admin and on the report page

	if (!is_admin())

		return;

	if ($pagenow == 'admin.php' && isset($_GET['page']) && $_GET['page'] == 'hm_sbpf' && !empty($_POST['hm_sbp_do_export'])) {

		

		// Verify the nonce

		check_admin_referer('hm_sbpf_do_export');

		

		$newSettings = array_intersect_key($_POST, hm_psrf_default_report_settings());

		foreach ($newSettings as $key => $value)

			if (!is_array($value))

				$newSettings[$key] = htmlspecialchars($value);

		

		// Update the saved report settings

		$savedReportSettings = get_option('hm_psr_report_settings');

		$savedReportSettings[0] = array_merge(hm_psrf_default_report_settings(), $newSettings);

		



		update_option('hm_psr_report_settings', $savedReportSettings);

		

		// Check if no fields are selected or if not downloading

		if (empty($_POST['fields']) || empty($_POST['hm_sbp_download']))

			return;

		

		

		// Assemble the filename for the report download

		$filename =  'Product Sales - ';

		if (!empty($_POST['cat']) && is_numeric($_POST['cat'])) {

			$cat = get_term($_POST['cat'], 'product_cat');

			if (!empty($cat->name))

				$filename .= addslashes(html_entity_decode($cat->name)).' - ';

		}

		$filename .= date('Y-m-d', current_time('timestamp')).'.csv';

		

		// Send headers

		header('Content-Type: text/csv');

		header('Content-Disposition: attachment; filename="'.$filename.'"');

		

		// Output the report header row (if applicable) and body

		$stdout = fopen('php://output', 'w');

		if (!empty($_POST['include_header']))

			hm_sbpf_export_header($stdout);

		hm_sbpf_export_body($stdout);

		

		exit;

	}

}



// This function outputs the report header row

function hm_sbpf_export_header($dest, $return=false) {

	$header = array();

	

	foreach ($_POST['fields'] as $field) {

		switch ($field) {

			case 'order_id':

				$header[] = 'Order ID';

				break;
            case 'product_name':

				$header[] = 'Product Name';

				break;
			case 'quantity_sold':

				$header[] = 'Quantity Sold';

				break;	
			case 'gross_sales':

				$header[] = 'Gross Sales';

				break;	
			case 'product_categories':

				$header[] = 'Schools';

				break;		
            case 'customer_name':

				$header[] = 'Customer Name';

				break;
			case 'city':

				$header[] = 'City';

				break;
			case 'address':

				$header[] = 'Address';

				break;		
			
			case 'ceremony_date':

				$header[] = 'Ceremony Date';

				break;
		    case 'ceremony_time':

				$header[] = 'Ceremony Time';

				break;	
			case 'customer_note':

				$header[] = 'Additional Information';

				break;				
			

		}

	}

	

	if ($return)

		return $header;

	fputcsv($dest, $header);

}



// This function generates and outputs the report body rows

function hm_sbpf_export_body($dest, $return=false) {

	global $woocommerce, $wpdb;

	

	$product_ids = array();

	if ($_POST['products'] == 'cats') {

		$cats = array();

		foreach ($_POST['product_cats'] as $cat)

			if (is_numeric($cat))

				$cats[] = $cat;

		$product_ids = get_objects_in_term($cats, 'product_cat');

	} else if ($_POST['products'] == 'ids') {

		foreach (explode(',', $_POST['product_ids']) as $productId) {

			$productId = trim($productId);

			if (is_numeric($productId))

				$product_ids[] = $productId;

		}

	}

	

	// Calculate report start and end dates (timestamps)

	switch ($_POST['report_time']) {

		case '0d':

			$end_date = strtotime('midnight', current_time('timestamp'));

			$start_date = $end_date;

			break;

		case '1d':

			$end_date = strtotime('midnight', current_time('timestamp')) - 86400;

			$start_date = $end_date;

			break;

		case '7d':

			$end_date = strtotime('midnight', current_time('timestamp')) - 86400;

			$start_date = $end_date - (86400 * 6);

			break;

		case '1cm':

			$start_date = strtotime(date('Y-m', current_time('timestamp')).'-01 midnight -1month');

			$end_date = strtotime('+1month', $start_date) - 86400;

			break;

		case '0cm':

			$start_date = strtotime(date('Y-m', current_time('timestamp')).'-01 midnight');

			$end_date = strtotime('+1month', $start_date) - 86400;

			break;

		case '+1cm':

			$start_date = strtotime(date('Y-m', current_time('timestamp')).'-01 midnight +1month');

			$end_date = strtotime('+1month', $start_date) - 86400;

			break;

		case '+7d':

			$start_date = strtotime('midnight', current_time('timestamp')) + 86400;

			$end_date = $start_date + (86400 * 6);

			break;

		case '+30d':

			$start_date = strtotime('midnight', current_time('timestamp')) + 86400;

			$end_date = $start_date + (86400 * 29);

			break;

		case 'custom':

			$end_date = strtotime('midnight', strtotime($_POST['report_end']));

			$start_date = strtotime('midnight', strtotime($_POST['report_start']));

			break;

		default: // 30 days is the default

			$end_date = strtotime('midnight', current_time('timestamp')) - 86400;

			$start_date = $end_date - (86400 * 29);

	}

	

	// Assemble order by string

	$orderby = (in_array($_POST['orderby'], array('product_id', 'gross', 'gross_after_discount')) ? $_POST['orderby'] : 'quantity');

	$orderby .= ' '.($_POST['orderdir'] == 'asc' ? 'ASC' : 'DESC');

	

	// Create a new WC_Admin_Report object

	include_once($woocommerce->plugin_path().'/includes/admin/reports/class-wc-admin-report.php');

	$wc_report = new WC_Admin_Report();

	$wc_report->start_date = $start_date;

	$wc_report->end_date = $end_date;

	

	//echo(date('Y-m-d', $end_date));

	

	$where_meta = array();

	if ($_POST['products'] != 'all') {

		$where_meta[] = array(

			'type' => 'order_item_meta',

			'meta_key' => '_product_id',

			'operator' => 'in',

			'meta_value' => $product_ids

		);

	}

	if (!empty($_POST['exclude_free'])) {

		$where_meta[] = array(

			'meta_key' => '_line_total',

			'meta_value' => 0,

			'operator' => '!=',

			'type' => 'order_item_meta'

		);

	}

	

	// Get report data

	

	// Avoid max join size error

	$wpdb->query('SET SQL_BIG_SELECTS=1');

	

	// Prevent plugins from overriding the order status filter

	add_filter('woocommerce_reports_order_statuses', 'hm_psrf_report_order_statuses', 9999);

	

	// Based on woocoommerce/includes/admin/reports/class-wc-report-sales-by-product.php

	$sold_products = $wc_report->get_order_report_data(array(

		'data' => array(

			'_product_id' => array(

				'type' => 'order_item_meta',

				'order_item_type' => 'line_item',

				'function' => '',

				'name' => 'product_id'

			),

			'_qty' => array(

				'type' => 'order_item_meta',

				'order_item_type' => 'line_item',

				'function' => 'SUM',

				'name' => 'quantity'

			),

			'_line_subtotal' => array(

				'type' => 'order_item_meta',

				'order_item_type' => 'line_item',

				'function' => 'SUM',

				'name' => 'gross'

			),

			'_line_total' => array(

				'type' => 'order_item_meta',

				'order_item_type' => 'line_item',

				'function' => 'SUM',

				'name' => 'gross_after_discount'

			),
            /*usama*/
			'order_id' => array(

				'type' => 'order_item',

				'order_item_type' => 'line_item',

				'function' => '',

				'name' => 'order_id'
			)
             /*usama*/
		),

		'query_type' => 'get_results',

		'group_by' => 'order_id',

		'where_meta' => $where_meta,

		'order_by' => $orderby,

		'limit' => (!empty($_POST['limit_on']) && is_numeric($_POST['limit']) ? $_POST['limit'] : ''),

		'filter_range' => ($_POST['report_time'] != 'all'),

		'order_types' => wc_get_order_types('order_count'),

		'order_status' => hm_psrf_report_order_statuses()

	));

	

	// Remove report order statuses filter

	remove_filter('woocommerce_reports_order_statuses', 'hm_psrf_report_order_statuses', 9999);

	

	if ($return)

		$rows = array();



	// Output report rows

	foreach ($sold_products as $product) {

		$row = array();

		
         /*usama*/
		$order = wc_get_order($product->order_id);
        $customerName =  $order->get_billing_first_name().' '.$order->get_billing_last_name();
        $billingCity = $order->get_billing_city();
        $billingAddress1 = $order->get_billing_address_1();
  		$note = $order->get_customer_note();
        
        
        //echo $product->order_id;
        //echo $customerName.$city.$billingAddress1;
		//echo '<pre>';print_r($order);exit;
         /*usama*/
		foreach ($_POST['fields'] as $field) {

			switch ($field) {

				case 'order_id':

					$row[] = $product->order_id;

					break;
				case 'product_name':

					$row[] = html_entity_decode(get_the_title($product->product_id));

					break;

				case 'quantity_sold':

					$row[] = $product->quantity;

					break;

				case 'gross_sales':

					$row[] = $product->gross;

					break;	
				/*case 'variation_id':

					$row[] = (empty($product->variation_id) ? '' : $product->variation_id);

					break;

				case 'product_sku':

					$row[] = get_post_meta($product->product_id, '_sku', true);

					break;*/
				case 'product_categories':

					$terms = get_the_terms($product->product_id, 'product_cat');

					if (empty($terms)) {

						$row[] = '';

					} else {

						$categories = array();

						foreach ($terms as $term)

							$categories[] = $term->name;

						$row[] = implode(', ', $categories);

					}

				break;	
                case 'customer_name':

					$row[] = $customerName;

					break;
                case 'city':

					$row[] = $billingCity;

					break;
				case 'address':

					$row[] = $billingAddress1;

					break;
				case 'customer_note':

					$row[] = $note;

					break;


				/*case 'gross_after_discount':

					$row[] = $product->gross_after_discount;

					break;*/


                /*usama*/
				
				case 'ceremony_date':

					$row[] = $order->get_meta( '_billing_myfield12', true );

					break;
				case 'ceremony_time':

					$row[] = $order->get_meta( '_billing_myfield13', true );

					break;
				case 'customer_note':

					$row[] = $order->get_meta( '_billing_myfield14', true );

					break;


			}

		}

			

		if ($return)

			$rows[] = $row;

		else

			fputcsv($dest, $row);

	}

	if ($return)

		return $rows;

}



add_action('admin_enqueue_scripts', 'hm_psrf_admin_enqueue_scripts');

function hm_psrf_admin_enqueue_scripts() {

	wp_enqueue_style('hm_psrf_admin_style', plugins_url('css/hm-product-sales-report.css', __FILE__));

	wp_enqueue_style('pikaday', plugins_url('css/pikaday.css', __FILE__));

	wp_enqueue_script('moment', plugins_url('js/moment.min.js', __FILE__));

	wp_enqueue_script('pikaday', plugins_url('js/pikaday.js', __FILE__));

}



// Schedulable email report hook

add_filter('pp_wc_get_schedulable_email_reports', 'hm_psrf_add_schedulable_email_reports');

function hm_psrf_add_schedulable_email_reports($reports) {

	$reports['hm_psr'] = array(

		'name' => 'Product Sales Report',

		'callback' => 'hm_psrf_run_scheduled_report',

		'reports' => array(

			'last' => 'Last used settings'

		)

	);

	return $reports;

}



function hm_psrf_run_scheduled_report($reportId, $start, $end, $args=array(), $output=false) {

	$savedReportSettings = get_option('hm_psr_report_settings');

	if (!isset($savedReportSettings[0]))

		return false;

	$prevPost = $_POST;

	$_POST = $savedReportSettings[0];

	$_POST['report_time'] = 'custom';

	$_POST['report_start'] = date('Y-m-d', $start);

	$_POST['report_end'] = date('Y-m-d', $end);

	$_POST = array_merge($_POST, array_intersect_key($args, $_POST));

	

	if ($output) {

		echo('<table><thead><tr>');

		foreach (hm_sbpf_export_header(null, true) as $heading) {

			echo("<th>$heading</th>");

		}

		echo('</tr></thead><tbody>');

		foreach (hm_sbpf_export_body(null, true) as $row) {

			echo('<tr>');

			foreach ($row as $cell)

				echo('<td>'.htmlspecialchars($cell).'</td>');

			echo('</tr>');

		}

		echo('</tbody></table>');

		$_POST = $prevPost;

		return;

	}

	

	$filename = get_temp_dir().'/Product Sales Report.csv';

	$out = fopen($filename, 'w');

	if (!empty($_POST['include_header']))

		hm_sbpf_export_header($out);

	hm_sbpf_export_body($out);

	fclose($out);

	

	$_POST = $prevPost;

	

	return $filename;

}



function hm_psrf_report_order_statuses() {

	$wcOrderStatuses = wc_get_order_statuses();

	$orderStatuses = array();

	if (!empty($_POST['order_statuses'])) {

		foreach ($_POST['order_statuses'] as $orderStatus) {

			if (isset($wcOrderStatuses[$orderStatus]))

				$orderStatuses[] = substr($orderStatus, 3);

		}

	}

	return $orderStatuses;

}



/* Review/donate notice */



register_activation_hook(__FILE__, 'hm_psrf_first_activate');

function hm_psrf_first_activate() {

	$pre = 'hm_psr';

	$firstActivate = get_option($pre.'_first_activate');

	if (empty($firstActivate)) {

		update_option($pre.'_first_activate', time());

	}

}

if (is_admin() && get_option('hm_psr_rd_notice_hidden') != 1 && time() - get_option('hm_psr_first_activate') >= (14*86400)) {

	add_action('admin_notices', 'hm_psrf_rd_notice');

	add_action('wp_ajax_hm_psrf_rd_notice_hide', 'hm_psrf_rd_notice_hide');

}

function hm_psrf_rd_notice() {

	$pre = 'hm_psr';

	$slug = 'product-sales-report-for-woocommerce';

	echo('

		<div id="'.$pre.'_rd_notice" class="updated notice is-dismissible"><p>Do you use the <strong>Product Sales Report</strong> plugin?

		Please support our free plugin by <a href="" target="_blank">making a donation</a>!product-sales-report-for-woocommerce

		Thanks!</p></div>

		<script>jQuery(document).ready(function($){$(\'#'.$pre.'_rd_notice\').on(\'click\', \'.notice-dismiss\', function(){jQuery.post(ajaxurl, {action:\'hm_psrf_rd_notice_hide\'})});});</script>

	');

}

function hm_psrf_rd_notice_hide() {

	$pre = 'hm_psr';

	update_option($pre.'_rd_notice_hidden', 1);

}

?>

 

Share this post


Link to post
Share on other sites

What debugging attempts have you made so far?  We're supposed to be looking at a lot of lines of your code without any idea what you have tried?  Can you isolate where you think the problem lies?  

Share this post


Link to post
Share on other sites

Hi ginerjm!

 

Here is the main codes printing output

 

//echo $product->order_id;
        //echo $customerName.$city.$billingAddress1;
		//echo '<pre>';print_r($order);exit;
         /*usama*/
		foreach ($_POST['fields'] as $field) {

			switch ($field) {

				case 'order_id':

					$row[] = $product->order_id;

					break;
				case 'product_name':

					$row[] = html_entity_decode(get_the_title($product->product_id));

					break;

				case 'quantity_sold':

					$row[] = $product->quantity;

					break;

				case 'gross_sales':

					$row[] = $product->gross;

					break;	

 

Edited by Mr_Ali

Share this post


Link to post
Share on other sites

I tried chaning class get_name instead get_the_title but it didn't work

 

case 'product_name':

					$row[] = html_entity_decode(get_the_title($product->product_id));

 

Share this post


Link to post
Share on other sites

Don't know what you are telling me but you try by telling me what you found out from your debugging.

Share this post


Link to post
Share on other sites
3 minutes ago, ginerjm said:

Don't know what you are telling me but you try by telling me what you found out from your debugging.

Yes Sir! I'm a newbie and learning everything from internet that' why i can't explain you properly! Sorry for that but i guess this line is printing product name in report

$row[] = html_entity_decode(get_the_title($product->product_id));

Share this post


Link to post
Share on other sites

And have you done any code to help you see what is going on inside?  Do some echo statements to dump some of the values to see if they are what you think they are as you read thru your code.  That is "debugging".

Share this post


Link to post
Share on other sites

I tried using echo with some value it shows in report but only problem is i can't see all product name it shows only one product name but customer has multiple items

Share this post


Link to post
Share on other sites

So that sounds like a loop that is supposed to go thru all the products is failing you.  Find that area and do some echos to show what it is finding and why it is stopping.  

Think!

Share this post


Link to post
Share on other sites

This code is using this reference $row[] = html_entity_decode(get_the_title($product->product_id));

// Assemble the filename for the report download

		$filename =  'Product Sales - ';

		if (!empty($_POST['cat']) && is_numeric($_POST['cat'])) {

			$cat = get_term($_POST['cat'], 'product_cat');

			if (!empty($cat->name))

				$filename .= addslashes(html_entity_decode($cat->name)).' - ';

		}

 

Share this post


Link to post
Share on other sites
5 minutes ago, ginerjm said:

And?

Maybe this 

// This function generates and outputs the report body rows

function hm_sbpf_export_body($dest, $return=false) {

	global $woocommerce, $wpdb;

	

	$product_ids = array();

	if ($_POST['products'] == 'cats') {

		$cats = array();

		foreach ($_POST['product_cats'] as $cat)

			if (is_numeric($cat))

				$cats[] = $cat;

		$product_ids = get_objects_in_term($cats, 'product_cat');

	} else if ($_POST['products'] == 'ids') {

		foreach (explode(',', $_POST['product_ids']) as $productId) {

			$productId = trim($productId);

			if (is_numeric($productId))

				$product_ids[] = $productId;

		}

	}

 

Share this post


Link to post
Share on other sites

Above output functions shows $productId = trim($productId); is that reason which is not showing all product names?

Share this post


Link to post
Share on other sites

You obviously don't know any php and furthermore are not willing to open up a book and look anything up.

The trim function (mentioned above) is one that removes leading and trailing spaces from a string.  That is all. It has nothing to do with a loop or with output.

Why are you into something this deep if you don't know anything about php or programming?  As a professional programmer I find it ridiculous when people with no knowledge think they can just jump into it and hope someone can hold their hand for the next 2 months teaching them what they should already have tried to learn for themselves.

Have fun.  It's a learning process that can possibly give you a new set of knowledge that you may find invaluable.  But - it takes work.

Good bye

  • Like 1

Share this post


Link to post
Share on other sites

Sir thank you for your time ! one last time please see code 

//echo $product->order_id;
        //echo $customerName.$city.$billingAddress1;
		//echo '<pre>';print_r($order);exit;
        
		foreach ($_POST['fields'] as $field) {

			switch ($field) {

				case 'order_id':

					$row[] = $product->order_id;

					break;
				case 'product_name':

					$row[] = html_entity_decode(get_the_title($product->product_id));

					break;

				case 'quantity_sold':

					$row[] = $product->quantity;

					break;

				case 'gross_sales':

					$row[] = $product->gross;

					break;	
				/*case 'variation_id':

					$row[] = (empty($product->variation_id) ? '' : $product->variation_id);

					break;

				case 'product_sku':

					$row[] = get_post_meta($product->product_id, '_sku', true);

					break;*/
				case 'product_categories':

					$terms = get_the_terms($product->product_id, 'product_cat');

					if (empty($terms)) {

						$row[] = '';

					} else {

						$categories = array();

						foreach ($terms as $term)

							$categories[] = $term->name;

						$row[] = implode(', ', $categories);

					}

				break;	
                case 'customer_name':

					$row[] = $customerName;

					break;
                case 'city':

					$row[] = $billingCity;

					break;
				case 'address':

					$row[] = $billingAddress1;

					break;
				case 'customer_note':

					$row[] = $note;

					break;

 

Share this post


Link to post
Share on other sites

Why?  You posted some code but you didn't say why.  What? You just want me to go over it and verify that it is written correctly?  I have no idea what it is trying to do so again I ask - Why?

It looks silly to me.  You have an array and you are putting different values into separate elements of it.  What for?  Are you going to implode those into a string later on?

Share this post


Link to post
Share on other sites

This is a WordPress plugin, and given what you're said about your experience I assume it's not code you wrote. It looks very similar to https://github.com/wp-plugins/product-sales-report-for-woocommerce/blob/master/hm-product-sales-report.php, which looks like it was last updated about 5 years ago. My guess is either the author decided to make the plugin commercial and took it off the public repository or it's a very similar, paid version of the plugin in the public repository. Either way, the plugin author should be accessible and if the plugin isn't working as intended that would be your first avenue to figure out why. If the plugin hasn't been updated in 5 or more years, then I'd reconsider using that particular plugin. At the same point, this is WC so I'd be shocked if there wasn't an actively maintained plugin that does the same thing.

All that having been said, if you're trying to learn PHP I really can't recommend enough finding a different way to do it. WordPress is fine for a lot of things, and in some ways I think it's better than its reputation. However, it's not a good example of how to code PHP. It's very easy to do very bad things that still "work" when programming WordPress plugins and themes, and the code code itself oftentimes encourages bad practices.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.