Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 288
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Woo_Sync_My_Account_Integration
0.00% covered (danger)
0.00%
0 / 287
0.00% covered (danger)
0.00%
0 / 10
17822
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 instance
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 init_hooks
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 render_invoice_list
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 check_customer_has_invoices
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 append_items_to_woo_menu
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 register_styles_scripts
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 enqueue_styles_scripts
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 render_additional_crm_fields_on_my_account
0.00% covered (danger)
0.00%
0 / 194
0.00% covered (danger)
0.00%
0 / 1
10100
 save_my_account_crm_field_changes
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 1
240
1<?php
2/*
3 * Jetpack CRM
4 * https://jetpackcrm.com
5 *
6 * WooSync: WooCommerce My Account integration
7 *
8 */
9namespace Automattic\JetpackCRM;
10
11// block direct access
12defined( 'ZEROBSCRM_PATH' ) || exit( 0 );
13
14/**
15 * WooSync My Account integration class
16 */
17class Woo_Sync_My_Account_Integration {
18
19    /**
20     * The single instance of the class.
21     */
22    protected static $_instance = null;
23
24    /**
25     * Setup WooSync
26     * Note: This will effectively fire after core settings and modules loaded
27     * ... effectively on tail end of `init`
28     */
29    public function __construct() {
30        // Initialise Hooks
31        $this->init_hooks();
32        // Styles and scripts
33        $this->register_styles_scripts();
34    }
35
36    /**
37     * Main Class Instance.
38     *
39     * Ensures only one instance of Woo_Sync_My_Account_Integration is loaded or can be loaded.
40     *
41     * @since 2.0
42     * @static
43     * @see
44     * @return Woo_Sync_My_Account_Integration main instance
45     */
46    public static function instance() {
47        if ( self::$_instance === null ) {
48            self::$_instance = new self();
49        }
50        return self::$_instance;
51    }
52
53    /**
54     * Initialise Hooks
55     */
56    private function init_hooks() {
57
58        // Add menu item to Woo My Account
59        add_filter( 'woocommerce_account_menu_items', array( $this, 'append_items_to_woo_menu' ), 99, 1 );
60
61        // Expose invoice content:
62        add_action( 'woocommerce_account_invoices_endpoint', array( $this, 'render_invoice_list' ) );
63
64        // Enqueue styles and scripts
65        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles_scripts' ) );
66
67        // Expose CRM fields for editing on My Account (where specified in `wcport` setting)
68        add_action( 'woocommerce_edit_account_form', array( $this, 'render_additional_crm_fields_on_my_account' ), 10, 0 );
69
70        // Save any changes to CRM fields as submitted from My Account page (where used `$this->render_additional_crm_fields_on_my_account`)
71        add_action( 'woocommerce_save_account_details', array( $this, 'save_my_account_crm_field_changes' ), 10, 1 );
72
73        // See also $zbs->wordpress_user_integration->wordpress_profile_update (catches woo my account + wp profile update changes)
74    }
75
76    /**
77     * Get Invoice List
78     */
79    public function render_invoice_list() {
80
81        global $zbs;
82
83        $settings = $zbs->modules->woosync->settings->getAll();
84        if ( array_key_exists( 'wcacc', $settings ) &&
85            $settings['wcacc'] &&
86            property_exists( $zbs->modules, 'portal' )
87        ) {
88
89            if ( $this->check_customer_has_invoices() ) {
90                $invoices_endpoint = new \Automattic\JetpackCRM\Invoices_Endpoint( $zbs->modules->portal );
91                $invoices_endpoint->list_invoices_html_output();
92            } else {
93
94                echo esc_html__( 'No invoices available.', 'zero-bs-crm' );
95
96            }
97        } else {
98
99            echo esc_html__( 'This feature is disabled.', 'zero-bs-crm' );
100
101        }
102    }
103
104    /**
105     * Does the current logged in customer have invoices?
106     *
107     * @return bool
108     */
109    private function check_customer_has_invoices() {
110
111        $wordpress_user_id = get_current_user_id();
112        $uinfo             = get_userdata( $wordpress_user_id );
113        $contact_id        = zeroBS_getCustomerIDWithEmail( $uinfo->user_email );
114
115        if ( $contact_id > 0 ) {
116
117            $customer_invoices = zeroBS_getInvoicesForCustomer( $contact_id, true, 100, 0, false );
118
119            if ( count( $customer_invoices ) > 0 ) {
120
121                return true;
122
123            }
124        }
125
126        return false;
127    }
128
129    /**
130     * Appends our menu items (e.g. `Your Invoices`) to the Woo menu stack
131     *  To be fired via hook: `woocommerce_account_menu_items`
132     */
133    public function append_items_to_woo_menu( $items ) {
134
135        global $zbs;
136
137        $my_account_invoices_enabled = zeroBSCRM_getSetting( 'feat_invs' ) > 0;
138        $wc_settings                 = $zbs->modules->woosync->settings->getAll();
139
140        if ( $my_account_invoices_enabled && $wc_settings['wcacc'] ) {
141
142            $modified_items = array( 'invoices' => __( 'Your Invoices', 'zero-bs-crm' ) );
143            $modified_items = array_slice( $items, 0, 2, true ) + $modified_items + array_slice( $items, 2, count( $items ), true );
144
145            $items = $modified_items;
146
147        }
148
149        return $items;
150    }
151
152    /**
153     * Register styles and scripts
154     */
155    public function register_styles_scripts() {
156        global $zbs;
157        wp_register_style( 'jpcrm-woo-sync-my-account', plugins_url( '/css/jpcrm-woo-sync-my-account' . wp_scripts_get_suffix() . '.css', JPCRM_WOO_SYNC_ROOT_FILE ), array(), $zbs::VERSION );
158        wp_register_style( 'jpcrm-woo-sync-fa', plugins_url( '/build/lib/font-awesome/css/font-awesome.min.css', ZBS_ROOTFILE ), array(), $zbs::VERSION );
159    }
160
161    /**
162     * Enqueue styles and scripts
163     */
164    public function enqueue_styles_scripts() {
165
166        $account_page_id = get_option( 'woocommerce_myaccount_page_id' );
167
168        if ( is_page( $account_page_id ) ) {
169            wp_enqueue_style( 'jpcrm-woo-sync-my-account' );
170            wp_enqueue_style( 'jpcrm-woo-sync-fa' );
171        }
172    }
173
174    /**
175     * Render CRM fields for editing on My Account (where specified in `wcport` setting)
176     * WH note: This could make use of a central functions for a chunk of it (e.g. shared with portal/front-end exposed fields?)
177     */
178    public function render_additional_crm_fields_on_my_account() {
179
180        // make action magic happen here...
181        global $zbs, $zbsCustomerFields, $zbsFieldsEnabled;
182
183        $settings = $zbs->modules->woosync->settings->getAll();
184
185        if ( array_key_exists( 'wcport', $settings ) ) {
186
187            // Retrieve current user data
188            $wordpress_user_id = get_current_user_id();
189            $uinfo             = get_userdata( $wordpress_user_id );
190            $contact_id        = zeroBS_getCustomerIDWithEmail( $uinfo->user_email );
191            $crm_contact       = zeroBS_getCustomerMeta( $contact_id );
192
193            // Field models/settings
194
195            // Fields pulled from contact model
196            $fields = $zbsCustomerFields;
197
198            // Retireve fields show/hide statuses
199            $fields_to_show                   = $settings['wcport'];
200            $fields_to_hide                   = $zbs->settings->get( 'fieldhides' );
201            $fields_to_show_on_woo_my_account = explode( ',', $fields_to_show );
202
203            // Fields to hide for front-end situations (Portal)
204            $fields_to_hide_on_portal = $zbs->DAL->fields_to_hide_on_frontend( ZBS_TYPE_CONTACT );
205
206            // Portal hide field setting (overrides global setting ^)
207            $portal_hide_fields_setting = $zbs->settings->get( 'portal_hidefields' );
208            if ( isset( $portal_hide_fields_setting ) ) {
209
210                $portal_hide_fields_setting_array = explode( ',', $portal_hide_fields_setting );
211                if ( is_array( $portal_hide_fields_setting_array ) ) {
212
213                    $fields_to_hide_on_portal = $portal_hide_fields_setting_array;
214                }
215            }
216
217            // Address/contact settings
218            $show_addresses             = zeroBSCRM_getSetting( 'showaddress' );
219            $show_second_address        = zeroBSCRM_getSetting( 'secondaddress' );
220            $show_address_country_field = zeroBSCRM_getSetting( 'countries' );
221            $click2call                 = false;
222
223            // Legacy: This global holds "enabled/disabled" for specific fields... ignore unless you're WH or ask
224            if ( $show_second_address == '1' ) {
225                $zbsFieldsEnabled['secondaddress'] = true;
226            }
227
228            // Track group element state
229            $open_field_group = false;
230            $field_group_key  = '';
231
232            ?>
233            <input type="hidden" name="zbs_customer_id" id="zbs_customer_id" value="<?php echo esc_attr( $contact_id ); ?>" />
234            <?php
235
236            // Cycle through fields and op
237            foreach ( $fields as $field_key => $field_value ) {
238
239                // Hard global front-end & specific Woo My Account blocking of some fields
240                if (
241                    // Global block
242                    ! in_array( $field_key, $fields_to_hide_on_portal )
243                    && // Woo My Account settings specific block
244                    in_array( $field_key, $fields_to_show_on_woo_my_account )
245                    && // Hard-hidden by opt override (on off for second address, mostly)
246                    ! ( isset( $field_value['opt'] ) && ( ! isset( $zbsFieldsEnabled[ $field_value['opt'] ] ) || ! $zbsFieldsEnabled[ $field_value['opt'] ] ) )
247                    && // or is hidden by checkbox?
248                    ! ( isset( $fields_to_hide['customer'] ) && is_array( $fields_to_hide['customer'] ) && in_array( $field_key, $fields_to_hide['customer'] ) )
249                ) {
250                    // Output all fields with a field format type
251                    if ( isset( $field_value[0] ) ) {
252
253                        // Output Fields in Woo matching format (<p> per line)
254                        ?>
255                        <p class="form-row">
256                        <?php
257
258                        // Split by field format
259                        switch ( $field_value[0] ) {
260
261                            case 'text':
262                                ?>
263                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
264                                <input type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="input-text" style="width: 100%;padding: 15px;margin-bottom: 18px;" placeholder="<?php echo ( isset( $field_value[2] ) ? esc_attr__( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
265                                <?php
266
267                                break;
268
269                            case 'price':
270                                ?>
271                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
272                                <?php echo esc_html( zeroBSCRM_getCurrencyChr() ); ?> <input style="width: 130px;display: inline-block;" type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control  numbersOnly" placeholder="<?php echo ( isset( $field_value[2] ) ? esc_attr__( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
273                                <?php
274
275                                break;
276
277                            case 'date':
278                                $value = ( isset( $crm_contact[ $field_key ] ) ) ? $crm_contact[ $field_key ] : null;
279
280                                $date_value = '';
281                                if ( ! empty( $value ) && $value !== -99 ) {
282                                    $date_value = jpcrm_uts_to_date_str( $value, 'Y-m-d', true );
283                                }
284                                ?>
285                                <p>
286                                    <label class='label' for="<?php echo esc_attr( $field_key ); ?>">
287                                <?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?>:
288                                    </label>
289                                    <input type="date" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="zbsc_<?php echo esc_attr( $field_key ); ?>" placeholder="yyyy-mm-dd" value="<?php echo esc_attr( $date_value ); ?>"/>
290                                </p>
291                                <?php
292                                break;
293
294                            case 'select':
295                                ?>
296                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
297                                    <select name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control zbs-watch-input" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>">
298                                <?php
299                                            // pre DAL 2 = $field_value[3], DAL2 = $field_value[2]
300                                            $options = array();
301                                if ( isset( $field_value[3] ) ) {
302
303                                    $options = $field_value[3];
304
305                                } else {
306
307                                    // DAL2 these don't seem to be auto-decompiled
308                                    if ( isset( $field_value[2] ) ) {
309                                                $options = explode( ',', $field_value[2] );
310                                    }
311                                }
312
313                                if ( isset( $options ) && count( $options ) > 0 ) {
314
315                                    echo '<option value="" disabled="disabled"';
316                                    if (
317                                    ! isset( $crm_contact[ $field_key ] )
318                                    ||
319                                    ( isset( $crm_contact[ $field_key ] ) && empty( $crm_contact[ $field_key ] ) )
320                                    ) {
321
322                                        echo ' selected="selected"';
323
324                                    }
325                                    echo '>' . esc_html__( 'Select', 'zero-bs-crm' ) . '</option>';
326
327                                    foreach ( $options as $opt ) {
328
329                                        echo '<option value="' . esc_attr( $opt ) . '"';
330
331                                        if ( isset( $crm_contact[ $field_key ] ) && strtolower( $crm_contact[ $field_key ] ) == strtolower( $opt ) ) {
332
333                                                                echo ' selected="selected"';
334
335                                        }
336
337                                        // __ here so that things like country lists can be translated
338                                        echo '>' . esc_html__( $opt, 'zero-bs-crm' ) . '</option>';
339
340                                    }
341                                } else {
342                                    echo '<option value="">' . esc_html__( 'No Options', 'zero-bs-crm' ) . '!</option>';
343                                }
344
345                                ?>
346                                    </select>
347                                <?php
348
349                                break;
350
351                            case 'tel':
352                                ?>
353                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
354                                    <input type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control zbs-tel" placeholder="<?php echo ( isset( $field_value[2] ) ? esc_attr__( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
355                                <?php
356
357                                if ( $click2call == '1' && isset( $crm_contact[ $field_key ] ) && ! empty( $crm_contact[ $field_key ] ) ) {
358
359                                    echo '<a href="' . esc_attr( zeroBSCRM_clickToCallPrefix() . $crm_contact[ $field_key ] ) . '" class="button"><i class="fa fa-phone"></i> ' . esc_html( $crm_contact[ $field_key ] ) . '</a>';
360
361                                }
362
363                                if ( $field_key == 'mobtel' ) {
364
365                                    // Twilio hook-in
366                                    do_action( 'zbs_twilio_nonce' );
367
368                                    // Twilio filtering for css classes
369                                    $sms_class = 'send-sms-none';
370                                    $sms_class = apply_filters( 'zbs_twilio_sms', $sms_class );
371
372                                    $contact_mobile = '';
373                                    if ( is_array( $crm_contact ) && isset( $crm_contact[ $field_key ] ) && isset( $contact['id'] ) ) {
374
375                                        $contact_mobile = zeroBS_customerMobile( $contact['id'], $crm_contact );
376
377                                    }
378
379                                    if ( ! empty( $contact_mobile ) ) {
380                                        echo '<a class="' . esc_attr( $sms_class ) . ' button" data-smsnum="' . esc_attr( $contact_mobile ) . '"><i class="mobile alternate icon"></i> ' . esc_html__( 'SMS', 'zero-bs-crm' ) . ': ' . esc_html( $contact_mobile ) . '</a>';
381                                    }
382                                }
383
384                                ?>
385                                <?php
386
387                                break;
388
389                            case 'email':
390                                ?>
391                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?>:</label>
392                                    <input type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control zbs-email" placeholder="<?php echo esc_attr( isset( $field_value[2] ) ? __( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
393                                <?php
394
395                                break;
396
397                            case 'textarea':
398                                ?>
399                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?>:</label>
400                                    <textarea name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control" placeholder="<?php echo esc_attr( isset( $field_value[2] ) ? __( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>"><?php echo esc_textarea( isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : '' ); ?></textarea>
401                                <?php
402
403                                break;
404
405                            #} Added 1.1.19
406                            case 'selectcountry':
407                                $countries = zeroBSCRM_loadCountryList();
408
409                                if ( $show_address_country_field == '1' ) {
410
411                                    ?>
412                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
413                                    <select name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>">
414                                    <?php
415
416                                            // got countries?
417                                    if ( isset( $countries ) && count( $countries ) > 0 ) {
418
419                                        echo '<option value="" disabled="disabled"';
420                                        if ( ! isset( $crm_contact[ $field_key ] )
421                                        ||
422                                        ( isset( $crm_contact[ $field_key ] ) && empty( $crm_contact[ $field_key ] ) ) ) {
423
424                                            echo ' selected="selected"';
425
426                                        }
427                                        echo '>' . esc_html__( 'Select', 'zero-bs-crm' ) . '</option>';
428
429                                        foreach ( $countries as $countryKey => $country ) {
430
431                                            // temporary fix for people storing "United States" but also "US"
432                                            // needs a migration to iso country code, for now, catch the latter (only 1 user via api)
433
434                                            echo '<option value="' . esc_attr( $country ) . '"';
435                                            if ( isset( $crm_contact[ $field_key ] )
436                                            &&
437                                            (
438                                            strtolower( $crm_contact[ $field_key ] ) == strtolower( $country )
439                                            ||
440                                            strtolower( $crm_contact[ $field_key ] ) == strtolower( $countryKey )
441                                            )
442                                            ) {
443
444                                                    echo ' selected="selected"';
445
446                                            }
447
448                                            echo '>' . esc_html( $country ) . '</option>';
449
450                                        }
451                                    } else {
452                                        echo '<option value="">' . esc_html__( 'No Countries Loaded', 'zero-bs-crm' ) . '!</option>';
453                                    }
454
455                                    ?>
456                                    </select>
457                                    <?php
458
459                                }
460
461                                break;
462
463                            // auto number - can't actually edit autonumbers, so its just outputting :)
464                            case 'autonumber':
465                                ?>
466                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
467                                <?php
468                                    // output any saved autonumber for this obj
469                                    $value = $field_value[2];
470                                    $str   = '';
471                                if ( $value !== -99 ) {
472                                    $str = $value;
473                                }
474
475                                                        // we strip the hashes saved in db for easy separation later
476                                                        $str = str_replace( '#', '', $str );
477
478                                                        // then output...
479                                if ( empty( $str ) ) {
480                                    echo '~';
481                                } else {
482                                    echo esc_html( $str );
483                                }
484
485                                break;
486
487                            case 'numberint':
488                                $value = isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : -99;
489
490                                ?>
491                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?></label>
492                                <input style="width: 130px;display: inline-block;" type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control intOnly zbs-dc zbs-custom-field" placeholder="<?php echo esc_attr( isset( $field_value[2] ) ? __( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( $value !== -99 ? $value : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
493                                <?php
494
495                                break;
496
497                            case 'numberfloat':
498                                $value = isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : -99;
499
500                                ?>
501                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?></label>
502                                <input style="width: 130px;display: inline-block;" type="text" name="zbsc_<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" class="form-control numbersOnly zbs-dc zbs-custom-field" placeholder="<?php echo esc_attr( isset( $field_value[2] ) ? __( $field_value[2], 'zero-bs-crm' ) : '' ); /* phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText */ ?>" value="<?php echo esc_attr( $value !== -99 ? $value : '' ); ?>" autocomplete="<?php echo esc_attr( jpcrm_disable_browser_autocomplete() ); ?>" />
503                                <?php
504
505                                break;
506
507                            case 'checkbox':
508                                    $value = isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : -99;
509
510                                ?>
511                                <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
512                                <?php
513                                    // pre DAL 2 = $fieldV[3], DAL2 = $fieldV[2]
514                                    $options = false;
515                                if ( isset( $field_value[3] ) && is_array( $field_value[3] ) ) {
516                                    $options = $field_value[3];
517                                } elseif ( isset( $field_value[2] ) ) {
518                                    // DAL2 these don't seem to be auto-decompiled?
519                                    // doing here for quick fix, maybe fix up the chain later.
520                                    $options = explode( ',', $field_value[2] );
521                                }
522
523                                                        // split fields (multi select)
524                                                        $data_options = array();
525                                if ( $value !== -99 && ! empty( $value ) ) {
526                                    $data_options = explode( ',', $value );
527                                }
528
529                                if (
530                                                        isset( $options )
531                                                        && is_array( $options )
532                                                        && count( $options ) > 0
533                                                        && $options[0] != ''
534                                                        ) {
535                                    $option_index = 0;
536
537                                    foreach ( $options as $opt ) {
538                                        echo '<div class="ui checkbox"><input type="checkbox" name="zbsc_' . esc_attr( $field_key . '-' . $option_index ) . '" id="' . esc_attr( $field_key . '-' . $option_index ) . '" value="' . esc_attr( $opt ) . '"';
539                                        if ( in_array( $opt, $data_options ) ) {
540                                            echo ' checked="checked"';
541                                        }
542                                        echo ' /><label for="' . esc_attr( $field_key . '-' . $option_index ) . '">' . esc_html( $opt ) . '</label></div>';
543
544                                        ++$option_index;
545                                    }
546                                } else {
547                                            echo '<label for="' . esc_attr( $field_key ) . '-0">' . esc_html__( 'No Options', 'zero-bs-crm' ) . '!</label>';
548                                }
549                                ?>
550                                <input type="hidden" name="zbsc_<?php echo esc_attr( $field_key ); ?>_dirtyflag" id="zbsc_<?php echo esc_attr( $field_key ); ?>_dirtyflag" value="0" />
551                                                        <?php
552
553                                break;
554
555                            case 'radio':
556                                    $value = isset( $crm_contact[ $field_key ] ) ? $crm_contact[ $field_key ] : -99;
557
558                                ?>
559                                    <label for="<?php echo esc_attr( $field_key ); ?>"><?php esc_html_e( $field_value[1], 'zero-bs-crm' ); ?></label>
560                                    <div class="zbs-field-radio-wrap">
561                                    <?php
562                                        // pre DAL 2 = $fieldV[3], DAL2 = $fieldV[2]
563                                        $options = false;
564                                    if ( isset( $field_value[3] ) && is_array( $field_value[3] ) ) {
565                                        $options = $field_value[3];
566                                    } elseif ( isset( $field_value[2] ) ) {
567                                        // DAL2 these don't seem to be auto-decompiled?
568                                        // doing here for quick fix, maybe fix up the chain later.
569                                        $options = explode( ',', $field_value[2] );
570                                    }
571
572                                    if (
573                                                            isset( $options )
574                                                            && is_array( $options )
575                                                            && count( $options ) > 0
576                                                            && $options[0] != ''
577                                                            ) {
578                                        $option_index = 0;
579
580                                        foreach ( $options as $opt ) {
581                                            echo '<div class="zbs-radio"><input type="radio" name="zbsc_' . esc_attr( $field_key ) . '" id="' . esc_attr( $field_key . '-' . $option_index ) . '" value="' . esc_attr( $opt ) . '"';
582
583                                            if ( $value !== -99 && $value == $opt ) {
584                                                echo ' checked="checked"';
585                                            }
586                                            echo ' /> <label for="' . esc_attr( $field_key . '-' . $option_index ) . '">' . esc_html( $opt ) . '</label></div>';
587
588                                            ++$option_index;
589                                        }
590                                    } else {
591                                                    echo '<label for="' . esc_attr( $field_key ) . '-0">' . esc_html__( 'No Options', 'zero-bs-crm' ) . '!</label>';
592                                    }
593
594                                    ?>
595                                        </div>
596                                        <input type="hidden" name="zbsc_<?php echo esc_attr( $field_key ); ?>_dirtyflag" id="zbsc_<?php echo esc_attr( $field_key ); ?>_dirtyflag" value="0" />
597                                                            <?php
598
599                                break;
600                        }
601                    }
602
603                    ?>
604                    </p>
605                    <?php
606
607                } // / not in 'hard do not show' list
608
609            } // foreach field
610
611        } // if array key does not exist
612    }
613
614    /**
615     * Save any changes made from extra field additions on My Account page (via `$this->render_additional_crm_fields_on_my_account`)
616     *
617     * @param int $wordpress_user_id
618     */
619    public function save_my_account_crm_field_changes( $wordpress_user_id ) {
620        global $zbs, $zbsCustomerFields;
621
622        $contact_id       = zeroBS_getCustomerIDFromWPID( $wordpress_user_id );
623        $old_contact_data = $zbs->DAL->contacts->getContact( $contact_id );
624        $new_contact_data = zeroBS_buildContactMeta( $_POST, $old_contact_data ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
625
626        // Here we check for fields already updated via core WordPress User integration
627        if ( defined( 'JPCRM_PROFILE_UPDATE_CHANGES' ) ) {
628            $do_not_update = JPCRM_PROFILE_UPDATE_CHANGES;
629        } else {
630            $do_not_update = array();
631        }
632
633        if ( $contact_id > 0 ) {
634            // First thing we have to do is to get some fields from WooCommerce
635            // and 'translate' their key names into our CRM key names.
636            $woo_field_to_crm_field = array(
637                'account_first_name' => 'fname',
638                'account_last_name'  => 'lname',
639                'account_email'      => 'email',
640            );
641
642            foreach ( $_POST as $post_key => $post_value ) {
643                if ( ! isset( $woo_field_to_crm_field[ $post_key ] ) ) {
644                    continue;
645                }
646
647                $crm_field = $woo_field_to_crm_field[ $post_key ];
648
649                if ( ! in_array( $crm_field, $do_not_update ) ) {
650                        $new_contact_data[ $crm_field ] = $post_value;
651                }
652            }
653
654            // TODO: This is the same code from Client Portal. This should be centralised somehow.
655            // process fields
656            $fields_to_change = array();
657            foreach ( $new_contact_data as $key => $value ) {
658                if ( ! isset( $zbsCustomerFields[ $key ] ) || in_array( $key, $do_not_update ) ) {
659                    $new_contact_data[ $key ] = $old_contact_data[ $key ];
660                }
661                // collect fields that changed
662                elseif ( isset( $old_contact_data[ $key ] ) && $old_contact_data[ $key ] != $value ) {
663                    $fields_to_change[] = $key;
664                }
665            }
666            // update contact if fields changed
667            if ( count( $fields_to_change ) > 0 ) {
668                $contact_id = $zbs->DAL->contacts->addUpdateContact(
669                    array(
670                        'id'                   => $contact_id,
671                        'data'                 => $new_contact_data,
672                        'do_not_update_blanks' => false,
673                    )
674                );
675
676                // update log if contact update was successful
677                if ( $contact_id ) {
678
679                    // build long description string for log
680                    $longDesc = '';
681                    foreach ( $fields_to_change as $field ) {
682                        if ( ! empty( $longDesc ) ) {
683                            $longDesc .= '<br>';
684                        }
685                        $longDesc .= sprintf( '%s: <code>%s</code> → <code>%s</code>', $field, $old_contact_data[ $field ], $new_contact_data[ $field ] );
686                    }
687
688                    zeroBS_addUpdateLog(
689                        $contact_id,
690                        -1,
691                        -1,
692                        array(
693                            'type'      => __( 'Details updated via WooCommerce My Account', 'zero-bs-crm' ),
694                            'shortdesc' => __( 'Contact changed some of their details via WooCommerce My Account', 'zero-bs-crm' ),
695                            'longdesc'  => $longDesc,
696                        ),
697                        'zerobs_customer'
698                    );
699                }
700            }
701        }
702    }
703}