Code Snippets

Home » Developers » Code Snippets

Code Snippets

Here are several examples of things you can do using the many hooks and filters available in Sliced Invoices. These code snippets are designed to be added to your (child) theme’s functions.php file.

Caution: we do NOT guarantee compatibility between these snippets and future releases of Sliced Invoices. USE AND MODIFY AT YOUR OWN RISK. If you’re not a developer, you probably shouldn’t use these.

General

Change 'Pay with PayPal' button text
add_filter( 'sliced_get_gateway_paypal_label', 'sliced_custom_gateway_paypal_label' );
function sliced_custom_gateway_paypal_label() {
	return 'Pay with Credit Card';
}
Custom Template Example - add 'Payments' section
By default our invoice template does not show detailed payment information, only the total paid. But what if you want to show detailed information for each payment? You can easily customize the template using a little code. Read how to do this on our Quote & Invoice Templates page.

Here’s an example template which adds a “Payments” section. Feel free to modify as needed.

Automatically send new user welcome email to new clients
add_action( 'user_register', 'sliced_send_welcome_email', 10, 1 );
function sliced_send_welcome_email( $user_id ) {
    wp_new_user_notification( $user_id, 'both' );
}
Adding custom email wildcards
Example #1: add a wildcard %username% that returns the client’s username:

Example #2: add wildcard %payment_method% which represents the gateway used for the last payment:

Adding email recipients
add_filter( 'sliced_get_email_recipient', 'sliced_custom_add_recipient', 10, 3 );
function sliced_custom_add_recipient( $output, $id, $type ) {
	if ( $type === 'payment_received' ) {
		$output .= ', second_email_address@example.com';
	}
	return $output;
}
Change email subject
add_filter( 'sliced_get_email_subject', 'sliced_get_email_subject_custom', 20, 3 );
function sliced_get_email_subject_custom( $subject, $id, $type ) {
	switch ( $type ) {
		case 'quote_accepted':
			$subject = "Votre devis %number% a été accepté!";
			$subject = str_replace( "%number%", sliced_get_invoice_prefix( $id ) . sliced_get_invoice_number( $id ), $subject );
			break;
	}
	return $subject;
}

You can easily add additional case statements for other email types (for example quote_declined, payment_received, etc).

Disable certain automatic emails
The following example will disable the automatic “payment received” email to both the client and admin. You can easily modify this to disable other emails, just add or remove the $type you want in the conditional.

add_filter( 'sliced_get_email_content', 'sliced_disable_email', 10, 3 );
function sliced_disable_email( $output, $id, $type ) {
	if ( $type === 'payment_received' || $type === 'payment_received_client' ) {
		return false;
	}
	return $output;
}
Automatically send quotes/invoices
For Quotes:

For Invoices:

Automatically mark converted invoices as unpaid
add_action( 'sliced_client_accepted_quote', 'sliced_auto_mark_converted_invoice_unpaid', 10, 1 );
function sliced_auto_mark_converted_invoice_unpaid( $id ) {
	Sliced_Invoice::set_as_unpaid( $id );
}
Automatically send new quotes to admin
add_action( 'new_to_publish', 'auto_send_pdf', 10, 1 );
add_action( 'auto_send_pdf_deferred', 'auto_send_pdf_deferred_function', 10, 1 );
function auto_send_pdf( $post ) {
	if ( $post->post_type === 'sliced_quote' ) {
		// run in background 1 minute from now
		wp_schedule_single_event( time() + 60, 'auto_send_pdf_deferred', array( $post ) );
	}
}
function auto_send_pdf_deferred_function( $post ) {
	if ( $post->post_type === 'sliced_quote' ) {
		$sliced_notifications = new Sliced_Notifications();
		$sliced_notifications->id = $post->ID;
		$sliced_notifications->type = "quote";
		$type = "quote_available";
		add_filter( 'wp_mail_content_type', array( $sliced_notifications, 'set_email_type' ) );
		$send = wp_mail(
			$sliced_notifications->settings['from'], // send to admin
			$sliced_notifications->get_subject( $type ),
			$sliced_notifications->get_content( $type ),
			$sliced_notifications->get_headers( $type ),
			$sliced_notifications->get_attachments()
		);
		remove_filter( 'wp_mail_content_type', array( $sliced_notifications, 'set_email_type' ) );
		do_action( 'sliced_after_send_email', $sliced_notifications->id );
	}
}
Enable custom statuses
add_filter( 'sliced_quote_status_params', 'sliced_enable_custom_statuses' );
add_filter( 'sliced_invoice_status_params', 'sliced_enable_custom_statuses' );
function sliced_enable_custom_statuses( $opts ) {
	$opts['show_ui'] = TRUE;
	return $opts;
}
Show quantity field as whole numbers only, no decimals
The following is an example use case of the sliced_invoice_line_items_output filter. The same filter can be used to replace any or all content of an invoice’s line items section.

