<?php
/*!
* Jetpack CRM
* https://jetpackcrm.com
* V3.0
*
* Copyright 2020 Automattic
*
* Date: 20/02/2019
*/
/* ======================================================
Breaking Checks ( stops direct access )
====================================================== */
defined( 'ZEROBSCRM_PATH' ) || exit( 0 );
/* ======================================================
/ Breaking Checks
====================================================== */
/* ======================================================
Init Func
====================================================== */
function zeroBSCRM_InvoicesMetaboxSetup() {
// main detail
$zeroBS__Metabox_Invoice = new zeroBS__Metabox_Invoice( __FILE__ );
// actions (status + save)
$zeroBS__Metabox_InvoiceActions = new zeroBS__Metabox_InvoiceActions( __FILE__ );
// invoice tags box
$zeroBS__Metabox_InvoiceTags = new zeroBS__Metabox_InvoiceTags( __FILE__ );
// external sources
$zeroBS__Metabox_ExtSource = new zeroBS__Metabox_ExtSource( __FILE__, 'invoice', 'zbs-add-edit-invoice-edit' );
// files
$zeroBS__Metabox_InvoiceFiles = new zeroBS__Metabox_InvoiceFiles( __FILE__ );
}
add_action( 'admin_init', 'zeroBSCRM_InvoicesMetaboxSetup' );
/* ======================================================
/ Init Func
====================================================== */
/* ======================================================
Invoicing Metabox
====================================================== */
class zeroBS__Metabox_Invoice extends zeroBS__Metabox {
// this is for catching 'new' invoice
private $newRecordNeedsRedir = false;
public function __construct( $plugin_file ) {
// set these
$this->objType = 'invoice';
$this->metaboxID = 'zerobs-invoice-edit';
$this->metaboxTitle = __( 'Invoice Information', 'zero-bs-crm' ); // will be headless anyhow
$this->headless = true;
$this->metaboxScreen = 'zbs-add-edit-invoice-edit';
$this->metaboxArea = 'normal';
$this->metaboxLocation = 'high';
$this->saveOrder = 1;
$this->capabilities = array(
'can_hide' => false, // can be hidden
'areas' => array( 'normal' ), // areas can be dragged to - normal side = only areas currently
'can_accept_tabs' => true, // can/can't accept tabs onto it
'can_become_tab' => false, // can be added as tab
'can_minimise' => true, // can be minimised
'can_move' => true, // can be moved
);
// call this
$this->initMetabox();
}
public function html( $invoice, $metabox ) {
// localise ID
$invoiceID = is_array( $invoice ) && isset( $invoice['id'] ) ? (int)$invoice['id'] : -1;
global $zbs;
// Prefill ID and OBJ are added to the #zbs_invoice to aid in prefilling the data (when drawn with JS)
$prefill_id = -1;
$prefill_obj = -1;
$prefill_email = '';
$prefill_name = '';
if ( !empty( $_GET['zbsprefillcust'] ) ) {
$prefill_id = (int)$_GET['zbsprefillcust'];
$prefill_obj = ZBS_TYPE_CONTACT;
$prefill_email = zeroBS_customerEmail( $prefill_id );
$prefill_name = $zbs->DAL->contacts->getContactNameWithFallback( $prefill_id );
}
if ( !empty( $_GET['zbsprefillco'] ) ) {
$prefill_id = (int)$_GET['zbsprefillco'];
$prefill_obj = ZBS_TYPE_COMPANY;
$prefill_email = zeroBS_companyEmail( $prefill_id );
$prefill_name = $zbs->DAL->companies->getCompanyNameEtc( $prefill_id );
}
?>
<?php /* AJAX NONCE */ ?>
<script type="text/javascript">var zbscrmjs_secToken = '<?php echo esc_js( wp_create_nonce( 'zbscrmjs-ajax-nonce' ) ); ?>';</script>
<?php /* END OF NONCE */ ?>
<?php
// AJAX NONCE for inv sending... defunct v3.0?
echo '<input type="hidden" name="inv-ajax-nonce" id="inv-ajax-nonce" value="' . esc_attr( wp_create_nonce( 'inv-ajax-nonce' ) ) . '" />';
// invoice UI divs (loader and canvas)
echo '<div id="zbs_loader"><div class="ui active dimmer inverted"><div class="ui text loader">' . esc_html( __( 'Loading Invoice...', 'zero-bs-crm' ) ) . '</div></div><p></p></div>';
echo "<div id='zbs_invoice' class='zbs_invoice_html_canvas' data-invid='" . esc_attr( $invoiceID ) . "'></div>";
// we pass the hash along the chain here too :)
if ( isset( $invoice['hash'] ) ) {
echo '<input type="hidden" name="zbsi_hash" id="zbsi_hash" value="' . esc_attr( $invoice['hash'] ) . '" />';
}
// custom fields
$customFields = $zbs->DAL->getActiveCustomFields( array( 'objtypeid' => ZBS_TYPE_INVOICE ) );
if ( !is_array( $customFields ) ) {
$customFields = array();
}
// pass data:
?>
<script type="text/javascript">
<?php
if ( $prefill_obj > 0 ) {
echo 'var zbsJS_prefillobjtype = ' . esc_js( $prefill_obj ) . ';';
}
if ( $prefill_id > 0 ) {
echo 'var zbsJS_prefillid = ' . esc_js( $prefill_id ) . ';';
}
echo 'var zbsJS_prefillemail = \'' . esc_js( $prefill_email ) . '\';';
echo 'var zbsJS_prefillname = \'' . esc_js( $prefill_name ) . '\';';
// only sendemail if have active template :)
echo 'var zbsJS_invEmailActive = ' . ( zeroBSCRM_get_email_status( ZBSEMAIL_EMAILINVOICE ) == 1 ? '1' : '-1' ) . ';';
?>
</script>
<div id="zbs-invoice-custom-fields-holder" style="display:none">
<table>
<?php
// here we put the fields out then:
// 1) copy the fields into the UI
foreach ( $customFields as $cfK => $cF ) {
zeroBSCRM_html_editField_for_invoices( $invoice, $cfK, $cF, 'zbsi_' ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
}
?>
</table>
</div>
<?php
// allow hook-ins from invoicing pro etc.
do_action( 'zbs_invoicing_append' );
}
public function save_data( $invoiceID, $invoice ) {
if ( !defined( 'ZBS_OBJ_SAVED' ) ) {
define( 'ZBS_OBJ_SAVED', 1 );
global $zbs;
// check this
if ( empty( $invoiceID ) || $invoiceID < 1 ) {
$invoiceID = -1;
}
// retrieve existing
$existing_invoice = $zbs->DAL->invoices->getInvoice( $invoiceID );
$autoGenAutonumbers = true; // generate if not set :)
$removeEmpties = false; // req for autoGenAutonumbers
$invoice = zeroBS_buildObjArr( $_POST, array(), 'zbsi_', '', $removeEmpties, ZBS_TYPE_INVOICE, $autoGenAutonumbers );
// Use the tag-class function to retrieve any tags so we can add inline.
// Save tags against objid
$invoice['tags'] = zeroBSCRM_tags_retrieveFromPostBag( true, ZBS_TYPE_INVOICE );
// pay via
$invoice['pay_via'] = isset( $_POST['pay_via'] ) && (int)$_POST['pay_via'] === -1 ? -1 : 0;
// new way.. now not limited to 30 lines as now they are stored in [] type array in JS draw
$zbsInvoiceLines = array();
// gather lineitem data from POST
// really this could use a refactor on the JS side so the POST data is structured how we want
foreach ( $_POST['zbsli_itemname'] as $k => $v ) {
$ks = sanitize_text_field( $k ); // at least this
if ( !isset( $zbsInvoiceLines[$ks]['net'] ) ) {
$zbsInvoiceLines[$ks]['net'] = 0.0;
}
$zbsInvoiceLines[$ks]['title'] = sanitize_text_field( $_POST['zbsli_itemname'][$k] );
$zbsInvoiceLines[$ks]['desc'] = sanitize_textarea_field( $_POST['zbsli_itemdes'][$k] );
$zbsInvoiceLines[$ks]['quantity'] = sanitize_text_field( $_POST['zbsli_quan'][$k] );
$zbsInvoiceLines[$ks]['price'] = sanitize_text_field( $_POST['zbsli_price'][$k] );
// calc a net, if have elements
if ( !empty( $zbsInvoiceLines[$ks]['quantity'] ) && !empty( $zbsInvoiceLines[$ks]['price'] ) ) {
$zbsInvoiceLines[$ks]['net'] = $zbsInvoiceLines[$ks]['quantity'] * $zbsInvoiceLines[$ks]['price'];
} else {
// leave net as empty :)
}
// taxes now stored as csv in 'taxes', 'tax' contains a total, but that's not passed by MS UI (yet? not needed?)
$zbsInvoiceLines[$ks]['tax'] = 0;
$zbsInvoiceLines[$ks]['taxes'] = empty( $_POST['zbsli_tax'][$k] ) ? '' : sanitize_text_field( $_POST['zbsli_tax'][$k] );
/* as at 22/2/19, each lineitem here could hold:
'order' => '',
'title' => '',
'desc' => '',
'quantity' => '',
'price' => '',
'currency' => '',
'net' => '',
'discount' => '',
'fee' => '',
'shipping' => '',
'shipping_taxes' => '',
'shipping_tax' => '',
'taxes' => '',
'tax' => '',
'total' => '',
'created' => '',
'lastupdated' => '',
*/
}
if ( count( $zbsInvoiceLines ) > 0 ) {
$invoice['lineitems'] = $zbsInvoiceLines;
}
// other items to update
// hours or quantity switch
if ( !empty( $_POST['invoice-customiser-type'] ) ) {
$invoice['hours_or_quantity'] = $_POST['invoice-customiser-type'] === 'hours' ? 0 : 1;
}
// totals passed
$invoice['discount'] = empty( $_POST['invoice_discount_total'] ) ? 0 : (float)sanitize_text_field( $_POST['invoice_discount_total'] );
$invoice['discount_type'] = empty( $_POST['invoice_discount_type'] ) ? 0 : sanitize_text_field( $_POST['invoice_discount_type'] );
$invoice['shipping'] = empty( $_POST['invoice_postage_total'] ) ? 0 : (float)sanitize_text_field( $_POST['invoice_postage_total'] );
// phpcs:ignore WordPress.Security.NonceVerification.Missing
$invoice['shipping_taxes'] = empty( $_POST['zbsli_tax_ship'] ) ? 0 : (float) sanitize_text_field( wp_unslash( $_POST['zbsli_tax_ship'] ) );
// or shipping_taxes (not set by MS script)
// ... js pass through :o Will be overwritten on php calc on addUpdate, actually, v3.0+
$invoice['total'] = empty( $_POST['zbs-inv-grand-total-store'] ) ? 0 : (float)sanitize_text_field( $_POST['zbs-inv-grand-total-store'] );
// assignments
$zbsInvoiceContact = (int)$_POST['zbs_invoice_contact'];
$invoice['contacts'] = $zbsInvoiceContact > 0 ? array( $zbsInvoiceContact ) : array();
$zbsInvoiceCompany = (int)$_POST['zbs_invoice_company'];
$invoice['companies'] = $zbsInvoiceCompany > 0 ? array( $zbsInvoiceCompany ) : array();
// Later use: 'address_to_objtype'
// other fields
if ( isset( $_POST['invoice_status'] ) ) {
$invoice['status'] = sanitize_text_field( $_POST['invoice_status'] );
}
if ( isset( $_POST['zbsi_logo'] ) ) {
$invoice['logo_url'] = sanitize_url( $_POST['zbsi_logo'] );
}
$ref_type = $zbs->settings->get( 'reftype' );
if ( $invoiceID === -1 && $ref_type === 'autonumber' ) {
$next_number = $zbs->settings->get( 'refnextnum' );
$prefix = $zbs->settings->get( 'refprefix' );
$suffix = $zbs->settings->get( 'refsuffix' );
$invoice['id_override'] = $prefix . $next_number . $suffix;
$next_number++;
$zbs->settings->update( 'refnextnum', $next_number );
} elseif ( isset( $_POST['zbsi_ref'] ) ) {
$invoice['id_override'] = sanitize_text_field( $_POST['zbsi_ref'] );
} else {
// ref should exist
if ( empty( $invoice['id_override'] ) && isset( $existing_invoice['id_override'] ) ) {
// override empty with existing
$invoice['id_override'] = $existing_invoice['id_override'];
}
}
// this needs to be translated to UTS (GMT)
if ( isset( $_POST['zbsi_date'] ) ) {
$invoice['date'] = sanitize_text_field( $_POST['zbsi_date'] );
$invoice['date'] = jpcrm_date_str_to_uts( $invoice['date'] );
}
// due date is now calculated on save, then stored as UTS, if passed this way:
// ... if due_date not set, editor will keep showing "due in x days" select
// ... once set, that'll always show as a datepicker, based on the UTS in due_date
if ( isset( $_POST['zbsi_due'] ) ) {
// days (-1 - 90)
$dueInDays = sanitize_text_field( $_POST['zbsi_due'] );
// got date + due days?
if ( isset( $invoice['date'] ) && $dueInDays >= 0 ) {
// project it forward
$invoice['due_date'] = $invoice['date'] + ( $dueInDays * 60 * 60 * 24 );
}
}
// ... this then catches datepicker-picked dates (if passed by datepicker variant to due_days)
if ( isset( $_POST['zbsi_due_date'] ) ) {
$invoice['due_date'] = sanitize_text_field( $_POST['zbsi_due_date'] );
$invoice['due_date'] = jpcrm_date_str_to_uts( $invoice['due_date'] );
}
// Custom Fields.
/*$customFields = $zbs->DAL->getActiveCustomFields(array('objtypeid' => ZBS_TYPE_INVOICE));
if (!is_array($customFields)) $customFields = array();
foreach ($customFields as $cfK => $cfV){
if (isset($_POST['zbsi_'.$cfK])) $invoice[$cfK] = sanitize_text_field($_POST['zbsi_'.$cfK]);
}*/
// add/update
$addUpdateReturn = $zbs->DAL->invoices->addUpdateInvoice(
array(
'id' => $invoiceID,
'data' => $invoice,
'limitedFields' => -1,
// here we want PHP to calculate the total, tax etc. where we don't calc all the specifics in js
'calculate_totals' => 1,
)
);
// Note: For NEW objs, we make sure a global is set here, that other update funcs can catch
// ... so it's essential this one runs first!
// this is managed in the metabox Class :)
if ( $invoiceID === -1 && !empty( $addUpdateReturn ) && $addUpdateReturn != -1 ) {
$invoiceID = $addUpdateReturn;
global $zbsJustInsertedMetaboxID;
$zbsJustInsertedMetaboxID = $invoiceID;
// set this so it redirs
$this->newRecordNeedsRedir = true;
}
// success?
if ( $addUpdateReturn > 0 ) {
// Update Msg
// this adds an update message which'll go out ahead of any content
// This adds to metabox: $this->updateMessages['update'] = zeroBSCRM_UI2_messageHTML('info olive mini zbs-not-urgent',__('Contact Updated',"zero-bs-crm"),'','address book outline','contactUpdated');
// This adds to edit page
$this->updateMessage();
// catch any non-critical messages
$nonCriticalMessages = $zbs->DAL->getErrors( ZBS_TYPE_INVOICE );
if ( is_array( $nonCriticalMessages ) && count( $nonCriticalMessages ) > 0 ) {
$this->dalNoticeMessage( $nonCriticalMessages );
}
} else {
// fail somehow
$failMessages = $zbs->DAL->getErrors( ZBS_TYPE_INVOICE );
// show msg (retrieved from DAL err stack)
if ( is_array( $failMessages ) && count( $failMessages ) > 0 ) {
$this->dalErrorMessage( $failMessages );
} else {
$this->dalErrorMessage( array( __( 'Insert/Update Failed with general error', 'zero-bs-crm' ) ) );
}
// pass the pre-fill:
global $zbsObjDataPrefill;
$zbsObjDataPrefill = $invoice;
}
}
return $invoice;
}
// This catches 'new' contacts + redirs to right url
public function post_save_data( $objID, $obj ) {
if ( $this->newRecordNeedsRedir ) {
global $zbsJustInsertedMetaboxID;
if ( !empty( $zbsJustInsertedMetaboxID ) && $zbsJustInsertedMetaboxID > 0 ) {
// redir
wp_redirect( jpcrm_esc_link( 'edit', $zbsJustInsertedMetaboxID, $this->objType ) );
exit( 0 );
}
}
}
public function updateMessage() {
global $zbs;
// zbs-not-urgent means it'll auto hide after 1.5s
// genericified from DAL3.0
$msg = zeroBSCRM_UI2_messageHTML( 'info olive mini zbs-not-urgent', $zbs->DAL->typeStr( $zbs->DAL->objTypeKey( $this->objType ) ) . ' ' . __( 'Updated', 'zero-bs-crm' ), '', 'address book outline', 'contactUpdated' );
$zbs->pageMessages[] = $msg;
}
}
/* ======================================================
/ Invoicing Metabox
====================================================== */
/* ======================================================
Invoice Files Metabox
====================================================== */
class zeroBS__Metabox_InvoiceFiles extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
// DAL3 switched for objType $this->postType = 'zerobs_customer';
$this->objType = 'invoice';
$this->metaboxID = 'zerobs-invoice-files';
$this->metaboxTitle = __('Associated Files',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-invoice-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'normal';
$this->metaboxLocation = 'low';
$this->capabilities = array(
'can_hide' => true, // can be hidden
'areas' => array('normal'), // areas can be dragged to - normal side = only areas currently
'can_accept_tabs' => true, // can/can't accept tabs onto it
'can_become_tab' => true, // can be added as tab
'can_minimise' => true // can be minimised
);
// call this
$this->initMetabox();
}
public function html( $invoice, $metabox ) {
global $zbs;
$html = '';
// localise ID
$invoiceID = -1; if (is_array($invoice) && isset($invoice['id'])) $invoiceID = (int)$invoice['id'];
#} retrieve
$zbsFiles = array(); if ($invoiceID > 0) $zbsFiles = zeroBSCRM_files_getFiles('invoice',$invoiceID);
?><table class="form-table wh-metatab wptbp" id="wptbpMetaBoxMainItemFiles">
<?php
// WH only slightly updated this for DAL3 - could do with a cleanup run (contact file edit has more functionality)
#} Any existing
if (is_array($zbsFiles) && count($zbsFiles) > 0){
?><tr class="wh-large"><th><label><?php printf( esc_html( _n( '%s associated file', '%s associated files', count($zbsFiles), 'text-domain' ) ), esc_html( number_format_i18n( count($zbsFiles) ) ) ); ?></label></th>
<td id="zbsFileWrapInvoices">
<?php $fileLineIndx = 1; foreach($zbsFiles as $zbsFile){
$file = zeroBSCRM_files_baseName($zbsFile['file'],isset($zbsFile['priv']));
echo '<div class="zbsFileLine" id="zbsFileLineInvoice'. esc_attr( $fileLineIndx ) .'"><a href="'. esc_url( $zbsFile['url'] ) .'" target="_blank">'. esc_html( $file ) .'</a> (<span class="zbsDelFile" data-delurl="'. esc_attr( $zbsFile['url'] ) .'"><i class="fa fa-trash"></i></span>)</div>';
$fileLineIndx++;
} ?>
</td></tr><?php
}
?>
<?php #adapted from http://code.tutsplus.com/articles/attaching-files-to-your-posts-using-wordpress-custom-meta-boxes-part-1--wp-22291
$html .= '<input type="file" id="zbsobj_file_attachment" name="zbsobj_file_attachment" size="25" class="zbs-dc">';
?><tr class="wh-large"><th><label><?php esc_html_e('Add File',"zero-bs-crm");?>:</label><br />(<?php esc_html_e('Optional',"zero-bs-crm");?>)<br /><?php esc_html_e('Accepted File Types',"zero-bs-crm");?>:<br /><?php echo esc_html( zeroBS_acceptableFileTypeListStr() ); ?></th>
<td><?php
wp_nonce_field(plugin_basename(__FILE__), 'zbsobj_file_attachment_nonce');
echo $html;
?></td></tr>
</table>
<script type="text/javascript">
var zbsInvoicesCurrentlyDeleting = false;
var zbsMetaboxFilesLang = {
'err': '<?php echo esc_html( zeroBSCRM_slashOut(__('Error',"zero-bs-crm")) ); ?>',
'unabletodel' : '<?php echo esc_html( zeroBSCRM_slashOut(__('Unable to delete this file',"zero-bs-crm")) ); ?>',
'viewcontact' : '<?php echo esc_html__( 'View contact', 'zero-bs-crm' ); ?>',
'viewcompany' : '<?php echo esc_html( __( 'View', 'zero-bs-crm' ) . ' ' . jpcrm_label_company() ); ?>',
}
jQuery(function(){
jQuery('.zbsDelFile').on( 'click', function(){
if (!window.zbsInvoicesCurrentlyDeleting){
// blocking
window.zbsInvoicesCurrentlyDeleting = true;
var delUrl = jQuery(this).attr('data-delurl');
var lineIDtoRemove = jQuery(this).closest('.zbsFileLine').attr('id');
if (typeof delUrl != "undefined" && delUrl != ''){
// postbag!
var data = {
'action': 'delFile',
'zbsfType': 'invoices',
'zbsDel': delUrl, // could be csv, never used though
'zbsCID': <?php echo esc_html( $invoiceID ); ?>,
'sec': window.zbscrmjs_secToken
};
// Send it Pat :D
jQuery.ajax({
type: "POST",
url: ajaxurl, // admin side is just ajaxurl not wptbpAJAX.ajaxurl,
"data": data,
dataType: 'json',
timeout: 20000,
success: function(response) {
// visually remove
jQuery('#' + lineIDtoRemove).remove();
// file deletion errors, show msg:
if (typeof response.errors != "undefined" && response.errors.length > 0){
jQuery.each(response.errors,function(ind,ele){
jQuery('#zerobs-invoice-files-box').append('<div class="ui warning message" style="margin-top:10px;">' + ele + '</div>');
});
}
},
error: function(response){
jQuery('#zerobs-invoice-files-box').append('<div class="ui warning message" style="margin-top:10px;"><strong>' + window.zbsMetaboxFilesLang.err + ':</strong> ' + window.zbsMetaboxFilesLang.unabletodel + '</div>');
}
});
}
window.zbsInvoicesCurrentlyDeleting = false;
} // / blocking
});
});
</script><?php
}
public function save_data( $invoiceID, $invoice ) {
global $zbsobj_justUploadedObjFile;
$id = $invoiceID;
if(!empty($_FILES['zbsobj_file_attachment']['name']) &&
(!isset($zbsobj_justUploadedObjFile) ||
(isset($zbsobj_justUploadedObjFile) && $zbsobj_justUploadedObjFile != $_FILES['zbsobj_file_attachment']['name'])
)
) {
/* --- security verification --- */
if(!wp_verify_nonce($_POST['zbsobj_file_attachment_nonce'], plugin_basename(__FILE__))) {
return $id;
} // end if
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $id;
} // end if
if (!zeroBSCRM_permsInvoices()){
return $id;
}
/* - end security verification - */
// Blocking repeat-upload bug
$zbsobj_justUploadedObjFile = $_FILES['zbsobj_file_attachment']['name'];
// verify file extension and mime type
if ( jpcrm_file_check_mime_extension( $_FILES['zbsobj_file_attachment'] ) ){
$invoice_dir_info = jpcrm_storage_dir_info_for_invoices( $invoiceID );
$upload = jpcrm_save_admin_upload_to_folder( 'zbsobj_file_attachment', $invoice_dir_info['files'] );
if ( isset( $upload['error'] ) && $upload['error'] != 0 ) {
wp_die('There was an error uploading your file. The error is: ' . esc_html( $upload['error'] ) );
} else {
// w mod - adds to array :)
$zbsFiles = zeroBSCRM_files_getFiles('invoice',$invoiceID);
if (is_array($zbsFiles)){
//add it
$zbsFiles[] = $upload;
} else {
// first
$zbsFiles = array($upload);
}
// update
zeroBSCRM_files_updateFiles('invoice',$invoiceID, $zbsFiles);
// Fire any 'post-upload-processing' (e.g. CPP makes thumbnails of pdf, jpg, etc.)
// not req invoicing: do_action('zbs_post_upload_contact',$upload);
}
} else {
wp_die("The file type that you've uploaded is not an accepted file format.");
}
}
return $invoice;
}
}
/* ======================================================
/ Attach files to invoice metabox
====================================================== */
/* ======================================================
Invoicing Metabox Helpers
====================================================== */
function zeroBS__InvoicePro(){
$upTitle = __('Want more from invoicing?',"zero-bs-crm");
$upDesc = __('Accept Payments Online with Invoicing Pro.',"zero-bs-crm");
$upButton = __('Buy Now',"zero-bs-crm");
$upTarget = "https://jetpackcrm.com/product/invoicing-pro/";
echo zeroBSCRM_UI2_squareFeedbackUpsell($upTitle,$upDesc,$upButton,$upTarget);
}
/* ======================================================
/ Invoicing Metabox Helpers
====================================================== */
/* ======================================================
Create Tags Box
====================================================== */
class zeroBS__Metabox_InvoiceTags extends zeroBS__Metabox_Tags{
public function __construct( $plugin_file ) {
$this->objTypeID = ZBS_TYPE_INVOICE;
// DAL3 switched for objType $this->postType = 'zerobs_customer';
$this->objType = 'invoice';
$this->metaboxID = 'zerobs-invoice-tags';
$this->metaboxTitle = __('Invoice Tags',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-invoice-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
$this->showSuggestions = true;
$this->capabilities = array(
'can_hide' => true, // can be hidden
'areas' => array('side'), // areas can be dragged to - normal side = only areas currently
'can_accept_tabs' => false, // can/can't accept tabs onto it
'can_become_tab' => false, // can be added as tab
'can_minimise' => true // can be minimised
);
// call this
$this->initMetabox();
}
// html + save dealt with by parent class :)
}
/* ======================================================
/ Create Tags Box
====================================================== */
/* ======================================================
Invoice Actions Metabox
====================================================== */
class zeroBS__Metabox_InvoiceActions extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
// set these
$this->objType = 'invoice';
$this->metaboxID = 'zerobs-invoice-actions';
$this->metaboxTitle = __('Invoice Actions','zero-bs-crm'); // will be headless anyhow
$this->headless = true;
$this->metaboxScreen = 'zbs-add-edit-invoice-edit';
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
$this->saveOrder = 1;
$this->capabilities = array(
'can_hide' => false, // can be hidden
'areas' => array('side'), // areas can be dragged to - normal side = only areas currently
'can_accept_tabs' => true, // can/can't accept tabs onto it
'can_become_tab' => false, // can be added as tab
'can_minimise' => true, // can be minimised
'can_move' => true // can be moved
);
// call this
$this->initMetabox();
}
public function html( $invoice, $metabox ) {
?><div class="zbs-generic-save-wrap">
<div class="ui medium dividing header"><i class="save icon"></i> <?php esc_html_e('Invoice Actions','zero-bs-crm'); ?></div>
<?php
// localise ID & content
$invoiceID = -1; if (is_array($invoice) && isset($invoice['id'])) $invoiceID = (int)$invoice['id'];
if ($invoiceID > 0){ // existing
?>
<?php do_action('zbs_invpro_itemlink'); ?>
<div class="clear"></div>
<div class="zbs-invoice-actions-bottom zbs-objedit-actions-bottom">
<button class="ui button black" type="button" id="zbs-edit-save"><?php esc_html_e( 'Update', 'zero-bs-crm' ); ?> <?php esc_html_e( 'Invoice', 'zero-bs-crm' ); ?></button>
<?php
#} Quick ver of this: http://themeflection.com/replace-wordpress-submit-meta-box/
?><div id="zbs-invoice-actions-delete" class="zbs-objedit-actions-delete"><?php
// for now just check if can modify invs, later better, granular perms.
if ( zeroBSCRM_permsInvoices() ) {
/* WP Deletion:
no trash (at least v3.0)
if ( !EMPTY_TRASH_DAYS )
$delete_text = __('Delete Permanently', "zero-bs-crm");
else
$delete_text = __('Move to Trash', "zero-bs-crm");
?><a class="submitdelete deletion" href="<?php echo get_delete_post_link($post->ID); ?>"><?php echo $delete_text; ?></a><?php
*/
$delete_text = __('Delete Permanently', "zero-bs-crm");
?><a class="submitdelete deletion" href="<?php echo jpcrm_esc_link( 'delete', $invoiceID, 'invoice' ); ?>"><?php echo esc_html( $delete_text ); ?></a><?php
} //if ?>
</div>
<div class='clear'></div>
</div>
<?php
} else {
?>
<?php do_action('zbs_invpro_itemlink'); ?>
<button class="ui button black" type="button" id="zbs-edit-save"><?php esc_html_e( 'Save', 'zero-bs-crm' ); ?> <?php esc_html_e( 'Invoice', 'zero-bs-crm' ); ?></button>
<?php
#} If it's a new post
#} Gross hide :/
}
?></div><?php // / .zbs-generic-save-wrap
}
// saved via main metabox
}