<?php
/*!
* Jetpack CRM
* https://jetpackcrm.com
* V3.0
*
* Copyright 2020 Automattic
*
* Date: 20/02/2019
*/
defined( 'ZEROBSCRM_PATH' ) || exit( 0 );
/* ======================================================
Init Func
====================================================== */
function zeroBSCRM_CustomersMetaboxSetup(){
if (zeroBSCRM_is_customer_edit_page()){
// Customer Fields
$zeroBS__Metabox_Contact = new zeroBS__Metabox_Contact( __FILE__ );
// Actions
$zeroBS__Metabox_ContactActions = new zeroBS__Metabox_ContactActions( __FILE__ );
// Logs
// req. for custom log types
zeroBSCRM_setupLogTypes();
// metabox
$zeroBS__Metabox_ContactLogs = new zeroBS__Metabox_ContactLogs( __FILE__ );
// Tags
$zeroBS__Metabox_ContactTags = new zeroBS__Metabox_ContactTags( __FILE__ );
// External sources
//$zeroBS__Metabox_ContactExternalSources = new zeroBS__Metabox_ContactExternalSources( __FILE__ );
$zeroBS__Metabox_ExtSource = new zeroBS__Metabox_ExtSource( __FILE__, 'contact','zbs-add-edit-contact-edit');
// Quotes, Invs, Trans
// Don't need now we have singular :)
//$zeroBS__MetaboxAssociated = new zeroBS__MetaboxAssociated( __FILE__ );
// Client Portal access
if (zeroBSCRM_isExtensionInstalled('portal')) $zeroBS__Metabox_ContactPortal = new zeroBS__Metabox_ContactPortal( __FILE__ );
// Customer File Attachments
// Custom file attachment boxes
if (zeroBSCRM_is_customer_edit_page()){
/* old way
$settings = zeroBSCRM_getSetting('customfields'); $cfbInd = 1;
if (isset($settings['customersfiles']) && is_array($settings['customersfiles']) && count($settings['customersfiles']) > 0) foreach ($settings['customersfiles'] as $cfb){
$cfbName = ''; if (isset($cfb[0])) $cfbName = $cfb[0];
//add_meta_box('zerobs-customer-files-'.$cfbInd, $cfbName, 'zeroBS__MetaboxFilesCustom', 'zerobs_customer', 'normal', 'low',$cfbName);
$zeroBS__Metabox_ContactCustomFiles = new zeroBS__Metabox_ContactCustomFiles( __FILE__, 'zerobs-customer-files-'.$cfbInd , $cfbName);
$cfbInd++;
} */
$fileSlots = zeroBSCRM_fileSlots_getFileSlots();
if (count($fileSlots) > 0) foreach ($fileSlots as $fs){
$zeroBS__Metabox_ContactCustomFiles = new zeroBS__Metabox_ContactCustomFiles( __FILE__, 'zerobs-customer-files-'.$fs['key'] , $fs['name']);
}
}
#} Social
if (zeroBSCRM_getSetting('usesocial') == "1") $zeroBS__Metabox_ContactSocial = new zeroBS__Metabox_ContactSocial( __FILE__ );
#} AKA
if (zeroBSCRM_getSetting('useaka') == "1") $zeroBS__Metabox_ContactAKA = new zeroBS__Metabox_ContactAKA( __FILE__ );
#} Ownership
if (zeroBSCRM_getSetting('perusercustomers') == "1") $zeroBS__Metabox_Ownership = new zeroBS__Metabox_Ownership( __FILE__, ZBS_TYPE_CONTACT);
#} B2B mode (assign to co)
if (zeroBSCRM_getSetting('companylevelcustomers') == "1") $zeroBS__Metabox_ContactCompany = new zeroBS__Metabox_ContactCompany( __FILE__ );
}
// Activity box on view page
if ( zeroBSCRM_is_customer_view_page() ) {
$zeroBS__Metabox_Contact_Activity = new zeroBS__Metabox_Contact_Activity( __FILE__ );
if ( zeroBSCRM_isExtensionInstalled( 'portal' ) ) {
$zeroBS__Metabox_ContactPortal = new zeroBS__Metabox_ContactPortal( __FILE__, 'zbs-view-contact' );
}
}
}
add_action( 'admin_init', 'zeroBSCRM_CustomersMetaboxSetup' );
/* ======================================================
/ Init Func
====================================================== */
/* ======================================================
Declare Globals
====================================================== */
#} Used throughout
// Don't know who added this, but GLOBALS are out of scope here
//global $zbsCustomerFields,$zbsCustomerQuoteFields,$zbsCustomerInvoiceFields;
/* ======================================================
/ Declare Globals
====================================================== */
// PerfTest: zeroBSCRM_performanceTest_startTimer('custmetabox');
/* ======================================================
Customer Metabox
====================================================== */
class zeroBS__Metabox_Contact extends zeroBS__Metabox{
// this is for catching 'new' contacts
private $newRecordNeedsRedir = false;
public function __construct( $plugin_file ) {
// set these
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-edit';
$this->metaboxTitle = __('Contact Details',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$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();
}
/**
* This method generates HTML content for contact and metadata.
*
* It contains a series of operations to format and display contact data
* and metadata according to the parameters. This includes information retrieval,
* settings configuration, field hiding, address display and others.
*
* @param array $contact An associative array containing contact details.
* @param array $metabox Metabox information.
*
* @return void
*/
public function html( $contact, $metabox ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
global $zbs; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
global $zbsContactEditing; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
global $zbsCustomerFields; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
if ( ! isset( $zbsContactEditing ) && isset( $contact['id'] ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$customer = zeroBS_getCustomer( $contact['id'], false, false, false );
$zbsContactEditing = $customer; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
} else {
$customer = $zbsContactEditing; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
}
$fields_to_hide = $zbs->settings->get( 'fieldhides' );
$show_id = (int) $zbs->settings->get( 'showid' );
$fields = $zbsCustomerFields; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$show_addresses = zeroBSCRM_getSetting( 'showaddress' );
$show_second_address = (int) zeroBSCRM_getSetting( 'secondaddress' );
$show_country_fields = zeroBSCRM_getSetting( 'countries' );
$second_address_label = zeroBSCRM_getSetting( 'secondaddresslabel' );
if ( empty( $second_address_label ) ) {
$second_address_label = __( 'Second Address', 'zero-bs-crm' );
}
?>
<script type="text/javascript">var zbscrmjs_secToken = '<?php echo esc_js( wp_create_nonce( 'zbscrmjs-ajax-nonce' ) ); ?>';</script>
<?php
if ( gettype( $customer ) !== 'array' ) {
echo '<input type="hidden" name="zbscrm_newcustomer" value="1" />';
}
?>
<div>
<div class="jpcrm-form-grid" id="wptbpMetaBoxMainItem">
<?php
$avatar_mode = (int) zeroBSCRM_getSetting( 'avatarmode' );
if ( $avatar_mode === 2 ) :
?>
<div class="jpcrm-form-group jpcrm-form-group-span-2">
<label class="jpcrm-form-label"><?php esc_html_e( 'Profile Picture', 'zero-bs-crm' ); ?>:</label>
<?php
$avatar_url = isset( $contact['id'] ) ? $zbs->DAL->contacts->getContactAvatar( $contact['id'] ) : zeroBSCRM_getDefaultContactAvatar(); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase, WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$empty_avatar_url = zeroBSCRM_getDefaultContactAvatar();
?>
<div class="zbs-text-input">
<div class="jpcrm-customer-profile-picture-container" style="margin-right:10px;">
<img src="<?php echo esc_attr( $avatar_url ); ?>" id="profile-picture-img" class="jpcrm-customer-profile-picture" />
<img src="<?php echo esc_attr( $empty_avatar_url ); ?>" id="empty-profile-picture" class="jpcrm-customer-profile-picture" style="display:none;" />
<br />
<label for="zbsc_profile-picture-file" class="jpcrm-customer-file-upload">
<?php esc_html_e( 'Change Picture', 'zero-bs-crm' ); ?>
<input id="zbsc_profile-picture-file" type="file" name="zbsc_profile-picture-file" class="jpcrm-customer-input-file"/>
</label>
<label id="zbsc_remove-profile-picture-button" class="jpcrm-customer-file-upload-remove">
<?php esc_html_e( 'Remove', 'zero-bs-crm' ); ?>
<input type="hidden" id="zbsc_remove-profile-picture" name="zbsc_remove-profile-picture" value="0" />
</label>
</div>
</div>
</div>
<?php
endif;
if ( $show_id === 1 && isset( $contact['id'] ) && ! empty( $contact['id'] ) ) :
?>
<div class="jpcrm-form-group">
<label class="jpcrm-form-label"><?php esc_html_e( 'Contact ID', 'zero-bs-crm' ); ?>:</label>
<b>#<?php echo isset( $contact['id'] ) ? esc_html( $contact['id'] ) : ''; ?></b>
</div>
<div class="jpcrm-form-group">
</div>
<?php
endif;
global $zbsFieldsEnabled; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
if ( $show_second_address === 1 ) {
$zbsFieldsEnabled['secondaddress'] = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
}
$field_group = '';
foreach ( $fields as $field_key => $field_value ) {
$show_field = ! isset( $field_value['opt'] ) || isset( $zbsFieldsEnabled[ $field_value['opt'] ] ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$show_field = isset( $fields_to_hide['customer'] )
&& is_array( $fields_to_hide['customer'] )
&& in_array( $field_key, $fields_to_hide['customer'] ) // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
? false
: $show_field;
$show_field = isset( $field_value[0] )
&& 'selectcountry' === $field_value[0]
&& 0 === $show_country_fields
? false
: $show_field;
if ( isset( $field_value['area'] ) && $field_value['area'] !== '' ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
if ( $show_addresses !== 1 ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
continue;
} elseif ( $field_group === '' ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
echo '<div class="jpcrm-form-grid" style="padding:0;grid-template-columns: 1fr;">';
echo '<div class="jpcrm-form-group"><label>';
echo esc_html__( $field_value['area'], 'zero-bs-crm' ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase, WordPress.WP.I18n.NonSingularStringLiteralText
echo '</label></div>';
} elseif ( $field_group !== $field_value['area'] ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
echo '</div>';
echo '<div class="jpcrm-form-grid" style="padding:0;grid-template-columns: 1fr;">';
echo '<div class="jpcrm-form-group"><label>';
echo $show_field ? esc_html( $second_address_label ) : '';
echo '</label></div>';
}
$field_group = $field_value['area']; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase, WordPress.WP.I18n.NonSingularStringLiteralText
}
if ( $field_group !== '' && ( ! isset( $field_value['area'] ) || $field_value['area'] === '' ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$field_group = ''; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
echo '</div>';
echo '<div class="jpcrm-form-group jpcrm-form-group-span-2"> </div>';
}
if ( $show_field ) {
if ( isset( $field_value[0] ) ) {
if ( $field_group === 'Second Address' ) {
$field_value[1] = str_replace( ' (' . $second_address_label . ')', '', $field_value[1] );
}
zeroBSCRM_html_editField( $customer, $field_key, $field_value, 'zbsc_' );
}
}
}
?>
</div>
</div>
<?php
}
public function save_data( $contact_id, $contact ) {
if (!defined('ZBS_C_SAVED')){
// debug if (get_current_user_id() == 12) echo 'FIRING<br>';
define('ZBS_C_SAVED',1);
global $zbs;
// check this
if (empty($contact_id) || $contact_id < 1) $contact_id = -1;
$dataArr = zeroBS_buildContactMeta($_POST);
// Use the tag-class function to retrieve any tags so we can add inline.
// Save tags against objid
$dataArr['tags'] = zeroBSCRM_tags_retrieveFromPostBag(true,ZBS_TYPE_CONTACT);
// owner - saved here now, rather than ownership box, to allow for pre-hook update. (as tags)
$owner = -1;
// Only allow an existing contact to change owners if they have permission to do so.
if ( $contact_id > -1 ) {
$can_edit_all_contacts = current_user_can( 'admin_zerobs_customers' ) && $zbs->settings->get( 'perusercustomers' ) == 0; // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual,WordPress.WP.Capabilities.Unknown -- capability was defined in ZeroBSCRM.Permissions.php
$can_give_ownership = $zbs->settings->get( 'usercangiveownership' ) == 1; // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- also above, there is the chance the numbers could be strings here, as expected elsewhere in the plugin.
$can_change_owner = ( $can_give_ownership || current_user_can( 'manage_options' ) || $can_edit_all_contacts );
if ( $can_change_owner ) {
if ( isset( $_POST['zerobscrm-owner'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- todo - noted in zero-bs-crm 2457.
$potential_owner = (int) sanitize_text_field( wp_unslash( $_POST['zerobscrm-owner'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- todo - noted in zero-bs-crm 2457.
if ( $potential_owner > 0 ) {
$owner = $potential_owner;
}
}
} else {
$owner = (int) $zbs->DAL->contacts->getContactOwner( $contact_id ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
}
// now we check whether a user with this email already exists (separate to this contact id), so we can warn them
// ... that it wont have changed the email
if ( !empty( $dataArr['email'] ) ) {
if ( !zeroBSCRM_validateEmail( $dataArr['email'] ) ) {
$this->update_invalid_email( $dataArr['email'] );
$dataArr['email'] = '';
} else {
$potentialID = zeroBS_getCustomerIDWithEmail( $dataArr['email'] );
if ( !empty( $potentialID ) && $potentialID != $contact_id ) {
// no go.
$this->updateEmailDupeMessage( $potentialID );
// unset email change (leave as was)
$dataArr['email'] = zeroBS_customerEmail( $contact_id );
}
}
}
// phpcs:disable WordPress.NamingConventions.ValidVariableName -- to be refactored.
// We have to explicitly retrieve the avatar from the DB.
$dataArr['avatar'] = ( $contact_id !== -1 ) ? $zbs->DAL->contacts->getContactAvatar( $contact_id ) : '';
//phpcs:enable WordPress.NamingConventions.ValidVariableName
// make a copy for IA below (just fields)
$contactData = $dataArr;
// Company assignment?
if (isset($_POST['zbs_company'])) $dataArr['companies'] = array((int)sanitize_text_field($_POST['zbs_company']));
// Stripslashes
// This avoids us adding `O\'toole ltd' into the db. see #1107
// ...this is more sensitive than using zeroBSCRM_stripSlashesFromArr
// in the long term it may make more sense to stripslashes pre insert/update in the DAL
// in the case of contacts, there are no core fields which will be broken by stripslashes at this time (4.0.11)
$data_array = $dataArr;
foreach ($dataArr as $key => $val){
// op strings
$value = $val;
if ( is_string( $value ) ) $value = stripslashes( $value );
// pass into final array
$data_array[$key] = $value;
}
// add update directly
$addUpdateReturn = $zbs->DAL->contacts->addUpdateContact(array(
'id' => $contact_id,
'owner' => $owner,
'data' => $data_array,
'limitedFields' => -1,
/* array(
'email' => $userDeets['email'], // Unique Field !
'status' => $userDeets['status'],
'prefix' => $userDeets['prefix'],
'fname' => $userDeets['fname'],
'lname' => $userDeets['lname'],
'addr1' => $userDeets['addr1'],
'addr2' => $userDeets['addr2'],
'city' => $userDeets['city'],
'county' => $userDeets['county'],
'country' => $userDeets['country'],
'postcode' => $userDeets['postcode'],
'secaddr1' => $userDeets['secaddr_addr1'],
'secaddr2' => $userDeets['secaddr_addr2'],
'seccity' => $userDeets['secaddr_city'],
'seccounty' => $userDeets['secaddr_county'],
'seccountry' => $userDeets['secaddr_country'],
'secpostcode' => $userDeets['secaddr_postcode'],
'hometel' => $userDeets['hometel'],
'worktel' => $userDeets['worktel'],
'mobtel' => $userDeets['mobtel'],
'wpid' => -1,
'avatar' => $avatarURL,
// Note Custom fields may be passed here, but will not have defaults so check isset()
'tags' => $tags,
// wh added for later use.
'lastcontacted' => $lastcontacted,
'companies' => $companies // array of co id's :)
) */
));
// Note: For NEW contacts, 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 ($contact_id == -1 && !empty($addUpdateReturn) && $addUpdateReturn != -1) {
$contact_id = $addUpdateReturn;
global $zbsJustInsertedMetaboxID; $zbsJustInsertedMetaboxID = $contact_id;
// set this so it redirs
$this->newRecordNeedsRedir = true;
}
// success?
if ($addUpdateReturn != -1 && $addUpdateReturn > 0){
$this->save_profile_picture( $contact_id, $contact );
// 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( $this->newRecordNeedsRedir );
// catch any non-critical messages
$nonCriticalMessages = $zbs->DAL->getErrors(ZBS_TYPE_CONTACT);
if (is_array($nonCriticalMessages) && count($nonCriticalMessages) > 0) $this->dalNoticeMessage($nonCriticalMessages);
} else {
// fail somehow
$failMessages = $zbs->DAL->getErrors(ZBS_TYPE_CONTACT);
// 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 = $dataArr;
}
}
return $contact;
}
/*
* Saves the profile picture
*/
public function save_profile_picture( $contact_id, $crm_contact ) {
global $zbs;
$contact_dir_info = jpcrm_storage_dir_info_for_contact( $contact_id );
$field_key = 'jpcrm-profile-picture';
$is_remove_flag_set = isset( $_POST['zbsc_remove-profile-picture'] ) && $_POST['zbsc_remove-profile-picture'] == '1';
$remove_old_avatar = false;
$has_new_avatar_file =
isset( $_FILES['zbsc_profile-picture-file'] )
&& empty( $_FILES['zbsc_profile-picture-file']['error'] )
&& is_uploaded_file( $_FILES['zbsc_profile-picture-file']['tmp_name'] );
if ( $is_remove_flag_set ) {
$zbs->DAL->contacts->addUpdateContact( array(
'id' => $contact_id,
'limitedFields' => array(
array(
'key' => 'zbsc_avatar',
'val' => '',
'type' => '%s'
)
)
));
$remove_old_avatar = true;
} else if ( $has_new_avatar_file ) {
// verify image file type
$allowed_image_types = array('image/jpeg' => 'jpg', 'image/jpg' => 'jpg', 'image/gif' => 'gif', 'image/png' => 'png');
$allowed_file_extensions = array( '.jpg', '.jpeg', '.gif', '.png' );
$allowed_mime_types = array( 'image/jpeg','image/jpg', 'image/gif', 'image/png' );
if ( !jpcrm_file_check_mime_extension( $_FILES['zbsc_profile-picture-file'], $allowed_file_extensions, $allowed_mime_types ) ){
$this->dalErrorMessage ( array( __( 'Error: Profile Picture only accepts jpg, png, and gif images!', 'zero-bs-crm' ) ) );
return;
}
if ( $contact_dir_info === false ) {
$this->dalErrorMessage ( array( __( 'Error while retrieving the contact\'s folder.', 'zero-bs-crm' ) ) );
return;
}
$avatar_path = $contact_dir_info['avatar']['path'];
$contact_folder_exists = jpcrm_create_and_secure_dir_from_external_access( $avatar_path, false );
if ( ! $contact_folder_exists ) {
$this->dalErrorMessage ( array( __( 'There was an error creating the profile picture directory.', 'zero-bs-crm' ) ) );
return;
}
$zbs->load_encryption();
$avatar_filename = sprintf(
'avatar_%s.%s',
$zbs->encryption->get_rand_hex( 10 ),
$allowed_image_types[ $_FILES['zbsc_profile-picture-file']['type'] ] // extension for this filetype
);
if (
! file_exists( $avatar_path . '/' . $avatar_filename )
&& move_uploaded_file( $_FILES['zbsc_profile-picture-file']['tmp_name'], $avatar_path . '/' . $avatar_filename)
) {
$zbs->DAL->contacts->addUpdateContact( array(
'id' => $contact_id,
'limitedFields' => array(
array(
'key' => 'zbsc_avatar',
'val' => $contact_dir_info['avatar']['url'] . '/' . $avatar_filename,
'type' => '%s'
)
)
));
$remove_old_avatar = true;
} else {
$this->dalErrorMessage ( array( __( 'There was an error updating the profile picture.', 'zero-bs-crm' ) ) );
}
}
if ( $remove_old_avatar && ! empty( $crm_contact['avatar'] ) ) {
$previous_avatar_full_path = $contact_dir_info['avatar']['path'] . '/' . basename( $crm_contact['avatar'] );
if ( file_exists( $previous_avatar_full_path ) ) {
unlink( $previous_avatar_full_path );
}
}
}
// This catches 'new' contacts + redirs to right url
public function post_save_data($objID,$obj){
if ($this->newRecordNeedsRedir){
global $zbs, $zbsJustInsertedMetaboxID;
if (!empty($zbsJustInsertedMetaboxID) && $zbsJustInsertedMetaboxID > 0){
// redir
$zbs->new_record_edit_redirect( 'zerobs_customer', $zbsJustInsertedMetaboxID );
}
}
}
public function updateMessage( $created = false ){
$text = $created ? __('Contact Created',"zero-bs-crm") : __('Contact Updated',"zero-bs-crm");
// zbs-not-urgent means it'll auto hide after 1.5s
$msg = zeroBSCRM_UI2_messageHTML('info olive mini zbs-not-urgent',$text,'','address book outline','contactUpdated');
// quick + dirty
global $zbs;
$zbs->pageMessages[] = $msg;
}
public function update_invalid_email( $invalid_email ) {
global $zbs;
$msg = zeroBSCRM_UI2_messageHTML(
'info orange mini',
sprintf( __( 'The contact email specified (%s) is not valid.', 'zero-bs-crm' ), $invalid_email ),
'',
'address book outline',
'contactUpdated'
);
$zbs->pageMessages[] = $msg;
}
public function updateEmailDupeMessage($otherContactID=-1){
$viewHTML = ' <a href="'.jpcrm_esc_link('view',$otherContactID,'zerobs_customer').'" target="_blank">'.__('View Contact','zero-bs-crm').'</a>';
$msg = zeroBSCRM_UI2_messageHTML('info orange mini',__('Contact email could not be updated because a contact already exists with this email address.',"zero-bs-crm").$viewHTML,'','address book outline','contactUpdated');
// quick + dirty
global $zbs;
$zbs->pageMessages[] = $msg;
}
}
/* ======================================================
/ Customer Metabox
====================================================== */
/* ======================================================
Create Actions Box
====================================================== */
class zeroBS__Metabox_ContactActions extends zeroBS__Metabox{
private $actions = array();
public function __construct( $plugin_file ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-actions';
$this->metaboxTitle = __('Contact Actions',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
$this->headless = true;
$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' => false, // can/can't accept tabs onto it
'can_become_tab' => false, // can be added as tab
'can_minimise' => false, // can be minimised
'can_move' => false // can be moved
);
// hacky id check for now:
if (isset($_GET['zbsid']) && !empty($_GET['zbsid'])) {
$id = (int)sanitize_text_field($_GET['zbsid']);
// call this, if actions
$this->actions = zeroBS_contact_actions($id);
}
$this->initMetabox();
}
public function html( $contact, $metabox ) {
$avatarMode = zeroBSCRM_getSetting( 'avatarmode' );
$avatarStr = '';
$is_new_contact = count( $this->actions ) > 0 ? false : true;
if ( $avatarMode !== 3 ) {
$cID = -1; if (is_array($contact) && isset($contact['id'])) $cID = (int)$contact['id'];
$avatarStr = zeroBS_customerAvatarHTML($cID);
}
?>
<div class="zbs-generic-save-wrap">
<div class="ui medium dividing header"><i class="save icon"></i> <?php esc_html_e( 'Contact Actions', 'zero-bs-crm' ); ?></div>
<div class="clear"></div>
<?php
# https://codepen.io/kyleshockey/pen/bdeLrE
if ( ! $is_new_contact ) {
?>
<script type="text/javascript">
var zbsContactAvatarLang = {
'upload': '<?php esc_html_e("Upload Image","zero-bs-crm");?>',
};
</script>
<div class="action-wrap">
<div class="ui dropdown jpcrm-button white-bg jpcrm-dropdown"><?php esc_html_e( 'Contact Actions', 'zero-bs-crm' ); ?><i class="fa fa-angle-down"></i>
<div class="menu" style="margin: 4px;">
<?php foreach ($this->actions as $actKey => $action){
// filter out 'edit' as on that page :)
if ($actKey != 'edit'){
?>
<div class="item zbs-contact-action" id="zbs-contact-action-<?php echo esc_attr( $actKey ); ?>"<?php
// if url isset, pass that data-action, otherwise leave for js to attach to
if (isset($action['url']) && !empty($action['url'])){
?> data-action="<?php if (isset($action['url'])) echo 'url'; ?>" data-url="<?php if (isset($action['url'])) echo esc_attr( $action['url'] ); ?>"<?php
}
// got extra attributes?
if (isset($action['extraattr']) && is_array($action['extraattr'])){
// dump extra attr into item
foreach ($action['extraattr'] as $k => $v){
echo ' data-'. esc_attr( $k ) .'="'. esc_attr( $v ) .'"';
}
} ?>>
<?php
// got ico?
if (isset($action['ico'])) echo '<i class="'. esc_attr( $action['ico'] ) .'"></i>';
// got text?
if (isset($action['label'])) echo esc_html( $action['label'] );
?>
</div>
<?php }
}?>
</div>
</div>
</div>
<script type="text/javascript">
jQuery(function(){
// actions drop down
jQuery('.ui.dropdown').dropdown();
// action items
jQuery('.zbs-contact-action').off('click').on( 'click', function(){
// get action type (at launch, only url)
var actionType = jQuery(this).attr('data-action');
if (typeof actionType != "undefined") switch (actionType){
case 'url':
var u = jQuery(this).attr('data-url');
if (typeof u != "undefined" && u != '') window.location = u;
break;
}
});
});
</script>
<?php }
?>
<div class="zbs-contact-actions-bottom zbs-objedit-actions-bottom">
<button class="jpcrm-button" type="button" id="zbs-edit-save"><?php $is_new_contact ? esc_html_e( 'Save', 'zero-bs-crm' ) : esc_html_e( 'Update', 'zero-bs-crm' ); ?> <?php esc_html_e( 'Contact', 'zero-bs-crm' ); ?></button>
<div class='clear'></div>
</div>
<?php
}
public function save_data( $contact_id, $contact ) {
// avatar changes saved by main contact save func (field editor), allowing for all-in-one creation/updates, see #AVATARSAVE
return $contact;
}
}
/* ======================================================
/ Create Actions Box
====================================================== */
/* ======================================================
Attach (custom) fileboxes to customer metabox
====================================================== */
class zeroBS__Metabox_ContactCustomFiles extends zeroBS__Metabox{
public function __construct( $plugin_file, $idOverride='',$titleOverride='' ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-custom-files';
$this->metaboxTitle = __('Other Files',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-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' => false, // can/can't accept tabs onto it
'can_become_tab' => true, // can be added as tab
'can_minimise' => true // can be minimised
);
if (!empty($idOverride)) $this->metaboxID = $idOverride;
if (!empty($titleOverride)) $this->metaboxTitle = __($titleOverride,"zero-bs-crm");
// call this
$this->initMetabox();
}
public function html( $contact, $args ) {
global $zbs;
$html = '';
$thisFileSlotName = ''; if (isset($args['title'])) $thisFileSlotName = $args['title'];
$filePerma = ''; if (isset($thisFileSlotName) && !empty($thisFileSlotName)) {
//$filePerma = strtolower(str_replace(' ','_',str_replace('.','_',substr($thisFileSlotName,0,20))));
$filePerma = $zbs->DAL->makeSlug($thisFileSlotName);
}
// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$zbsFiles = array();
if ( $contact ) {
// retrieve - shouldn't these vars be "other files"... confusing
$zbsFiles = zeroBSCRM_getCustomerFiles( $contact['id'] );
// This specifically looks for $args['title'] file
$fileSlotSrc = zeroBSCRM_fileslots_fileInSlot( $filePerma, $contact['id'], ZBS_TYPE_CONTACT );
// check for file + only show that
$zbsFilesArr = array();
if ( $fileSlotSrc !== '' && is_array( $zbsFiles ) && count( $zbsFiles ) > 0 ) {
foreach ( $zbsFiles as $f ) {
if ( $f['file'] === $fileSlotSrc ) {
$zbsFilesArr[] = $f;
}
}
}
$zbsFiles = $zbsFilesArr;
}
// while we only have 1 file per slot, we can do this:
// *js uses this to empty if deleted elsewhere (other metabox)
$fileSlotURL = '';
if ( is_array( $zbsFiles ) && count( $zbsFiles ) === 1 ) {
$fileSlotURL = $zbsFiles[0]['url'];
}
// phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
?>
<table class="form-table wh-metatab wptbp zbsFileSlotTable" data-sloturl="<?php echo esc_attr( $fileSlotURL ); ?>" id="<?php echo esc_attr( $this->metaboxID ); ?>-tab">
<?php
#} Any slot filled?
if (is_array($zbsFiles) && count($zbsFiles) > 0){
?><tr class="wh-large zbsFileSlotWrap"><th class="zbsFileSlotTitle"><label><?php echo '<span>' . esc_html( count( $zbsFiles ) ) . '</span> '.esc_html__('File(s)','zero-bs-crm').':'; ?></label></th>
<td class="">
<?php $fileLineIndx = 1; foreach($zbsFiles as $zbsFile){
/* $file = basename($zbsFile['file']);
// if in privatised system, ignore first hash in name
if (isset($zbsFile['priv'])){
$file = substr($file,strpos($file, '-')+1);
} */
$file = zeroBSCRM_files_baseName($zbsFile['file'],isset($zbsFile['priv']));
echo '<div class="zbsFileLine" id="zbsFileLineCustomer'. esc_attr( $fileLineIndx ) .'"><a href="'. esc_url( $zbsFile['url'] ) .'" target="_blank">'. esc_html( $file ) .'</a> </div>';
// if using portal.. state shown/hidden
// this is also shown in each file slot :) if you change any of it change that too
if(defined('ZBS_CLIENTPRO_TEMPLATES')){
if(isset($zbsFile['portal']) && $zbsFile['portal']){
echo "<p><i class='icon check circle green inverted'></i> ".esc_html__('Shown on Portal','zero-bs-crm').'</p>';
}else{
echo "<p><i class='icon ban inverted red'></i> ".esc_html__('Not shown on Portal','zero-bs-crm').'</p>';
}
}
$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
// will be done by mainfunc wp_nonce_field(plugin_basename(__FILE__), 'zbsc_file_attachment_nonce');
$html .= '<input type="file" id="zbsc_file_'.$filePerma.'" name="zbsc_file_'.$filePerma.'" 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
echo $html;
?></td></tr>
</table>
<?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('custmetabox');
// PerfTest: zeroBSCRM_performanceTest_debugOut();
?>
<script type="text/javascript">
jQuery(function(){
});
</script>
<?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('other');
}
public function save_data( $contact_id, $contact ) {
// when multiple custom file boxes, this only needs to fire once :)
if (zeroBSCRM_is_customer_edit_page() && !defined('ZBS_CUSTOMFILES_SAVED')){
define('ZBS_CUSTOMFILES_SAVED',1);
global $zbsc_justUploadedCustomer,$zbs;
$settings = $zbs->settings->get('customfields'); $cfbInd = 1;
$cfbsubs = array();
if (isset($settings['customersfiles']) && is_array($settings['customersfiles']) && count($settings['customersfiles']) > 0) foreach ($settings['customersfiles'] as $cfb){
$thisFileSlotName = ''; if (isset($cfb[0])) $thisFileSlotName = $cfb[0];
$filePerma = ''; if (isset($thisFileSlotName) && !empty($thisFileSlotName)) {
//$filePerma = strtolower(str_replace(' ','_',str_replace('.','_',substr($thisFileSlotName,0,20))));
$filePerma = $zbs->DAL->makeSlug($thisFileSlotName);
}
if (!empty($thisFileSlotName) && !empty($filePerma)) $cfbsubs[$filePerma] = $thisFileSlotName;
}
if (count($cfbsubs) > 0) foreach ($cfbsubs as $cfSubKey => $cfSubName){
/* --- security verification --- */
if (isset($_POST['zbsc_file_attachment_nonce'])) if(!wp_verify_nonce($_POST['zbsc_file_attachment_nonce'], plugin_basename(__FILE__))) {
return $contact_id;
} // end if
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $contact_id;
} // end if
if (!zeroBSCRM_permsCustomers()){
return $contact_id;
}
/* - end security verification - */
if(!empty($_FILES['zbsc_file_'.$cfSubKey]['name']) &&
(!isset($zbsc_justUploadedCustomer) ||
(isset($zbsc_justUploadedCustomer) && $zbsc_justUploadedCustomer != $_FILES['zbsc_file_'.$cfSubKey]['name'])
)
) {
// Blocking repeat-upload bug
$zbsc_justUploadedCustomer = $_FILES['zbsc_file_'.$cfSubKey]['name'];
// verify file extension and mime type
if ( jpcrm_file_check_mime_extension( $_FILES['zbsc_file_'.$cfSubKey] ) ){
$upload = wp_upload_bits($_FILES['zbsc_file_'.$cfSubKey]['name'], null, file_get_contents($_FILES['zbsc_file_'.$cfSubKey]['tmp_name']));
if ( isset( $upload['error'] ) && $upload['error'] != 0 ) {
wp_die('There was an error uploading your file. The error is: ' . esc_html( $upload['error'] ) );
} else {
//update_post_meta($contact_id, 'zbsc_file_'.$cfSubKey, $upload);
// v2.13 - also privatise the file (move to our asset store)
// $upload will have 'file' and 'url'
$fileName = basename($upload['file']);
$fileDir = dirname($upload['file']);
$privateThatFile = zeroBSCRM_privatiseUploadedFile($fileDir,$fileName);
if (is_array($privateThatFile) && isset($privateThatFile['file'])){
// successfully moved to our store
// modify URL + file attributes
$upload['file'] = $privateThatFile['file'];
$upload['url'] = $privateThatFile['url'];
// add this extra identifier if in privatised sys
$upload['priv'] = true;
} else {
// couldn't move to store, leave in uploaded for now :)
}
// w mod - adds to array :)
$zbsCustomerFiles = zeroBSCRM_getCustomerFiles($contact_id);
if (is_array($zbsCustomerFiles)){
//add it
$zbsCustomerFiles[] = $upload;
} else {
// first
$zbsCustomerFiles = array($upload);
}
///update_post_meta($contact_id, 'zbs_customer_files', $zbsCustomerFiles);
zeroBSCRM_updateCustomerFiles($contact_id,$zbsCustomerFiles);
// this'll override any prev in that slot, too
zeroBSCRM_fileslots_addToSlot($cfSubKey,$upload['file'],$contact_id,ZBS_TYPE_CONTACT,true);
// Fire any 'post-upload-processing' (e.g. CPP makes thumbnails of pdf, jpg, etc.)
do_action('zbs_post_upload_contact',$upload);
}
} else {
wp_die("The file type that you've uploaded is not an accepted file format.");
}
} // if file
} /// / foreach
}
return $contact;
}
}
/* ======================================================
/ Attach (custom) fileboxes to customer metabox
====================================================== */
/* ======================================================
Attach files to customer metabox
====================================================== */
/* ======================================================
Contact Files Metabox
====================================================== */
class zeroBS__Metabox_ContactFiles extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-files';
$this->metaboxTitle = __('Other Files',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-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( $contact, $metabox ) {
global $zbs;
$html = '';
// wmod
#} retrieve - shouldn't these vars be "other files"... confusing
$zbsFiles = false;
if (isset($contact['id'])) $zbsFiles = zeroBSCRM_getCustomerFiles($contact['id']);
?><table class="form-table wh-metatab wptbp" id="wptbpMetaBoxMainItemFiles">
<?php
#} Whole file delete method could do with rewrite
#} Also sort JS into something usable - should be ajax all this
#} Any existing
if (is_array($zbsFiles) && count($zbsFiles) > 0){
?><tr class="wh-large zbsFileDetails"><th class="zbsFilesTitle"><label><?php echo '<span>'.count($zbsFiles).'</span> '.esc_html__('File(s)','zero-bs-crm').':'; ?></label></th>
<td id="zbsFileWrapOther">
<table class="ui celled table" id="zbsFilesTable">
<thead>
<tr>
<th><?php esc_html_e("File", 'zero-bs-crm');?></th>
<th class="collapsing center aligned"><?php esc_html_e("Actions", 'zero-bs-crm');?></th>
</tr>
</thead><tbody>
<?php $fileLineIndx = 1; foreach($zbsFiles as $zbsFile){
/* $file = basename($zbsFile['file']);
// if in privatised system, ignore first hash in name
if (isset($zbsFile['priv'])){
$file = substr($file,strpos($file, '-')+1);
} */
$file = zeroBSCRM_files_baseName($zbsFile['file'],isset($zbsFile['priv']));
$fileEditUrl = admin_url('admin.php?page='.$zbs->slugs['editfile']) . "&customer=".$contact['id']."&fileid=" . ($fileLineIndx-1);
echo '<tr class="zbsFileLineTR" id="zbsFileLineTRCustomer'. esc_attr( $fileLineIndx ) .'">';
echo '<td><div class="zbsFileLine" id="zbsFileLineCustomer'. esc_attr( $fileLineIndx ) .'"><a href="' . esc_url( $zbsFile['url'] ) . '" target="_blank">' . esc_html( $file ) . '</a></div>';
// if using portal.. state shown/hidden
// this is also shown in each file slot :) if you change any of it change that too
if(defined('ZBS_CLIENTPRO_TEMPLATES')){
if(isset($zbsFile['portal']) && $zbsFile['portal']){
echo "<p><i class='icon check circle green inverted'></i> ".esc_html__('Shown on Portal','zero-bs-crm').'</p>';
}else{
echo "<p><i class='icon ban inverted red'></i> ".esc_html__('Not shown on Portal','zero-bs-crm').'</p>';
}
}
echo '</td>';
echo '<td class="collapsing center aligned"><span class="zbsDelFile ui button basic" data-delurl="' . esc_attr( $zbsFile['url'] ) . '"><i class="trash alternate icon"></i> '.esc_html__('Delete','zero-bs-crm').'</span> <a href="' . esc_url( $fileEditUrl) . '" target="_blank" class="ui button basic"><i class="edit icon"></i> '.esc_html__('Edit','zero-bs-crm').'</a></td></tr>';
$fileLineIndx++;
} ?>
</tbody></table>
</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="zbsc_file_attachment" name="zbsc_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__), 'zbsc_file_attachment_nonce');
echo $html;
?></td></tr>
</table>
<?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('custmetabox');
// PerfTest: zeroBSCRM_performanceTest_debugOut();
?>
<script type="text/javascript">
var zbsCustomerCurrentlyDeleting = false;
var zbsMetaboxFilesLang = {
'error': '<?php echo esc_html( zeroBSCRM_slashOut(__('Error','zero-bs-crm')) ); ?>',
'unabletodelete': '<?php echo esc_html( zeroBSCRM_slashOut(__('Unable to delete this file.','zero-bs-crm')) ); ?>'
};
jQuery(function(){
jQuery('.zbsDelFile').on( 'click', function(){
if (!window.zbsCustomerCurrentlyDeleting){
// blocking
window.zbsCustomerCurrentlyDeleting = true;
var delUrl = jQuery(this).attr('data-delurl');
//var lineIDtoRemove = jQuery(this).closest('.zbsFileLine').attr('id');
var lineToRemove = jQuery(this).closest('tr');
if (typeof delUrl != "undefined" && delUrl != ''){
// postbag!
var data = {
'action': 'delFile',
'zbsfType': 'customer',
'zbsDel': delUrl, // could be csv, never used though
'zbsCID': <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>,
'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) {
var localLineToRemove = lineToRemove, localDelURL = delUrl;
// visually remove
jQuery(localLineToRemove).remove();
// update number
var newNumber = jQuery('#zbsFilesTable tr').length-1;
if (newNumber > 0)
jQuery('#wptbpMetaBoxMainItemFiles .zbsFilesTitle span').html();
else
jQuery('#wptbpMetaBoxMainItemFiles .zbsFileDetails').remove();
// remove any filled slots (with this file)
jQuery('.zbsFileSlotTable').each(function(ind,ele){
if (jQuery(ele).attr('data-sloturl') == localDelURL){
jQuery('.zbsFileSlotWrap',jQuery(ele)).remove();
}
});
// file deletion errors, show msg:
if (typeof response.errors != "undefined" && response.errors.length > 0){
jQuery.each(response.errors,function(ind,ele){
jQuery('#zerobs-customer-files-box').append('<div class="ui warning message" style="margin-top:10px;">' + ele + '</div>');
});
}
},
error: function(response){
jQuery('#zerobs-customer-files-box').append('<div class="ui warning message" style="margin-top:10px;"><strong>' + window.zbsMetaboxFilesLang.error + ':</strong> ' + window.zbsMetaboxFilesLang.unabletodelete + '</div>');
}
});
}
window.zbsCustomerCurrentlyDeleting = false;
} // / blocking
});
});
</script><?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('other');
}
public function save_data( $contact_id, $contact ) {
global $zbsc_justUploadedCustomer;
if(!empty($_FILES['zbsc_file_attachment']['name']) &&
(!isset($zbsc_justUploadedCustomer) ||
(isset($zbsc_justUploadedCustomer) && $zbsc_justUploadedCustomer != $_FILES['zbsc_file_attachment']['name'])
)
) {
/* --- security verification --- */
if(!wp_verify_nonce($_POST['zbsc_file_attachment_nonce'], plugin_basename(__FILE__))) {
return $id;
} // end if
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $id;
} // end if
if (!zeroBSCRM_permsCustomers()){
return $contact_id;
}
/* - end security verification - */
// Blocking repeat-upload bug
$zbsc_justUploadedCustomer = $_FILES['zbsc_file_attachment']['name'];
// verify file extension and mime type
if ( jpcrm_file_check_mime_extension( $_FILES['zbsc_file_attachment'] ) ){
$upload = wp_upload_bits($_FILES['zbsc_file_attachment']['name'], null, file_get_contents($_FILES['zbsc_file_attachment']['tmp_name']));
if ( isset( $upload['error'] ) && $upload['error'] != 0 ) {
wp_die('There was an error uploading your file. The error is: ' . esc_html( $upload['error'] ) );
} else {
//update_post_meta($id, 'zbsc_file_attachment', $upload);
// v2.13 - also privatise the file (move to our asset store)
// $upload will have 'file' and 'url'
$fileName = basename($upload['file']);
$fileDir = dirname($upload['file']);
$privateThatFile = zeroBSCRM_privatiseUploadedFile($fileDir,$fileName);
if (is_array($privateThatFile) && isset($privateThatFile['file'])){
// successfully moved to our store
// modify URL + file attributes
$upload['file'] = $privateThatFile['file'];
$upload['url'] = $privateThatFile['url'];
// add this extra identifier if in privatised sys
$upload['priv'] = true;
} else {
// couldn't move to store, leave in uploaded for now :)
}
// w mod - adds to array :)
$zbsCustomerFiles = zeroBSCRM_getCustomerFiles($contact_id);
if (is_array($zbsCustomerFiles)){
//add it
$zbsCustomerFiles[] = $upload;
} else {
// first
$zbsCustomerFiles = array($upload);
}
///update_post_meta($id, 'zbs_customer_files', $zbsCustomerFiles);
zeroBSCRM_updateCustomerFiles($contact_id,$zbsCustomerFiles);
// Fire any 'post-upload-processing' (e.g. CPP makes thumbnails of pdf, jpg, etc.)
do_action('zbs_post_upload_contact',$upload);
}
} else {
wp_die("The file type that you've uploaded is not an accepted file format.");
}
}
return $contact;
}
}
/* ======================================================
/ Attach files to customer metabox
====================================================== */
/* ======================================================
Create Client Portal
====================================================== */
class zeroBS__Metabox_ContactPortal extends zeroBS__Metabox{
public function __construct( $plugin_file, $metabox_screen = 'zbs-add-edit-contact-edit' ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-portal';
$this->metaboxTitle = __('Client Portal',"zero-bs-crm");
$this->metaboxScreen = $metabox_screen; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
$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();
}
public function html( $contact, $metabox ) {
// PerfTest: zeroBSCRM_performanceTest_startTimer('portal-draw');
global $plugin_page, $zbs;
$screen = get_current_screen();
$wp_user_id = '';
#} Rather than reload all the time :)
global $zbsContactEditing;
#} retrieve
//$zbsCustomer = get_post_meta($contact['id'], 'zbs_customer_meta', true);
if (!isset($zbsContactEditing) && isset($contact['id'])){
$zbsCustomer = zeroBS_getCustomer($contact['id'],false,false,false);
$zbsContactEditing = $zbsCustomer;
} else {
$zbsCustomer = $zbsContactEditing;
}
if ( isset($zbsCustomer) && is_array($zbsCustomer) && isset($zbsCustomer['email']) ){
//check customer link to see if it exists - wh moved to dal
$wp_user_id = zeroBSCRM_getClientPortalUserID( $contact['id'] );
/* nope
if($wp_user_id == ''){
$wp_user_id = email_exists( $zbsCustomer['email'] );
} */
}
echo '<div class="waiting-togen">';
// get user obj
$user_object = get_userdata( $wp_user_id );
if ( $user_object ){
// a user already exists with this email
echo '<div class="zbs-customerportal-activeuser">';
esc_html_e('WordPress User Linked',"zero-bs-crm");
echo ' #<span class="zbs-user-id">'. esc_html( $wp_user_id ) .'</span>:<br />';
echo '<span class="ui label">'. esc_html( $user_object->user_email ) .'</span>';
// wp admins get link
if ( zeroBSCRM_isWPAdmin() ){
$url = admin_url('user-edit.php?user_id='.$wp_user_id);
echo '<br /><a style="font-size: 12px;color:black;font-weight:600;" href="' . esc_url( $url ) . '" target="_blank"><i class="wordpress simple icon"></i> ' . esc_html__( 'View WordPress Profile', 'zero-bs-crm' ) . '</a>'; // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText
}
echo '</div>';
// user ID will now have access to this area..
echo '<hr /><div class="zbs-customerportal-activeuser-actions">';
echo esc_html( __( 'Client Portal Access:', 'zero-bs-crm' ) );
$customerPortalActive = true; if (zeroBSCRM_isCustomerPortalDisabled($contact['id'])) $customerPortalActive = false;
if ( $customerPortalActive ) {
// revoke/disable access
echo ' <span class="ui green empty circular label"></span> <span class="zbs-portal-label">' . esc_html( __( 'Enabled', 'zero-bs-crm' ) ) . '</span>';
// wp admins get reset link, unless the crm contact is assigned to any other role than CRM Customer
if ( zeroBSCRM_isWPAdmin() && jpcrm_role_check( $user_object, array(), array(), array( 'zerobs_customer' ) ) ) {
echo '<div id="zbs-customerportal-access-actions" class="zbs-customerportal-activeuser">';
echo '<button type="button" id="zbs-customerportal-resetpw" class="ui mini button white">' . esc_html( __( 'Reset Password', 'zero-bs-crm' ) ) . '</button>';
echo '<button type="button" id="zbs-customerportal-toggle" data-zbsportalaction="disable" class="ui mini button white negative">' . esc_html( __( 'Disable Access', 'zero-bs-crm' ) ) . '</button>';
echo '</div>';
} else {
// explainer - rarely shown
echo '<p style="font-size: 0.9em;margin-top: 0.5em;">' . esc_html__( 'The WordPress user has a role other than CRM Contact. They will need to reset their password via the WP login page.', 'zero-bs-crm' ) . '</p>';
}
echo '<hr /><div class="zbs-customerportal-activeuser-actions">';
printf( '<a target="_blank" href="%s" class="ui mini button white">%s</a>', esc_url( zeroBS_portal_link() ), esc_html( __( 'Preview Portal', 'zero-bs-crm' ) ) );
echo '</div>';
} else {
// enable access
echo ' <span class="ui red empty circular label"></span> <span class="zbs-portal-label">' . esc_html( __( 'Disabled', 'zero-bs-crm' ) ) . '</span>';
// wp admins get enable link, unless the crm contact is assigned to any other role than CRM Customer
if ( zeroBSCRM_isWPAdmin() && jpcrm_role_check( $user_object, array(), array(), array( 'zerobs_customer' ) ) ) {
echo '<div id="zbs-customerportal-access-actions">';
echo '<button type="button" id="zbs-customerportal-toggle" data-zbsportalaction="enable" class="ui mini button positive">' . esc_html( __( 'Enable Access', 'zero-bs-crm' ) ) . '</button>';
echo '</div>';
}
}
echo '<input type="hidden" id="zbsportalaction-ajax-nonce" value="' . esc_attr( wp_create_nonce( 'zbsportalaction-ajax-nonce' ) ) . '" />';
echo '</div>';
} else if ( is_array($zbsCustomer) && isset($zbsCustomer['email']) && !empty($zbsCustomer['email'])){
echo '<div class="no-gen" style="text-align:center">';
echo esc_html( __( 'No WordPress User exists with this email', 'zero-bs-crm' ) );
echo '<br/><br/>';
echo '<div class="ui primary black button button-primary wp-user-generate">';
echo esc_html( __( 'Generate WordPress User', 'zero-bs-crm' ) );
echo '</div>';
echo '<input type="hidden" name="newwp-ajax-nonce" id="newwp-ajax-nonce" value="' . esc_attr( wp_create_nonce( 'newwp-ajax-nonce' ) ) . '" />';
echo '</div>';
}else{
echo esc_html( __( 'Save your contact, or add an email to enable Client Portal functionality', 'zero-bs-crm' ) );
}
echo '</div>';
?><script type="text/javascript">
jQuery(function(){
// bind activate/deactivate
jQuery('#zbs-customerportal-toggle').off("click").on('click',function(e){
// action
var action = jQuery(this).attr('data-zbsportalaction');
// fire ajax
var t = {
action: "zbsPortalAction",
portalAction: action,
cid: <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>,
security: jQuery( '#zbsportalaction-ajax-nonce' ).val()
}
i = jQuery.ajax({
url: ajaxurl,
type: "POST",
data: t,
dataType: "json"
});
i.done(function(e) {
//console.log(e);
if(typeof e.success != "undefined"){
// localise
var cAction = action;
if (action == 'enable'){
// switch label
jQuery('.ui.circular.label',jQuery('.zbs-customerportal-activeuser-actions')).removeClass('red').addClass('green');
jQuery('.zbs-portal-label',jQuery('.zbs-customerportal-activeuser-actions')).html('<?php echo esc_html( __( 'Enabled', 'zero-bs-crm' ) ); ?>');
jQuery('#zbs-customerportal-toggle').removeClass('positive').addClass('negative').html('<?php echo esc_html( __( 'Disable Access', 'zero-bs-crm' ) ); ?>').attr('data-zbsportalaction','disable');
} else if (action == 'disable'){
// switch label
jQuery('.ui.circular.label',jQuery('.zbs-customerportal-activeuser-actions')).addClass('red').removeClass('green');
jQuery('.zbs-portal-label',jQuery('.zbs-customerportal-activeuser-actions')).html('<?php echo esc_html( __( 'Disabled', 'zero-bs-crm' ) ); ?>');
jQuery('#zbs-customerportal-toggle').removeClass('negative').addClass('positive').html('<?php echo esc_html( __( 'Enable Access', 'zero-bs-crm' ) ); ?>').attr('data-zbsportalaction','enable');
}
}
}), i.fail(function(e) {
//error
});
});
// bind reset pw
jQuery('#zbs-customerportal-resetpw').off("click").on('click',function(e){
// fire ajax
var t = {
action: "zbsPortalAction",
portalAction: 'resetpw',
cid: <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>,
security: jQuery( '#zbsportalaction-ajax-nonce' ).val()
}
i = jQuery.ajax({
url: ajaxurl,
type: "POST",
data: t,
dataType: "json"
});
i.done(function(e) {
//console.log(e);
if(typeof e.success != "undefined"){
var newPassword = '<?php zeroBSCRM_slashOut(esc_html__('Unknown',"zero-bs-crm")); ?>';
if (typeof e.pw != "undefined") newPassword = e.pw;
if ( newPassword !== false ){
// swal confirm
swal(
'<?php zeroBSCRM_slashOut(esc_html__('Client Portal Password Reset',"zero-bs-crm")); ?>',
'<?php zeroBSCRM_slashOut(esc_html__('Client Portal password has been reset for this contact, and they have been emailed with the new password. The new password is:',"zero-bs-crm")); ?><br /><span class="ui label">' + newPassword + '</span>',
'info'
);
} else {
// swal confirm
swal(
'<?php zeroBSCRM_slashOut(esc_html__('Client Portal Password Reset Error',"zero-bs-crm")); ?>',
'<?php zeroBSCRM_slashOut(esc_html__('Error: Client Portal password has not been reset for this contact.',"zero-bs-crm")); ?>',
'info'
);
}
}
}), i.fail(function(e) {
//error
});
});
// bind create
jQuery('.wp-user-generate').off("click").on('click',function(e){
email = jQuery('#email').val();
customerid = <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>;
if(email == ''){
alert("The email field is blank. Please fill in the email and save");
return false;
}
var t = {
action: "zbs_new_user",
email: email,
cid: customerid,
security: jQuery( '#newwp-ajax-nonce' ).val(),
}
i = jQuery.ajax({
url: ajaxurl,
type: "POST",
data: t,
dataType: "json"
});
i.done(function(e) {
console.log(e);
if(e.success){
jQuery('.zbs-user-id').html(e.user_id);
jQuery('.no-gen').remove();
jQuery('.waiting-togen').html('<div class="alert alert-success">Success: ' + e.message + '</div>');
} else {
jQuery('.no-gen').remove();
jQuery('.waiting-togen').html('<div class="alert alert-danger">Error: ' + e.message + '</div>');
}
}), i.fail(function(e) {
//error
});
});
});
</script><?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('portal-draw');
// PerfTest: zeroBSCRM_performanceTest_finishTimer('portal');
}
}
/* ======================================================
/ Create Client Portal
====================================================== */
/* ======================================================
Create Social Box
====================================================== */
class zeroBS__Metabox_ContactSocial extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-social';
$this->metaboxTitle = __('Social Profiles',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
$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();
}
public function html( $contact, $metabox ) {
global $plugin_page, $zbs;
// declare + load existing
global $zbsSocialAccountTypes;
$zbsSocials = false;
if ( isset( $contact['id'] ) ) {
$zbsSocials = $zbs->DAL->contacts->getContactSocials( $contact['id'] ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
if (count($zbsSocialAccountTypes) > 0) foreach ($zbsSocialAccountTypes as $socialKey => $socialAccType){
?><div class="zbs-social-acc <?php echo esc_attr( $socialAccType['slug'] ); ?>" title="<?php echo esc_attr( $socialAccType['name'] ); ?>">
<?php if (is_array($zbsSocials) && isset($zbsSocials[$socialKey]) && !empty($zbsSocials[$socialKey])){
// got acc? link to it
$socialLink = zeroBSCRM_getSocialLink( $socialKey, $zbsSocials );
?>
<a href="<?php echo esc_url( $socialLink ); ?>" target="_blank" title="<?php echo esc_attr__('View',"zero-bs-crm") . ' ' . esc_attr( $socialAccType['name'] ); ?>"><i class="fa <?php echo esc_attr( $socialAccType['fa'] ); ?>" aria-hidden="true"></i></a>
<?php } else { ?>
<i class="fa <?php echo esc_attr( $socialAccType['fa'] ); ?>" aria-hidden="true"></i>
<?php } ?>
<input type="text" class="zbs-social-acc-input zbs-dc" title="<?php echo esc_attr( $socialAccType['name'] ); ?>" name="zbs-social-<?php echo esc_attr( $socialAccType['slug'] ); ?>" id="zbs-social-<?php echo esc_attr( $socialAccType['slug'] ); ?>" value="<?php if (is_array($zbsSocials) && isset($zbsSocials[$socialKey]) && !empty($zbsSocials[$socialKey])) echo esc_attr( $zbsSocials[$socialKey] ); ?>" placeholder="<?php echo esc_attr( $socialAccType['placeholder'] ); ?>" />
</div><?php
}
// ++ get counts etc.
}
public function save_data( $contact_id, $contact ) {
$zbsSocials = array();
global $zbsSocialAccountTypes;
foreach ($zbsSocialAccountTypes as $socialKey => $socialAccType){
// set
$zbsSocials[$socialKey] = false;
// get from post if present
if (isset($_POST['zbs-social-'.$socialAccType['slug']]) && !empty($_POST['zbs-social-'.$socialAccType['slug']])) $zbsSocials[$socialKey] = sanitize_text_field($_POST['zbs-social-'.$socialAccType['slug']]);
}
zeroBS_updateCustomerSocialAccounts($contact_id,$zbsSocials);
return $contact;
}
}
/* ======================================================
/ Create Social Box
====================================================== */
/* ======================================================
Create AKA Box
====================================================== */
class zeroBS__Metabox_ContactAKA extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-aka';
$this->metaboxTitle = __('Contact Aliases (AKA)',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'low';
$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();
}
public function html( $contact, $metabox ) {
global $plugin_page, $zbs;
$screen = get_current_screen(); ?>
<div class="ui active inverted dimmer" style="display:none" id="zbs-aka-alias-loader"></div>
<?php
#} Rather than reload all the time :)
global $zbsContactEditing;
#} retrieve
//$zbsCustomer = get_post_meta($contact['id'], 'zbs_customer_meta', true);
if (!isset($zbsContactEditing) && isset($contact['id'])){
$zbsCustomer = zeroBS_getCustomer($contact['id'],false,false,false);
$zbsContactEditing = $zbsCustomer;
} else {
$zbsCustomer = $zbsContactEditing;
}
if (gettype($zbsCustomer) != "array"){
// new cust, can't add till saved.
?><div class="ui message"><?php esc_html_e('You will not be able to add an alias until you\'ve saved this contact',"zero-bs-crm"); ?></div><?php
} else {
// customer saved, so proceed - aka mode
// declare + load existing
$customerAliases = zeroBS_getCustomerAliases($contact['id']);
?><div id="zbs-aka-alias-wrap"><?php
// each alias: ID,aka_alias,aka_create,aka_lastupdated
if (is_array($customerAliases) && count($customerAliases) > 0) foreach ($customerAliases as $alias){
?><div class="zbs-aka-alias" id="zbs-aka-alias-<?php echo esc_attr( $alias['ID'] ); ?>">
<div class="ui label"><?php echo esc_html( $alias['aka_alias'] ); ?> <button type="button" class="ui mini icon button negative zbs-aka-alias-remove" data-akaid="<?php echo esc_attr( $alias['ID'] ); ?>" title="<?php esc_attr_e('Remove Alias',"zero-bs-crm"); ?>"><i class="icon remove"></i></button></div>
</div><?php
}
?></div><?php
?><div id="zbs-aka-alias-input-wrap">
<input type="text" class="zbs-aka-alias-input" placeholder="<?php esc_attr_e('Add Alias.. e.g.', 'zero-bs-crm'); ?> mike2@domain.com" />
<div class="ui pointing label" style="display:none;margin-bottom: 1em;margin-top: 0;" id="zbs-aka-alias-input-msg"><?php esc_html_e('Must be a valid email','zero-bs-crm'); ?></div>
<button type="button" class="ui small black button primary" id="zbs-aka-alias-add"><?php esc_html_e( 'Add Alias', 'zero-bs-crm' ); ?></button>
</div>
<script type="text/javascript">
var zbsAliasAKABlocker = false;
jQuery(function(){
jQuery('.zbs-aka-alias-input').on( 'keydown', function(){
// hide 'must be valid email'
jQuery('#zbs-aka-alias-input-msg').hide();
});
jQuery('#zbs-aka-alias-add').off('click').on( 'click', function(){
var v = jQuery('.zbs-aka-alias-input').val();
if ( typeof v === 'string' ) {
v = v.trim();
}
// lazy check for now
if (v != "" && zbscrm_JS_validateEmail(v)){
// blocker
if (!window.zbsAliasAKABlocker){
// block
window.zbsAliasAKABlocker = true;
jQuery('#zbs-aka-alias-loader').show();
// postbag!
var data = {
'action': 'addAlias',
'cid': <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>,
'aka': v,
'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) {
if (typeof response.res != "undefined"){
//console.log('added:',response);
var id = response.res;
var alias = v;
var lineHTML = '<div class="zbs-aka-alias" id="zbs-aka-alias-' + id + '"><div class="ui label">' + alias + ' <button type="button" class=" ui mini icon button negative zbs-aka-alias-remove" data-akaid="' + id + '""><i class="icon remove"></i></button></div></div>';
// add to ui
jQuery('#zbs-aka-alias-wrap').append(lineHTML);
// empty this
jQuery('.zbs-aka-alias-input').val('');
// bind
setTimeout(function(){
zeroBSJS_bindAKAMode();
},0);
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
} else {
if (typeof response.fail != "undefined"){
if (response.fail == 'existing'){
// already in use err
swal(
'<?php esc_html_e('Error',"zero-bs-crm"); ?>',
'<?php esc_html_e('This Alias is already in use by another contact.',"zero-bs-crm"); ?>',
'warning'
);
}
} else {
// general err
swal(
'<?php esc_html_e('Error',"zero-bs-crm"); ?>',
'<?php esc_html_e('There was an error adding this alias',"zero-bs-crm"); ?>',
'warning'
);
}
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
}
},
error: function(response){
// err
swal(
'<?php esc_html_e('Error',"zero-bs-crm"); ?>',
'<?php esc_html_e('There was an error adding this alias',"zero-bs-crm"); ?>',
'warning'
);
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
}
});
} // / blocker
} // / if not empty
else {
// not valid email, showxxx
jQuery('#zbs-aka-alias-input-msg').show();
// hide after 2s
setTimeout(function(){
jQuery('#zbs-aka-alias-input-msg').hide();
},2000);
}
});
// other bind
zeroBSJS_bindAKAMode();
});
function zeroBSJS_bindAKAMode(){
// hover over
jQuery('.zbs-aka-alias').on( 'mouseenter', function () {
jQuery(this).addClass("hovering");
}).on( 'mouseleave', function () {
jQuery(this).removeClass("hovering");
});
// remoe aka
jQuery('.zbs-aka-alias-remove').off('click').on( 'click', function(){
// blocker
if (!window.zbsAliasAKABlocker){
// block
window.zbsAliasAKABlocker = true;
jQuery('#zbs-aka-alias-loader').show();
// get id
var akaID = jQuery(this).attr('data-akaid');
if (akaID > 0){
// postbag!
var data = {
'action': 'removeAlias',
'cid': <?php if (!empty($contact['id']) && $contact['id'] > 0) echo esc_html( $contact['id'] ); else echo -1; ?>,
'akaid': akaID,
'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) {
if (typeof response.res != "undefined"){
console.log('removed:',response);
var lID = akaID;
// remove from ui
jQuery('#zbs-aka-alias-' + lID).remove();
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
} else {
// err
swal(
'<?php esc_html_e('Error',"zero-bs-crm"); ?>',
'<?php esc_html_e('There was an error removing this alias',"zero-bs-crm"); ?>',
'warning'
);
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
}
},
error: function(response){
// err
swal(
'<?php esc_html_e('Error',"zero-bs-crm"); ?>',
'<?php esc_html_e('There was an error removing this alias',"zero-bs-crm"); ?>',
'warning'
);
//unblock
window.zbsAliasAKABlocker = false;
jQuery('#zbs-aka-alias-loader').hide();
}
});
} // / akai id present
}
});
}
</script>
<?php
} // / if cust defined
}
}
/* ======================================================
/ Create AKA Box
====================================================== */
/* ======================================================
Create Tags Box
====================================================== */
class zeroBS__Metabox_ContactTags extends zeroBS__Metabox_Tags{
public function __construct( $plugin_file ) {
$this->objTypeID = ZBS_TYPE_CONTACT;
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-tags';
$this->metaboxTitle = __('Contact Tags',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-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
====================================================== */
/* ======================================================
Create Logs Box
====================================================== */
class zeroBS__Metabox_ContactLogs extends zeroBS__Metabox_LogsV2{
public function __construct( $plugin_file ) {
$this->objtypeid = ZBS_TYPE_CONTACT;
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-logs';
$this->metaboxTitle = __('Activity Log',"zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'normal';
$this->metaboxLocation = 'high';
$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
'hide_on_new' => true // no point in adding logs while adding contact, add after creation :)
);
// call this
$this->initMetabox();
}
// html + save dealt with by parent class :)
}
/* ======================================================
/ Create Logs Box
====================================================== */
/* ======================================================
"Contacts at Company" Metabox
====================================================== */
class zeroBS__Metabox_ContactCompany extends zeroBS__Metabox{
public function __construct( $plugin_file ) {
# (language switch)
$companyOrOrg = zeroBSCRM_getSetting('coororg');
$companyLabel = jpcrm_label_company();
$this->objType = 'contact';
$this->metaboxID = 'zerobs-customer-company';
$this->metaboxTitle = __($companyLabel, "zero-bs-crm");
$this->metaboxScreen = 'zbs-add-edit-contact-edit'; //'zerobs_edit_contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'core';
$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();
}
public function html( $contact, $metabox ) {
global $plugin_page, $zbs;
// PerfTest: zeroBSCRM_performanceTest_startTimer('companydropdown');
# (language switch)
$companyOrOrg = zeroBSCRM_getSetting('coororg');
$companyLabel = jpcrm_label_company();
#} Typeahead instead
echo "<div id='zbscompnew'>";
echo "<span>" . esc_html( sprintf( __( 'Type to assign %s', 'zero-bs-crm' ), jpcrm_label_company() ) ) . '</span>';
#} Co Name Default
$coName = ''; $coID = '';
if ( 'contact' == $this->objType ){
$coID = -1; if (is_array($contact) && isset($contact['id'])) $coID = zeroBS_getCustomerCompanyID($contact['id']);
if (!empty($coID)){
$co = zeroBS_getCompany($coID);
// 3.0
if (isset($co) && isset($co['name'])) $coName = $co['name'];
// < 3.0
if (isset($co) && isset($co['meta']) && isset($co['meta']['coname'])) $coName = $co['meta']['coname'];
if (empty($coName) && isset($co['coname'])) $coName = $co['coname'];
}
}
#} Output
if ( get_option('permalink_structure') == '' ){
echo "<div class='ui message red'>" . esc_html__('You are using Plain Permalinks. Please set your permalinks to %postname% by visiting ','zero-bs-crm') . "<a href='" . esc_url( admin_url('options-permalink.php') )."'>".esc_html__('here','zero-bs-crm')."</a></div>";
}else{
echo zeroBSCRM_CompanyTypeList('zbscrmjs_customer_setCompany',$coName,true,'zbscrmjs_customer_changedCompany');
}
#} Hidden input (real input) & Callback func
?><input type="hidden" name="zbs_company" id="zbs_company" value="<?php echo esc_attr( $coID ); ?>" />
<script type="text/javascript">
// custom fuction to copy company details from typeahead company deets
function zbscrmjs_customer_setCompany(obj){
if (typeof obj.id != "undefined"){
// set vals
jQuery("#zbs_company").val(obj.id);
// set dirty
zbscrm_JS_addDirty('zbs-company');
}
}
// custom fuction to copy company details from typeahead company deets
// this one fires on any change, but here we're just using to catch empties :)
// in fact, this one now overrides above^
function zbscrmjs_customer_changedCompany(newval){
if (typeof newval == "undefined" || newval == ''){
// set vals
jQuery("#zbs_company").val('');
// set dirty
zbscrm_JS_addDirty('zbs-company');
}
}
</script>
</div><?php
// PerfTest: zeroBSCRM_performanceTest_finishTimer('companydropdown');
}
public function save_data( $contact_id, $contact ) {
return $contact;
}
}
/* ======================================================
/ "Contacts at Company" Metabox Related Funcs
====================================================== */
/* ======================================================
Contact Activity Metabox
====================================================== */
class zeroBS__Metabox_Contact_Activity extends zeroBS__Metabox {
public function __construct( $plugin_file ) {
$this->metaboxID = 'zbs-contact-activity-metabox';
$this->metaboxTitle = __('Activity', 'zero-bs-crm');
$this->metaboxIcon = 'heartbeat';
$this->metaboxScreen = 'zbs-view-contact'; // we can use anything here as is now using our func
$this->metaboxArea = 'side';
$this->metaboxLocation = 'high';
// call this
$this->initMetabox();
}
public function html( $obj, $metabox ) {
global $zbs, $zeroBSCRM_logTypes;
$objid = -1; if (is_array($obj) && isset($obj['id'])) $objid = $obj['id'];
// output any pinned logs
$pinned_logs = $zbs->DAL->logs->getLogsForObj(array(
'objtype' => ZBS_TYPE_CONTACT,
'objid' => $objid,
'only_pinned' => true,
'incMeta' => true,
'sortByField' => 'zbsl_created',
'sortOrder' => 'DESC',
'page' => -1,
'perPage' => -1,
'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_CONTACT )
));
if ( is_array( $pinned_logs ) && count( $pinned_logs ) > 0 ){
$pinned_log_count = 0;
echo '<h4 style="text-align:right" class="ui top attached header" id="jpcrm-pinned-logs-header">' . esc_attr__( 'Pinned Logs', 'zero-bs-crm' ) . '</h4>';
echo '<div class="jpcrm-pinned-logs ui green attached segment">';
foreach ( $pinned_logs as $log ){
if (is_array($log) && isset($log['created'])){
if ( $pinned_log_count > 0 ){
?><div class="ui divider"></div><?php
}
echo '<div class="jpcrm-pinned-log">';
// ico?
$ico = ''; $logKey = strtolower(str_replace(' ','_',str_replace(':','_',$log['type'])));
if (isset($zeroBSCRM_logTypes['zerobs_customer'][$logKey])) $ico = $zeroBSCRM_logTypes['zerobs_customer'][$logKey]['ico'];
// these are FA ico's at this point
// compile this first, so can catch default (empty types)
$logTitle = '';
if (!empty($ico)) $logTitle .= '<i class="fa '.$ico.'"></i> ';
// DAL 2 saves type as permalinked
if (isset($zeroBSCRM_logTypes['zerobs_customer'][$logKey])) $logTitle .= __($zeroBSCRM_logTypes['zerobs_customer'][$logKey]['label'],"zero-bs-crm");
?>
<?php
// short desc
if (isset($log['shortdesc']) && !empty($log['shortdesc'])){ ?>
<h4 class="jpcrm-pinned-log-shortdesc">
<?php echo $logTitle . ' | ' . esc_html( $log['shortdesc'] ); ?>
</h4>
<?php } ?>
<?php
// long desc
if (isset($log['longdesc']) && !empty($log['longdesc'])){ ?>
<div class="jpcrm-pinned-log-longdesc">
<?php echo wp_kses( html_entity_decode( $log['longdesc'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ), $zbs->acceptable_restricted_html ); ?>
</div>
<?php } ?>
<div class="jpcrm-pinned-log-author-date-meta">
<?php
$meta_string = '';
if ( !empty( $log['author'] ) ) {
$meta_string = $log['author'];
}
if ( !empty($log['createduts'] ) && $log['createduts'] > 0 ) {
if ( !empty( $meta_string ) ){
$meta_string .= ' — ';
}
$meta_string .= jpcrm_uts_to_date_str( $log['createduts'] );
}
echo esc_html( $meta_string );
?></div>
</div><?php
$pinned_log_count++;
}
}
?></div><?php
}
// normal activity output
echo '<div class="zbs-activity">';
echo '<div class="">';
$zbsCustomerActivity = zeroBSCRM_getContactLogs($objid,true,100,0,'',false);
zeroBSCRM_html_contactTimeline($objid,$zbsCustomerActivity,$obj);
echo '</div>';
echo '</div>';
}
// nothing to save here.
public function save_data( $objID, $obj ) {
return $obj;
}
}
/* ======================================================
/ Contact Activity Metabox
====================================================== */