add_filter( 'sliced_invoice_line_items_output', 'sliced_invoice_line_items_output_custom' );
function sliced_invoice_line_items_output_custom( $output ) {
	if ( preg_match_all('#<td class="qty">(.*?)</td>#', $output, $matches) ) {
		$patterns = array();
		$replacements = array();
		foreach ( $matches[1] as $match ) {
			$patterns[] = '#<td class="qty">'.$match.'</td>#';
			$replacements[] = '<td class="qty">'.intval($match).'</td>';
		}
		$output = preg_replace($patterns, $replacements, $output);
	}
	return $output;
}
Hide adjust field
add_filter( 'sliced_quote_hide_adjust_field', 'sliced_hide_the_adjust_field' );
function sliced_hide_the_adjust_field() {
	return true;
}

You can use basically this same code for both Quotes and Invoices, just change the first line where it says “sliced_quote” to “sliced_invoice”.

Update 2017-10-27: The above snippet is no longer necessary, you can hide the adjust field through the settings pages. See the setting “Hide Adjust Field” under Quote Settings and under Invoice Settings, respectively. This will hide the adjust field from showing on the frontend.

If you want to hide the adjust field on the admin side, use the following code snippet instead:


Adjust 'rate' field by amount in adjust field
add_filter( 'sliced_get_invoice_line_items', 'sliced_adjust_the_rate_field', 10, 2 );
function sliced_adjust_the_rate_field( $output, $id ) {
	if ( get_post_type( $id ) === 'sliced_quote' ) {
		if( !empty( $output ) && !empty( $output[0] ) ) {
			foreach ( $output[0] as &$item ) {
				if ( isset( $item['tax'] ) && $item['tax'] > 0 ) {
					$item['amount'] = '' . intval( $item['amount'] ) * ( 1 + ( intval( $item['tax'] ) / 100 ) );
					$item['tax'] = 0;
				}
			}
		}
	}
	return $output;
}
Hide other fields
For example, hide the client’s email address:

add_filter( 'sliced_get_client_email', 'sliced_hide_the_email_address', 10, 3 );
function sliced_hide_the_email_address( $email, $client, $id ) {
	return '';
}
Example of using filters to customize email header and footer templates
Example of a custom email header template:

add_filter( 'sliced_email_header', 'sliced_custom_email_header' );
function sliced_custom_email_header() {

	$email_header = "<!DOCTYPE html><html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><title>" . sliced_get_business_name() . "</title></head><body marginwidth='0' topmargin='0' marginheight='0' offset='0' style='background:#eeeeee; font-family: arial, helvetica; font-size: 16px;'>
			<div id='sliced-wrapper' style='margin-top:0'>

				<table border='0' topmargin='0' cellpadding='0' cellspacing='0' height='100%' width='640' align='center'>
					<tr>
						<td align='center' valign='top' style='background:#dddddd;'>
						<div id='sliced-logo'>
								<h1 class='business-name' style='margin:20px 0 20px 0;''>
									  <a href='" . esc_url( sliced_get_business_website() ) . "'>";

									  if ( sliced_get_business_logo() ) {
										$email_header .= "<img src='" . esc_url( sliced_get_business_logo() ) . "' />";
									  } else {
										$email_header .= esc_html( sliced_get_business_name() );
									  }

									  $email_header .= "</a>
								 </h1>
						</div>
							<table border='0' cellpadding='10' cellspacing='0' width='640' id='sliced-container'  style='background:#ffffff; color:#444444;'>
								<tr>
									<td align='center' valign='top'>
											<!-- Body -->
										<table border='0' cellpadding='0' cellspacing='0' width='600' id='template_body'>
										<tr>
												 <td valign='top' id='body_content'>
													  <!-- Content -->
													  <table border='0' cellpadding='20' cellspacing='0' width='100%'>
													  <tr>
															<td valign='top' style='font-size: 16px;'>
																 <div id='body_content_inner'>";

	return $email_header;
}

Example of a custom email footer template:

add_filter( 'sliced_email_footer', 'sliced_custom_email_footer' );
function sliced_custom_email_footer() {

	$settings = get_option( 'sliced_emails' );
	
	$email_footer = '';

	// include the button
	$button_text = '';
	$type = sliced_get_the_type();
	if( $type == 'invoice' ) {
		$button_text = __( 'View this invoice online', 'sliced-invoices' );
	} elseif ( $type == 'quote' ) {
		$button_text = __( 'View this quote online', 'sliced-invoices' );
	}
	
	$email_footer .= "<br><a href='" . esc_url( sliced_get_the_link() ) . "' style='font-size: 100%; line-height: 2; color: #ffffff; border-radius: 5px; display: inline-block; cursor: pointer; font-weight: bold; text-decoration: none; background: #60ad5d; margin: 30px 0 10px 0; padding: 0; border-color: #60ad5d; border-style: solid; border-width: 10px 20px;'>" . esc_html( $button_text ) . "</a>";

	$email_footer .=  "</div><!-- End body_content_inner -->
												</td>
															</tr>
													  </table><!-- End Content -->
												 </td>
											</tr>
									  </table><!-- End Body -->
								 </td>
							</tr>
						<tr>
								<td align='center' valign='top' style='background:#f6f6f6;color:#444444;'>
									  <!-- Footer -->
									<table border='0' cellpadding='10' cellspacing='0' width='600' id='sliced_footer' >
									<tr>
										<td valign='top'>
												 <table border='0' cellpadding='10' cellspacing='0' width='100%'>
												 <tr>
													  <td colspan='2' valign='middle' id='credit'>";
														$email_footer .= wpautop( wp_kses_post( stripslashes( $settings['footer'] ) ) ) . "</td>
												 </tr>
												 </table>
											</td>
									  </tr>
									  </table><!-- End Footer -->
								 </td>
							</tr>
					  </table>
				 </td>
			</tr>
	  </table>
	  </div><!-- End Sliced Wrapper -->
	 </body>
	</html>";

	return $email_footer;
}
Example taking over 'Pay with PayPal' button, go direct to PayPal Standard checkout
add_action( 'sliced_invoice_top_bar_left', 'sliced_paypal_standard_checkout', 999 );
function sliced_paypal_standard_checkout() {
	$paypal_email_address    = 'YOUR_EMAIL_ADDRESS_HERE';
	$id                      = sliced_get_invoice_id();
	$currency                = sliced_get_invoice_currency( $id );
	$payments                = get_option( 'sliced_payments' );
	$gateway                 = array();
	$gateway['currency']     = $payments['paypal_currency'];
	?>
	<script type="text/javascript">
		jQuery('a[data-gateway="paypal"]').attr('href', '#' ).removeClass('thickbox').click(function(e){
			e.preventDefault();
			jQuery('#sliced_paypal_standard_checkout').submit();
		});
	</script>
	<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="sliced_paypal_standard_checkout">
		<input type="hidden" name="business" value="">
		<input type="hidden" name="cmd" value="_xclick">
		<input type="hidden" name="item_name" value="">
		<input type="hidden" name="amount" value="">
		<input type="hidden" name="currency_code" value="">
	</form>
	
Example working with client meta fields

Sliced Invoices stores client fields in the wp_usermeta table, meaning you can access them using standard WordPress functions like in the following examples:

// Print client's business name
$user = get_userdata( $user_id );
echo $user->_sliced_client_business;

// Update client's business name
update_user_meta( $user_id, '_sliced_client_business', 'New Business Name' );

You can also use one of the many User Meta plugins available to access these fields, for example User Meta Pro (http://user-meta.com/).

The fields used by Sliced Invoices are the following:

_sliced_client_business
_sliced_client_address
_sliced_client_extra_info

Example adding custom javascript to admin area

For example, the following code automatically populates the title field when creating a new Invoice:

if ( @$pagenow === 'post-new.php' && @$_GET['post_type'] === 'sliced_invoice' ) {
	add_action( 'admin_head', 'sliced_custom_code_20161108' );
}
function sliced_custom_code_20161108() {
	echo '<script type="text/javascript">
			jQuery(document).ready(function(){
				var invPre = jQuery(".cmb2-id--sliced-invoice-number span.prefix").html();
				var invNum = jQuery("#_sliced_invoice_number").val();
				jQuery("#title").val( invPre + invNum );
			});
		</script>';
}
Remove Quotes section from admin menu

 

Braintree Payment Gateway

Supporting multiple currencies

To accept multiple currencies in Braintree, in your Braintree account you must create separate Merchant Account IDs for each currency. (Note: "Merchant Account ID" is not the same as your "Merchant ID"!)

If your default Merchant Account's currency is, for example, USD, then all invoices payments would be in USD, unless you specify a different currency on the Invoice. In that case, if the Invoice is in, for example, AUD, the following code can be used to map the currency to the correct Merchant Account ID.

add_filter( 'sliced_braintree_transaction_sale_args', 'sliced_braintree_add_addl_merchant_ids', 10, 2 );
function sliced_braintree_add_addl_merchant_ids( $args, $id ) {
	$currency = sliced_get_invoice_currency( $id );
	switch ( $currency ) {
		case "AUD":
			$args['merchantAccountId'] = 'slicedinvoicesaud';
			break;
	}
	return $args;
}

Be sure to change 'slicedinvoicesaud' to whatever your Merchant Account ID is for the given currency.

 

Client Area Extension

Don't load FontAwesome

The Sliced Invoices Client Area uses the popular FontAwesome CSS icon library. If you already have FontAwesome loaded somewhere else on your site, or if you want to use a different version from the one included with Sliced Invoices, you can prevent Sliced Invoices from loading it with the following code:

 

Gravity Forms Extension

Populate hidden fields

Example code:

add_action( 'gform_pre_submission', 'pre_submission_handler' );
function pre_submission_handler( $form ) {
        $_POST['input_4'] = $_POST['input_1'] . "\r\n"
        . $_POST['input_2'] . "\r\n"
        . $_POST['input_3'];
}

Another example:

add_action( 'gform_pre_submission', 'pre_submission_handler' );
function pre_submission_handler( $form ) {
        $_POST['input_6'] = "<table>
                <tr>
                <td>Name</td><td>{$_POST['input_1']}</td>
                </tr>
                </table>";
}
Custom quote numbering

For example, based on a timestamp:

add_filter( 'gform_field_value_quote_number', 'quote_number_population_function' );
function quote_number_population_function( $value ) {
	$timestamp = time();
	return date( "ymdHis", $timestamp );
}
Handling Line Items

When setting up the feed you can only choose one field containing the line items. There are basically two ways to get all your line items into one field -- the first, and easiest, is to add a Gravity Forms' "list" field to your form. The "list" field type allows you setup multiple columns/rows, which Gravity Forms automatically combines on the back end into a particular format which our plugin understands and can process.

The only catch here is that, for it to work, you must include 4 columns: Quantity, Title, Amount, Description. You can name the columns anything you like, but there must be 4, and in that order.

If you need more flexibility, the other way you can do this is to setup the form however you want, and use a little custom coding to format the line items on the back end. To do this you would add some code to your site's functions.php file which would take care of the necessary formatting. If you are comfortable with PHP coding, you can use something like the following as a starting point (this is just an example, you would need to adapt it to your particular scenario):

add_action( 'sliced_gravityforms_feed_processed', 'si_2017_04_17_custom_line_items', 10, 4 );
function si_2017_04_17_custom_line_items( $id, $feed, $entry, $form ) {
	$line_items = array(
		array(
			// this is one line item... match the field IDs to
			// your form.  For example if our field ID is 131
			// and it is a "product" field type, we would do:
			"qty"         => rgar( $entry, '131.3' ),
			"title"       => rgar( $entry, '131.1' ),
			"amount"      => rgar( $entry, '131.2' ),
			"description" => '',
		),
		array(
			// this is another line item
			"qty"         => rgar( $entry, '26.3' ),
			"title"       => rgar( $entry, '26.1' ),
			"amount"      => rgar( $entry, '26.2' ),
			"description" => '',
		),
		// etc...
	);
	update_post_meta( $id, '_sliced_items', $line_items );
}
Gravity Perks user registration - delay invoice creation pending user approval
//delay processing the feed
add_filter( 'gform_is_delayed_pre_process_feed', 'sliced_invoices_delay_feed', 10, 4 );
function sliced_invoices_delay_feed( $is_delayed, $form, $entry, $slug ) {
    if ( $slug === 'slicedinvoices' ) {
        return true;
    }
    return $is_delayed;
}

// process the feed on gform_user_registered
add_action( 'gform_user_registered', 'send_to_sliced_invoices', 10, 3 );
function send_to_sliced_invoices( $user_id, $feed, $entry ) {
    $form = GFAPI::get_form( $entry['form_id'] );
    $si_feed = GFAPI::get_feeds( null, null, 'slicedinvoices' );
    $SIGF = new Sliced_Invoices_GF;
    $SIGF->process_feed( $si_feed[0], $entry, $form );
}
Add adjust field to line items
add_action( 'gform_after_submission', 'sliced_quote_add_adjust', 10, 2 );
function sliced_quote_add_adjust( $entry, $form ) {
	$hidden_adjust_field = 'input_8'; // change this number to the correct field id
	
	$adjust = intval( $_POST[$hidden_adjust_field] );
	if ( $adjust > 0 ) {
		// get last quote
		$latest_quote_id = null;
		$args = array(
			'post_type'      => 'sliced_quote',
			'post_status'    => 'publish',
			'posts_per_page' => 1,
			'orderby'        => 'date',
			'order'          => 'DESC',
		);
		$the_query = new WP_Query( $args );
		if ( $the_query->have_posts() ) {
			$latest_quote_id = $the_query->post->ID;
		}
		
		// update line items
		if ( $latest_quote_id ) {
			$line_items = get_post_meta( $latest_quote_id, '_sliced_items' );
			$new_line_items = array();
			foreach ( $line_items as $line_item ) {
				foreach ( $line_item as $item ) {
					if ( ! isset( $item['tax'] ) ) {
						$item['tax'] = $adjust;
					}
					$new_line_items[] = $item;
				}
			}
			update_post_meta( $latest_quote_id, '_sliced_items', $new_line_items );
		}	
	}
}

Alternate, pre-submission approach:

add_action( 'gform_pre_submission', 'sliced_quote_add_adjust', 10, 1 );
function sliced_quote_add_adjust( $form ) {
	
	$hidden_adjust_field = 'input_27';	// change this number to the correct field id
	$line_items_field = 'input_20';		// change this too
	
	$adjust = intval( $_POST[$hidden_adjust_field] );
	if ( $adjust > 0 ) {
		$items = $_POST[$line_items_field];
		foreach ( $items as $index => $item ) {
			if ( ( $index - 2 ) % 4 === 0 ) {	// every 4th index, starting with [2]
				$_POST[$line_items_field][$index] = round( $_POST[$line_items_field][$index] * ( 1 + ( $adjust / 100 ) ), 2 );
			}
		}
	}
}

 

PDF Extension

Auto save PDFs

Example code:

add_action( 'publish_sliced_quote', 'auto_save_pdf', 10, 2 );
add_action( 'auto_save_pdf_deferred', 'auto_save_pdf_deferred_function', 10, 2 );
function auto_save_pdf( $id, $post ) {
	// run in background 1 minute from now
	wp_schedule_single_event( time() + 60, 'auto_save_pdf_deferred', array( $id, $post ) );
}
function auto_save_pdf_deferred_function( $id, $post ) {
	if ( $post->post_type === 'sliced_quote' ) {
		$html = Sliced_Shared::request_data( add_query_arg( array( 'create' => 'pdf', 'id' => $id ), sliced_get_the_link( $id ) ) );
		$nonce_start = strpos( $html, 'sliced-print-button" href="' ) + 27;
		$nonce_url = substr( $html, $nonce_start, strpos( $html, '"', $nonce_start ) - $nonce_start );
		$pdf = file_get_contents( html_entity_decode( $nonce_url ) );
		file_put_contents( '/quote-'.$id.'.pdf', $pdf );
	}
}
Change PDF filenames

This will change invoice-X-number.pdf to facture-X-number.pdf, and quote-X-number.pdf to quotation-X-number.pdf:

add_filter( 'sliced_get_filename', 'sliced_custom_filename', 10, 2 );
function sliced_custom_filename( $filename, $id ) {
	$filename = str_replace( 'invoice', 'facture', $filename );
	$filename = str_replace( 'quote', 'quotation', $filename );
	return $filename;
}

***

Another example:

add_filter( 'sliced_get_filename', 'sliced_custom_filename', 10, 2 );
function sliced_custom_filename( $filename, $id ) {
	if ( sliced_get_the_type( $id ) === 'invoice' ) {
		$filename = sliced_get_client_business( $id ) . "-facture-" . sliced_get_invoice_prefix( $id ) . sliced_get_invoice_number( $id ) . "-" . date( "Y-m-d" );
	}
	return $filename;
}
Disable PDF attachment to emails
add_filter( 'sliced_email_attachment', 'sliced_remove_pdf_attachment', 20, 2 );
function sliced_remove_pdf_attachment( $attachment = null, $id ) {
	return null;
}

 

Stripe Payment Gateway

Change 'Pay With Stripe' button label
add_filter( 'sliced_get_gateway_stripe_label', 'sliced_customize_stripe_gateway_label' );
function sliced_customize_stripe_gateway_label( $label ) {
	return 'Pay by Credit Card';
}
Show Stripe logo below payment form