PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | pages/page-mainwp-client.php +888 -245 5.2 → 6.2.1 View file →
@@ -8,8 +8,13 @@
8 8 */
9 9
10 10 namespace MainWP\Dashboard;
11 11
12 +// Exit if accessed directly.
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit;
15 +}
16 +
12 17 /**
13 18 * Class MainWP_client
14 19 *
15 20 * @uses page-mainwp-bulk-add::MainWP_Bulk_Add()
@@ -110,8 +115,20 @@
110 115
111 116 add_submenu_page(
112 117 'mainwp_tab',
113 118 esc_html__( 'Clients', 'mainwp' ),
119 + '<div class="mainwp-hidden">' . esc_html__( 'Import Clients', 'mainwp' ) . '</div>',
120 + 'read',
121 + 'ClientImport',
122 + array(
123 + static::get_class_name(),
124 + 'render_import_clients',
125 + )
126 + );
127 +
128 + add_submenu_page(
129 + 'mainwp_tab',
130 + esc_html__( 'Clients', 'mainwp' ),
114 131 '<div class="mainwp-hidden">' . esc_html__( 'Client Fields', 'mainwp' ) . '</div>',
115 132 'read',
116 133 'ClientAddField',
117 134 array(
@@ -185,14 +202,17 @@
185 202 <div id="menu-mainwp-Clients" class="mainwp-submenu-wrapper">
186 203 <div class="wp-submenu sub-open" style="">
187 204 <div class="mainwp_boxout">
188 205 <div class="mainwp_boxoutin"></div>
189 - <?php if ( mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) { ?>
206 + <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) { ?>
190 207 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ManageClients' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Clients', 'mainwp' ); ?></a>
191 208 <?php } ?>
192 209 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddNew' ) ) { ?>
193 210 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddNew' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Add Client', 'mainwp' ); ?></a>
194 211 <?php } ?>
212 + <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientImport' ) ) { ?>
213 + <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientImport' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Import Clients', 'mainwp' ); ?></a>
214 + <?php } ?>
195 215 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) { ?>
196 216 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddField' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Client Properties', 'mainwp' ); ?></a>
197 217 <?php } ?>
198 218 <?php
@@ -252,14 +272,22 @@
252 272 'right' => '',
253 273 'leftsub_order_level2' => 2,
254 274 ),
255 275 array(
276 + 'title' => esc_html__( 'Import Clients', 'mainwp' ),
277 + 'parent_key' => 'ManageClients',
278 + 'href' => 'admin.php?page=ClientImport',
279 + 'slug' => 'ClientImport',
280 + 'right' => '',
281 + 'leftsub_order_level2' => 3,
282 + ),
283 + array(
256 284 'title' => esc_html__( 'Client Fields', 'mainwp' ),
257 285 'parent_key' => 'ManageClients',
258 286 'href' => 'admin.php?page=ClientAddField',
259 287 'slug' => 'ClientAddField',
260 288 'right' => '',
261 - 'leftsub_order_level2' => 3,
289 + 'leftsub_order_level2' => 4,
262 290 ),
263 291 );
264 292
265 293 MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'ManageClients', 'ManageClients' );
@@ -281,10 +309,14 @@
281 309 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
282 310 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
283 311 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
284 312 $client_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
313 + $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
285 314
286 315 if ( $delete ) {
316 + if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'client', $iconfile_slug, $delnonce ) ) {
317 + die( 'Invalid nonce!' );
318 + }
287 319 if ( $client_id ) {
288 320 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
289 321 if ( $client && ! empty( $client->image ) ) {
290 322 $update = array(
@@ -313,17 +345,25 @@
313 345 $icon_url = $dirs[1] . $uploaded_icon;
314 346 wp_die(
315 347 wp_json_encode(
316 348 array(
317 - 'result' => 'success',
318 - 'iconfile' => esc_html( $uploaded_icon ),
319 - 'iconsrc' => esc_html( $icon_url ),
320 - 'iconimg' => '<img class="ui mini circular image" src="' . esc_attr( $icon_url ) . '" style="width:32px;height:auto;display:inline-block;" alt="Client custom icon">',
349 + 'result' => 'success',
350 + 'iconfile' => esc_html( $uploaded_icon ),
351 + 'iconsrc' => esc_html( $icon_url ),
352 + 'iconimg' => '<img class="ui circular image" src="' . esc_attr( $icon_url ) . '" style="width:28px;height:auto;display:inline-block;" alt="Client custom icon">',
353 + 'iconnonce' => MainWP_System_Utility::get_custom_nonce( 'client', esc_html( $uploaded_icon ) ),
321 354 )
322 355 )
323 356 );
324 357 } else {
325 - wp_die( wp_json_encode( array( 'result' => 'failed' ) ) );
358 + $result = array(
359 + 'result' => 'failed',
360 + );
361 + $error = MainWP_Post_Handler::get_upload_icon_error( $output );
362 + if ( ! empty( $error ) ) {
363 + $result['error'] = esc_html( $error );
364 + }
365 + wp_die( wp_json_encode( $result ) );
326 366 }
327 367 }
328 368
329 369
@@ -335,10 +375,14 @@
335 375 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
336 376 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
337 377 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
338 378 $contact_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
379 + $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
339 380
340 381 if ( $delete ) {
382 + if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'contact', $iconfile_slug, $delnonce ) ) {
383 + die( 'Invalid nonce!' );
384 + }
341 385 if ( $contact_id ) {
342 386 $contact_data = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'contact_id', $contact_id );
343 387 if ( $contact_data && ! empty( $contact_data->contact_image ) ) {
344 388 $update = array(
@@ -367,17 +411,25 @@
367 411 $icon_url = $dirs[1] . $uploaded_icon;
368 412 wp_die(
369 413 wp_json_encode(
370 414 array(
371 - 'result' => 'success',
372 - 'iconfile' => esc_html( $uploaded_icon ),
373 - 'iconsrc' => esc_html( $icon_url ),
374 - 'iconimg' => '<img class="ui mini circular image" src="' . esc_attr( $icon_url ) . '" style="width:32px;height:auto;display:inline-block;" alt="Client custom icon">',
415 + 'result' => 'success',
416 + 'iconfile' => esc_html( $uploaded_icon ),
417 + 'iconsrc' => esc_html( $icon_url ),
418 + 'iconimg' => '<img class="ui circular image" src="' . esc_attr( $icon_url ) . '" style="width:32px;height:auto;display:inline-block;" alt="Client custom icon">',
419 + 'iconnonce' => MainWP_System_Utility::get_custom_nonce( 'contact', esc_html( $uploaded_icon ) ),
375 420 )
376 421 )
377 422 );
378 423 } else {
379 - wp_die( wp_json_encode( array( 'result' => 'failed' ) ) );
424 + $result = array(
425 + 'result' => 'failed',
426 + );
427 + $error = MainWP_Post_Handler::get_upload_icon_error( $output );
428 + if ( ! empty( $error ) ) {
429 + $result['error'] = esc_html( $error );
430 + }
431 + wp_die( wp_json_encode( $result ) );
380 432 }
381 433 }
382 434
383 435
@@ -406,9 +458,9 @@
406 458 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
407 459 if ( $client ) {
408 460 $arr_client = MainWP_Utility::map_fields( $client, array( 'image', 'selected_icon_info' ), false ); // array map.
409 461 $client_pic = MainWP_Client_Handler::get_client_contact_image( $arr_client );
410 - $params['title'] = $client_pic . '<div class="content">' . $client->name . '<div class="sub header"><a href="mailto:' . $client->client_email . '" target="_blank" style="font-weight:normal!important;">' . $client->client_email . '</a> </div></div>';
462 + $params['title'] = $client_pic . '<div class="content">' . $client->name . '<div class="sub header"><a href="mailto:' . esc_attr( $client->client_email ) . '" target="_blank" style="font-weight:normal!important;">' . $client->client_email . '</a> </div></div>';
411 463 }
412 464 }
413 465
414 466 MainWP_UI::render_top_header( $params );
@@ -414,9 +466,9 @@
414 466 MainWP_UI::render_top_header( $params );
415 467
416 468 $renderItems = array();
417 469
418 - if ( mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) {
470 + if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
419 471 $renderItems[] = array(
420 472 'title' => esc_html__( 'Clients', 'mainwp' ),
421 473 'href' => 'admin.php?page=ManageClients',
422 474 'active' => ( '' === $shownPage ) ? true : false,
@@ -424,9 +476,9 @@
424 476 }
425 477
426 478 if ( $client_id ) {
427 479 $renderItems[] = array(
428 - 'title' => $client ? $client->name : esc_html__( 'Overview', 'mainwp' ),
480 + 'title' => $client ? $client->name : esc_html__( 'Operations', 'mainwp' ),
429 481 'href' => 'admin.php?page=ManageClients&client_id=' . $client_id,
430 482 'active' => ( 'overview' === $shownPage ),
431 483 );
432 484 $renderItems[] = array(
@@ -443,8 +495,16 @@
443 495 'active' => ( 'Add' === $shownPage ) ? true : false,
444 496 );
445 497 }
446 498
499 + if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientImport' ) ) {
500 + $renderItems[] = array(
501 + 'title' => esc_html__( 'Import Clients', 'mainwp' ),
502 + 'href' => 'admin.php?page=ClientImport',
503 + 'active' => ( 'Add' === $shownPage ) ? true : false,
504 + );
505 + }
506 +
447 507 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) {
448 508 $renderItems[] = array(
449 509 'title' => esc_html__( 'Client Fields', 'mainwp' ),
450 510 'href' => 'admin.php?page=ClientAddField',
@@ -494,32 +554,76 @@
494 554 MainWP_Client_Overview::instance()->on_show_page( intval( $_GET['client_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
495 555 return;
496 556 }
497 557
498 - if ( ! mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) {
499 - mainwp_do_not_have_permissions( esc_html__( 'manage clients', 'mainwp' ) );
558 + if ( ! \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
559 + \mainwp_do_not_have_permissions( esc_html__( 'manage clients', 'mainwp' ) );
500 560 return;
501 561 }
502 562
503 563 static::$itemsTable->prepare_items();
504 564
565 + $has_no_clients = ( 0 === static::$itemsTable->total_items );
566 +
505 567 static::render_header( '' );
506 - static::render_second_top_header();
507 568
569 + if ( ! $has_no_clients ) {
570 + static::render_second_top_header();
571 + }
572 +
508 573 ?>
509 - <div id="mainwp-manage-sites-content" class="ui segment">
510 - <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
511 - <form method="post" class="mainwp-table-container">
512 - <?php
513 - wp_nonce_field( 'mainwp-admin-nonce' );
514 - static::$itemsTable->display();
515 - static::$itemsTable->clear_items();
516 - ?>
517 - </form>
574 + <div id="mainwp-manage-clients-content" class="ui padded segment">
575 + <?php if ( $has_no_clients && MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-clients-welcome-message' ) ) : ?>
576 + <div class="ui icon message mainwp-welcome-message">
577 + <em data-emoji=":wave:" class="big"></em>
578 + <div class="content">
579 + <div class="ui massive header"><?php esc_html_e( 'Welcome to MainWP Clients', 'mainwp' ); ?></div>
580 + <p><?php esc_html_e( 'Organize and manage your customers with client profiles, contact information, and site associations.', 'mainwp' ); ?>
581 + </p>
582 + <p>
583 + <?php
584 + // translators: 1: Opening anchor tag for Add Client. 2: Closing anchor tag. 3: Opening anchor tag for Import Clients. 4: Closing anchor tag.
585 + printf( esc_html__( 'Start by %1$sadding your first client%2$s or %3$simporting existing clients%4$s from a CSV file.', 'mainwp' ), '<a href="admin.php?page=ClientAddNew">', '</a>', '<a href="admin.php?page=ClientImport">', '</a>' );
586 + ?>
587 + </p>
588 + </div>
589 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-clients-welcome-message"></i>
590 + </div>
591 + <?php else : ?>
592 + <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
593 + <?php if ( static::$itemsTable->total_items > 0 && static::$itemsTable->total_items <= 5 && MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-clients-add-more-clients-tip' ) ) : ?>
594 + <div class="ui message">
595 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-clients-add-more-clients-tip"></i>
596 + <?php
597 + // translators: 1: Bulb emoji element. 2: Opening anchor tag. 3: Closing anchor tag.
598 + printf( esc_html__( '%1$s Tip: Add more Clients. Use %2$sAdd Client%3$s to continue organizing your network.', 'mainwp' ), '<em data-emoji=":bulb:" class="small"></em>', '<a href="admin.php?page=ClientAddNew">', '</a>' );
599 + ?>
600 + </div>
601 + <?php endif; ?>
602 + <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-clients-columns-order-tip' ) ) : ?>
603 + <div class="ui message">
604 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-clients-columns-order-tip"></i>
605 + <?php
606 + // translators: 1: Bulb emoji element. 2: Cog icon element.
607 + printf( esc_html__( '%1$s Tip: Drag columns to reorder or use (%2$s) Page Settings to show/hide columns. Your column layout is saved automatically.', 'mainwp' ), '<em data-emoji=":bulb:" class="small"></em>', '<i class="cog fitted icon"></i>' );
608 + ?>
609 + </div>
610 + <?php endif; ?>
611 + <form method="post" class="mainwp-table-container">
612 + <?php
613 + MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' );
614 + static::$itemsTable->display();
615 + static::$itemsTable->clear_items();
616 + ?>
617 + </form>
618 + <?php endif; ?>
518 619 </div>
519 620 <?php
520 621 static::render_footer( '' );
521 - static::render_screen_options();
622 +
623 + if ( ! $has_no_clients ) {
624 + static::render_screen_options();
625 + }
522 626 }
523 627
524 628 /**
525 629 * Method render_second_top_header()
@@ -547,96 +651,95 @@
547 651 ?>
548 652 <div id="mainwp-edit-clients-modal" class="ui modal">
549 653 <i class="close icon"></i>
550 654 <div class="header"><?php esc_html_e( 'Edit client', 'mainwp' ); ?></div>
551 - <div class="ui message"><?php esc_html_e( 'Empty fields will not be passed to child sites.', 'mainwp' ); ?></div>
552 - <form id="update_client_profile">
553 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
554 - <div class="ui segment">
555 - <div class="ui form">
556 - <h3><?php esc_html_e( 'Name', 'mainwp' ); ?></h3>
557 - <div class="ui grid field">
558 - <label class="six wide column middle aligned"><?php esc_html_e( 'First Name', 'mainwp' ); ?></label>
559 - <div class="ui six wide column">
560 - <div class="ui left labeled input">
561 - <input type="text" name="first_name" id="first_name" value="" class="regular-text" />
562 - </div>
655 + <div class="scrolling content">
656 + <div class="ui info message"><?php esc_html_e( 'Blank fields will not be changed.', 'mainwp' ); ?></div>
657 + <form id="update_client_profile" class="ui form">
658 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
659 + <h3 class="ui header"><?php esc_html_e( 'Name', 'mainwp' ); ?></h3>
660 + <div class="ui grid field">
661 + <label class="six wide column middle aligned"><?php esc_html_e( 'First Name', 'mainwp' ); ?></label>
662 + <div class="ui six wide column">
663 + <div class="ui input">
664 + <input type="text" name="first_name" id="first_name" value="" class="regular-text" />
563 665 </div>
564 666 </div>
667 + </div>
565 668
566 - <div class="ui grid field">
567 - <label class="six wide column middle aligned"><?php esc_html_e( 'Last Name', 'mainwp' ); ?></label>
568 - <div class="ui six wide column">
569 - <div class="ui left labeled input">
570 - <input type="text" name="last_name" id="last_name" value="" class="regular-text" />
571 - </div>
669 + <div class="ui grid field">
670 + <label class="six wide column middle aligned"><?php esc_html_e( 'Last Name', 'mainwp' ); ?></label>
671 + <div class="ui six wide column">
672 + <div class="ui input">
673 + <input type="text" name="last_name" id="last_name" value="" class="regular-text" />
572 674 </div>
573 675 </div>
676 + </div>
574 677
575 - <div class="ui grid field">
576 - <label class="six wide column middle aligned"><?php esc_html_e( 'Nickname', 'mainwp' ); ?></label>
577 - <div class="ui six wide column">
578 - <div class="ui left labeled input">
579 - <input type="text" name="nickname" id="nickname" value="" class="regular-text" />
580 - </div>
678 + <div class="ui grid field">
679 + <label class="six wide column middle aligned"><?php esc_html_e( 'Nickname', 'mainwp' ); ?></label>
680 + <div class="ui six wide column">
681 + <div class="ui input">
682 + <input type="text" name="nickname" id="nickname" value="" class="regular-text" />
581 683 </div>
582 684 </div>
685 + </div>
583 686
584 - <div class="ui grid field">
585 - <label class="six wide column middle aligned"><?php esc_html_e( 'Display name publicly as', 'mainwp' ); ?></label>
586 - <div class="ui six wide column">
587 - <div class="ui left labeled input">
588 - <select name="display_name" id="display_name"></select>
589 - </div>
687 + <div class="ui grid field">
688 + <label class="six wide column middle aligned"><?php esc_html_e( 'Display name publicly as', 'mainwp' ); ?></label>
689 + <div class="ui six wide column">
690 + <div class="ui input">
691 + <select name="display_name" id="display_name" class="ui selection dropdown"></select>
590 692 </div>
591 693 </div>
694 + </div>
592 695
593 - <h3><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
696 + <h3 class="ui header"><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
594 697
595 - <div class="ui grid field">
596 - <label class="six wide column middle aligned"><?php esc_html_e( 'Email', 'mainwp' ); ?></label>
597 - <div class="ui six wide column">
598 - <div class="ui left labeled input">
599 - <input type="email" name="email" id="email" value="" class="regular-text ltr" />
600 - </div>
698 + <div class="ui grid field">
699 + <label class="six wide column middle aligned"><?php esc_html_e( 'Email', 'mainwp' ); ?></label>
700 + <div class="ui six wide column">
701 + <div class="ui input">
702 + <input type="email" name="email" id="email" value="" class="regular-text ltr" />
601 703 </div>
602 704 </div>
705 + </div>
603 706
604 - <div class="ui grid field">
605 - <label class="six wide column middle aligned"><?php esc_html_e( 'Website', 'mainwp' ); ?></label>
606 - <div class="ui six wide column">
607 - <div class="ui left labeled input">
608 - <input type="url" name="url" id="url" value="" class="regular-text code" />
609 - </div>
707 + <div class="ui grid field">
708 + <label class="six wide column middle aligned"><?php esc_html_e( 'Website', 'mainwp' ); ?></label>
709 + <div class="ui six wide column">
710 + <div class="ui input">
711 + <input type="url" name="url" id="url" value="" class="regular-text code" />
610 712 </div>
611 713 </div>
714 + </div>
612 715
613 - <h3><?php esc_html_e( 'About the client', 'mainwp' ); ?></h3>
716 + <h3 class="ui header"><?php esc_html_e( 'About the user', 'mainwp' ); ?></h3>
614 717
615 - <div class="ui grid field">
616 - <label class="six wide column middle aligned"><?php esc_html_e( 'Biographical Info', 'mainwp' ); ?></label>
617 - <div class="ui six wide column">
618 - <div class="ui left labeled input">
619 - <textarea name="description" id="description" rows="5" cols="30"></textarea>
620 - <p class="description"><?php esc_html_e( 'Share a little biographical information to fill out your profile. This may be shown publicly.', 'mainwp' ); ?></p>
621 - </div>
718 + <div class="ui grid field">
719 + <label class="six wide column middle aligned"><?php esc_html_e( 'Biographical Info', 'mainwp' ); ?></label>
720 + <div class="ui six wide column">
721 + <div class="ui input">
722 + <textarea name="description" id="description" rows="5" cols="30" style="width:100%"></textarea>
723 + <br/><span class="ui small text"><?php esc_html_e( 'Share a little biographical information to fill out your profile. This may be shown publicly.', 'mainwp' ); ?></span>
622 724 </div>
623 725 </div>
726 + </div>
624 727
625 - <h3><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
728 + <h3 class="ui header"><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
626 729
627 - <div class="ui grid field">
628 - <label class="six wide column middle aligned"><?php esc_html_e( 'Password', 'mainwp' ); ?></label>
629 - <div class="ui six wide column">
630 - <div class="ui left labeled action input">
631 - <input class="hidden" value=" "/>
632 - <input type="text" id="password" name="password" autocomplete="off" value="">
633 - </div>
730 + <div class="ui grid field">
731 + <label class="six wide column middle aligned"><?php esc_html_e( 'Password', 'mainwp' ); ?></label>
732 + <div class="ui six wide column">
733 + <div class="ui action input">
734 + <input class="hidden" value=" "/>
735 + <input type="text" id="password" name="password" autocomplete="off" value="">
634 736 </div>
635 737 </div>
636 738 </div>
637 - </div>
638 - </form>
739 +
740 + </form>
741 + </div>
639 742 <div class="actions">
640 743 <div id="mainwp_update_password_error" style="display: none"></div>
641 744 <span id="mainwp_clients_updating"><i class="ui active inline loader tiny"></i></span>
642 745 <input type="button" class="ui green button" id="mainwp_btn_update_client" value="<?php esc_attr_e( 'Update', 'mainwp' ); ?>">
@@ -669,9 +772,13 @@
669 772
670 773 if ( false === $show_cols ) { // to backwards.
671 774 $show_cols = array();
672 775 foreach ( $columns as $name => $title ) {
673 - $show_cols[ $name ] = 1;
776 + if ( in_array( $name, array( 'image', 'client', 'suspended', 'contact_name', 'websites', 'created' ) ) ) {
777 + $show_cols[ $name ] = 1;
778 + } else {
779 + $show_cols[ $name ] = 0;
780 + }
674 781 }
675 782 $user = wp_get_current_user();
676 783 if ( $user ) {
677 784 update_user_option( $user->ID, 'mainwp_settings_show_manage_clients_columns', $show_cols, true );
@@ -687,9 +794,9 @@
687 794 <i class="close icon"></i>
688 795 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
689 796 <div class="scrolling content ui form">
690 797 <form method="POST" action="" id="manage-sites-screen-options-form" name="manage_sites_screen_options_form">
691 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
798 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
692 799 <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'ManageClientsScrOptions' ) ); ?>" />
693 800 <div class="ui grid field">
694 801 <label class="six wide column"><?php esc_html_e( 'Default items per page value', 'mainwp' ); ?></label>
695 802 <div class="ten wide column">
@@ -749,9 +856,9 @@
749 856 </div>
750 857 <div class="ui small modal" id="mainwp-monitoring-sites-site-preview-screen-options-modal">
751 858 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
752 859 <div class="scrolling content ui form">
753 - <span><?php esc_html_e( 'Would you like to turn on home screen previews? This function queries WordPress.com servers to capture a screenshot of your site the same way comments shows you preview of URLs.', 'mainwp' ); ?>
860 + <span><?php esc_html_e( 'Would you like to turn on home screen previews? This function queries WordPress.com servers to capture a screenshot of your site the same way comments shows you preview of URLs.', 'mainwp' ); ?>
754 861 </div>
755 862 <div class="actions">
756 863 <div class="ui ok button"><?php esc_html_e( 'Yes', 'mainwp' ); ?></div>
757 864 <div class="ui cancel button"><?php esc_html_e( 'No', 'mainwp' ); ?></div>
@@ -771,13 +878,13 @@
771 878 } ).modal( 'show' );
772 879 }
773 880 } );
774 881 jQuery('#reset-manageclients-settings').on( 'click', function () {
775 - mainwp_confirm(__( 'Are you sure.' ), function(){
882 + mainwp_confirm(__( 'Are you sure?' ), function(){
776 883 jQuery('input[name=mainwp_default_manage_clients_per_page]').val(25);
777 884 jQuery('.mainwp_hide_wpmenu_checkboxes input[id^="mainwp_show_column_"]').prop( 'checked', false );
778 885 //default columns.
779 - let cols = ['name','email','phone','websites'];
886 + let cols = [ 'suspended','image','client','websites','contact_name','created'];
780 887 jQuery.each( cols, function ( index, value ) {
781 888 jQuery('.mainwp_hide_wpmenu_checkboxes input[id="mainwp_show_column_' + value + '"]').prop( 'checked', true );
782 889 } );
783 890 jQuery('input[name=reset_manageclients_columns_order]').attr('value',1);
@@ -815,27 +922,18 @@
815 922 static::render_header( $show );
816 923 ?>
817 924 <div class="ui alt segment" id="mainwp-add-clients">
818 925 <form action="" method="post" enctype="multipart/form-data" name="createclient_form" id="createclient_form" class="add:clients: validate">
819 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
926 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
820 927 <div class="mainwp-main-content">
821 - <div class="ui segment">
822 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-add-client-info-message' ) ) : ?>
823 - <div class="ui info message">
824 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-add-client-info-message"></i>
825 - <?php printf( esc_html__( 'use the provided form to create a new client on your child site(). for additional help, please check this %1$shelp documentation %2$s.', 'mainwp' ), '<a href="https://kb.mainwp.com/docs/create-a-new-client/" target="_blank">', '</a> <i class="external alternate icon"></i>' ); // NOSONAR - noopener - open safe. ?>
928 + <div class="ui padded segment">
929 + <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
930 + <div id="mainwp-add-new-client-form" >
931 + <?php static::render_add_client_content( $edit_client ); ?>
932 + </div>
826 933 </div>
827 - <?php endif; ?>
828 - <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
829 - <div id="mainwp-add-new-client-form" >
830 - <?php
831 - static::render_add_client_content( $edit_client );
832 - ?>
833 - </div>
834 934 </div>
835 - </div>
836 935 <div class="mainwp-side-content mainwp-no-padding">
837 -
838 936 <?php if ( $client_id ) : ?>
839 937 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
840 938 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Tokens Info', 'mainwp' ); ?></div>
841 939 <div class="content active">
@@ -880,10 +978,8 @@
880 978 </div>
881 979 </div>
882 980 <div style="clear:both"></div>
883 981 </form>
884 -
885 -
886 982 </div>
887 983 <?php
888 984 static::render_footer( $show );
889 985 static::render_add_field_modal( $client_id );
@@ -889,80 +985,388 @@
889 985 static::render_add_field_modal( $client_id );
890 986 MainWP_UI::render_modal_upload_icon();
891 987 }
892 988
893 -
894 989 /**
895 - * Renders the Add New Client Fields form.
990 + * Renders the Import Client form.
896 991 */
897 - public static function render_client_fields() {
992 + public static function render_import_clients() { // phpcs:ignore -- NOSONAR - Current complexity is the only way to achieve desired results, pull request solutions appreciated.
993 + static::render_header( 'ImportClients' );
994 + $title_page = esc_html__( 'Import Clients', 'mainwp' );
995 + // phpcs:disable WordPress.Security.NonceVerification.Missing
898 996
899 - static::render_header( 'AddField' );
997 + $has_import_data = ! empty( $_POST['mainwp_client_import_add'] );
998 + // phpcs:enable WordPress.Security.NonceVerification.Missing
999 + if ( $has_import_data && check_admin_referer( 'mainwp-admin-nonce' ) ) {
1000 + $result = static::render_import_client_modal();
1001 + }
900 1002 ?>
901 - <div class="ui segment" id="mainwp-add-client-fields">
1003 + <div class="ui padded segment" id="mainwp-import-clients">
1004 + <form method="POST" action="" enctype="multipart/form-data" id="mainwp_client_import_form" class="ui form">
1005 + <div>
1006 + <?php
1007 + if ( ! empty( $result ) && is_wp_error( $result ) ) {
1008 + ?>
1009 + <div class="ui message yellow"><i class="close icon"></i> <?php echo esc_html( $result->get_error_message() ); ?></div>
1010 + <?php
1011 + }
1012 + $el_id_mes_zn_1 = 'mainwp-message-zone';
1013 + ?>
1014 + <div id="<?php echo esc_attr( $el_id_mes_zn_1 ); ?>" class="ui message" style="display:none"></div>
1015 + <h3 class="ui dividing header">
1016 + <?php echo esc_html( $title_page ); ?>
1017 + <div class="sub header"><?php esc_html_e( 'Import multiple clients to your MainWP Dashboard.', 'mainwp' ); ?></div>
1018 + </h3>
1019 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1020 + <div class="ui grid field">
1021 + <label class="three wide column middle aligned" for="mainwp_client_import_file_bulkupload"><?php esc_html_e( 'Upload CSV', 'mainwp' ); ?> (<a href="<?php echo esc_url( MAINWP_PLUGIN_URL . 'assets/csv/sample_clients.csv' ); ?>" target="_blank"><?php esc_html_e( 'Download Sample', 'mainwp' ); ?></a>)</label>
1022 + <div class="nine wide column">
1023 + <div class="ui file input">
1024 + <input type="file" name="mainwp_client_import_file_bulkupload" id="mainwp_client_import_file_bulkupload" accept="text/comma-separated-values"/>
1025 + </div>
1026 + </div>
1027 + <div class="ui toggle checkbox four wide column middle aligned">
1028 + <input type="checkbox" name="mainwp_client_import_chk_header_first" checked="checked" id="mainwp_client_import_chk_header_first" value="1"/>
1029 + <label for="mainwp_client_import_chk_header_first"><?php esc_html_e( 'CSV file contains a header', 'mainwp' ); ?></label>
1030 + </div>
1031 + </div>
1032 + </div>
1033 + <div class="ui segment">
1034 + <div class="ui divider"></div>
1035 + <input type="submit" name="mainwp_client_import_add" id="mainwp_client_import_bulkadd" class="ui big green button" value="<?php echo esc_attr( $title_page ); ?>"/>
1036 + </div>
1037 + </form>
1038 + </div>
1039 + <script type="text/javascript">
1040 + jQuery('#mainwp-import-client-tabular-menu .item').tab();
1041 + </script>
902 1042 <?php
903 - $fields = MainWP_DB_Client::instance()->get_client_fields();
1043 + static::render_footer( 'ImportClients' );
1044 + }
1045 + /**
1046 + * Method render_import_client_modal()
1047 + *
1048 + * Render HTML import client modal.
1049 + *
1050 + * @return mixed Result.
1051 + */
1052 + public static function render_import_client_modal() {
1053 + $import_client_data = false;
1054 + $has_file_upload = isset( $_FILES['mainwp_client_import_file_bulkupload'] ) && isset( $_FILES['mainwp_client_import_file_bulkupload']['error'] ) && UPLOAD_ERR_OK === $_FILES['mainwp_client_import_file_bulkupload']['error']; // phpcs:ignore -- NOSONAR
1055 + if ( $has_file_upload ) {
1056 + $import_client_data = static::handle_client_import_files();
1057 + }
1058 + if ( ! is_array( $import_client_data ) || empty( $import_client_data['data'] ) || ! is_array( $import_client_data['data'] ) ) {
1059 + return new \WP_Error(
1060 + 'client_import_failed',
1061 + __( 'Failed to import client data. Please try again.', 'mainwp' )
1062 + );
1063 + }
904 1064 ?>
905 - <div class="ui info message" <?php echo ! MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-clients-manage-fields' ) ? 'style="display: none"' : ''; ?>>
906 - <?php esc_html_e( 'Create and manage custom Client fields.', 'mainwp' ); ?>
907 - <i class="ui close icon mainwp-notice-dismiss" notice-id="mainwp-clients-manage-fields"></i>
1065 + <div class="ui large modal mainwp-qsw-import-client-modal" id="mainwp-import-client-modal" >
1066 + <i class="close icon"></i>
1067 + <div class="header"><?php esc_html_e( 'Import Clients', 'mainwp' ); ?></div>
1068 + <div class="scrolling content">
1069 + <?php static::render_import_client_row_modal( $import_client_data ); ?>
1070 + </div>
1071 + <div class="actions">
1072 + <div class="ui two column grid">
1073 + <div class="left aligned middle aligned column">
1074 + <input type="button" name="mainwp_manageclients_btn_import" id="mainwp_manageclients_btn_import" class="ui basic button" value="<?php esc_attr_e( 'Pause', 'mainwp' ); ?>"/>
1075 + </div>
1076 + </div>
1077 + </div>
908 1078 </div>
909 - <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
910 - <table id="mainwp-clients-custom-fields-table" class="ui selectable compact table" style="width:100%">
911 - <thead>
912 - <tr>
913 - <th scope="col" ><?php esc_html_e( 'Field Name', 'mainwp' ); ?></th>
914 - <th scope="col" ><?php esc_html_e( 'Field Description', 'mainwp' ); ?></th>
915 - <th scope="col" class="no-sort collapsing"><?php esc_html_e( '', 'mainwp' ); ?></th>
916 - </tr>
917 - </thead>
918 - <tbody>
919 - <?php if ( is_array( $fields ) && ! empty( $fields ) ) : ?>
920 - <?php foreach ( $fields as $field ) : ?>
921 - <?php
922 - if ( ! $field ) {
923 - continue;
1079 + <script type="text/javascript">
1080 + jQuery( document ).ready( function () {
1081 + jQuery('#mainwp-import-client-tabular-menu .item').tab();
1082 + jQuery( "#mainwp-import-client-modal" ).modal( {
1083 + closable: false,
1084 + onHide: function() {
1085 + location.reload();
924 1086 }
925 - ?>
926 - <tr class="mainwp-field none-selected-color" field-id="<?php echo intval( $field->field_id ); ?>">
927 - <td class="field-name">[<?php echo esc_html( stripslashes( $field->field_name ) ); ?>]</td>
928 - <td class="field-description"><?php echo esc_html( stripslashes( $field->field_desc ) ); ?></td>
929 - <td>
930 - <div class="ui right pointing dropdown icon mini basic green button">
931 - <i class="ellipsis horizontal icon"></i>
932 - <div class="menu">
933 - <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
934 - <a class="item" id="mainwp-clients-delete-general-field" href="#"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
935 - </div>
1087 + } ).modal( 'show' );
1088 + } );
1089 + </script>
1090 + <?php
1091 +
1092 + return true;
1093 + }
1094 +
1095 + /**
1096 + * Method render_import_client_row_modal()
1097 + *
1098 + * Render row HTML import client.
1099 + *
1100 + * @return mixed Result or WP_Error.
1101 + */
1102 + public static function render_import_client_row_modal( $client_data = array() ) { // phpcs:ignore -- NOSONAR -complex.
1103 +
1104 + if ( is_array( $client_data ) && ! empty( $client_data['data'] ) && is_array( $client_data['data'] ) ) {
1105 + ?>
1106 + <div id="mainwp-importing-clients" class="ui active dimmer">
1107 + <div class="ui double text loader"><?php esc_html_e( 'Importing...', 'mainwp' ); ?></div>
1108 + </div>
1109 + <div class="ui message" id="mainwp-import-clients-status-message">
1110 + <i class="notched circle loading icon"></i> <?php echo esc_html__( 'Importing...', 'mainwp' ); ?>
1111 + </div>
1112 + <?php
1113 + $row = 0;
1114 + $header_line = trim( $client_data['header_line'] );
1115 + foreach ( $client_data['data'] as $val_client_data ) {
1116 + $encoded = wp_json_encode( $val_client_data );
1117 + $original = implode(
1118 + ', ',
1119 + array_map(
1120 + function ( $item ) {
1121 + return is_array( $item ) ? implode( ';', $item ) : $item;
1122 + },
1123 + $val_client_data
1124 + )
1125 + );
1126 + ?>
1127 + <input type="hidden" id="mainwp_manageclients_import_csv_line_<?php echo esc_attr( $row + 1 ); ?>" value="" encoded-data="<?php echo esc_attr( $encoded ); ?>" original="<?php echo esc_attr( $original ); ?>"/>
1128 + <?php
1129 + ++$row;
1130 + }
1131 + ?>
1132 + <input type="hidden" id="mainwp_manageclients_do_import" value="1"/>
1133 + <input type="hidden" id="mainwp_manageclients_total_import" value="<?php echo esc_attr( $row ); ?>"/>
1134 + <div class="mainwp_manageclients_import_listing" id="mainwp_manageclients_import_logging">
1135 + <span class="log ui medium text"><?php echo esc_html( $header_line ) . '<br/>'; ?></span>
1136 + </div>
1137 + <div class="mainwp_manageclients_import_listing" id="mainwp_manageclients_import_fail_logging" style="display: none;"><?php echo esc_html( $header_line ); ?> </div>
1138 + <?php
1139 + }
1140 + }
1141 +
1142 + /**
1143 + * Method handle_client_import_files()
1144 + *
1145 + * Handle client import files.
1146 + *
1147 + * @uses MainWP_System_Utility::get_wp_file_system()
1148 + * @uses MainWP_DB::instance()->get_websites_by_url()
1149 + *
1150 + * @return array Import data.
1151 + */
1152 + public static function handle_client_import_files() { // phpcs:ignore -- NOSONAR
1153 +
1154 + if ( isset( $_FILES['mainwp_client_import_file_bulkupload']['error'] ) && UPLOAD_ERR_OK !== $_FILES['mainwp_client_import_file_bulkupload']['error'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- NOSONAR
1155 + return false;
1156 + }
1157 +
1158 + $tmp_path = isset( $_FILES['mainwp_client_import_file_bulkupload']['tmp_name'] ) ? $_FILES['mainwp_client_import_file_bulkupload']['tmp_name'] : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- NOSONAR
1159 +
1160 + if ( ! is_uploaded_file( $tmp_path ) ) {
1161 + return false;
1162 + }
1163 +
1164 + $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
1165 + //phpcs:enable
1166 + /**
1167 + * WordPress files system object.
1168 + *
1169 + * @global object
1170 + */
1171 + global $wp_filesystem;
1172 +
1173 + $lines = array();
1174 + $header_line = '';
1175 +
1176 + if ( $hasWPFileSystem && ! empty( $wp_filesystem ) ) {
1177 + $content = $wp_filesystem->get_contents( $tmp_path );
1178 + if ( ! empty( $content ) ) {
1179 + // to compatible with EOL on OSs.
1180 + $content = str_replace( "\r\n", "\r", $content );
1181 + $content = str_replace( "\n", "\r", $content );
1182 + $lines = explode( "\r", $content );
1183 + }
1184 + } else {
1185 + return false;
1186 + }
1187 +
1188 + $import_data = array();
1189 + $default_values = array(
1190 + 'client.name' => '',
1191 + 'client.email' => '',
1192 + 'client.contact.address.1' => '',
1193 + 'client.contact.address.2' => '',
1194 + 'client.city' => '',
1195 + 'client.state' => '',
1196 + 'client.zip' => '',
1197 + 'client.country' => '',
1198 + 'client.suspended' => 0,
1199 + 'client.url' => '',
1200 + );
1201 + if ( is_array( $lines ) && ( ! empty( $lines ) ) ) {
1202 + $header_line = null;
1203 + foreach ( $lines as $original_line ) {
1204 + $line = trim( $original_line );
1205 + if ( MainWP_Utility::starts_with( $line, '#' ) ) {
1206 + continue;
1207 + }
1208 +
1209 + $items = str_getcsv( $line, ',' );
1210 +
1211 + if ( ( null === $header_line ) && ! empty( $_POST['mainwp_client_import_chk_header_first'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- NOSONAR
1212 + $header_line = sanitize_text_field( $line ) . "\r";
1213 + continue;
1214 + }
1215 + if ( 3 > count( $items ) ) {
1216 + continue;
1217 + }
1218 +
1219 + $x = 0;
1220 + $import_fields = array();
1221 + // Take data from the CSV file into the array.
1222 + foreach ( $default_values as $field => $val ) {
1223 + $value = isset( $items[ $x ] ) ? $items[ $x ] : $val;
1224 + $import_fields[ $field ] = sanitize_text_field( $value );
1225 + ++$x;
1226 + }
1227 + $import_data[] = $import_fields;
1228 + }
1229 + }
1230 +
1231 + if ( ! empty( $import_data ) ) {
1232 + foreach ( $import_data as $k_import => $val_import ) {
1233 + if ( ! empty( $val_import['client.url'] ) ) {
1234 + $import_data[ $k_import ]['client.url'] = explode( ';', sanitize_text_field( $val_import['client.url'] ) );
1235 + }
1236 + }
1237 + }
1238 + return array(
1239 + 'header_line' => esc_js( $header_line ),
1240 + 'data' => $import_data,
1241 + );
1242 + }
1243 +
1244 + /**
1245 + * Renders the Add New Client Fields form.
1246 + */
1247 + public static function render_client_fields() { // phpcs:ignore -- NOSONAR - Current complexity is the only way to achieve desired results, pull request solutions appreciated.
1248 +
1249 + $fields = MainWP_DB_Client::instance()->get_client_fields();
1250 + $has_no_fields = empty( $fields );
1251 +
1252 + static::render_header( 'AddField' );
1253 +
1254 + if ( ! $has_no_fields ) {
1255 + ?>
1256 + <div class="mainwp-sub-header">
1257 + <div class="ui grid">
1258 + <div class="equal width row ui mini form">
1259 + <div class="middle aligned column">
1260 + <div id="mainwp-client-fields-bulk-actions-menu" class="ui selection dropdown disabled">
1261 + <div class="default text"><?php esc_html_e( 'Bulk actions', 'mainwp' ); ?></div>
1262 + <i class="dropdown icon"></i>
1263 + <div class="menu">
1264 + <div class="item" data-value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></div>
936 1265 </div>
937 - </td>
1266 + </div>
1267 + <button class="ui mini basic button" id="mainwp-do-client-fields-bulk-actions" disabled="disabled"><?php esc_html_e( 'Apply', 'mainwp' ); ?></button>
1268 + </div>
1269 + <div class="right aligned middle aligned column">
1270 + <a class="ui mini green basic button" href="javascript:void(0);" id="mainwp-clients-new-custom-field-button"><i class="plus icon"></i><?php esc_html_e( 'Add Client Field', 'mainwp' ); ?></a>
1271 + </div>
1272 + </div>
1273 + </div>
1274 + </div>
1275 + <?php
1276 + }
1277 + ?>
1278 + <div class="ui padded segment" id="mainwp-add-client-fields">
1279 + <?php if ( $has_no_fields ) : ?>
1280 + <?php MainWP_UI::render_empty_page_placeholder( esc_html__( 'No custom fields created yet.', 'mainwp' ), esc_html__( 'Create custom fields to capture additional information about your clients. Click the New Field button to get started.', 'mainwp' ), '<em data-emoji=":compass:" class="big"></em>' ); ?>
1281 + <div style="text-align: center; margin-top: 20px;">
1282 + <a class="ui green button" href="javascript:void(0);" id="mainwp-clients-new-custom-field-button"><?php esc_html_e( 'Add Client Field', 'mainwp' ); ?></a>
1283 + </div>
1284 + <?php else : ?>
1285 + <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
1286 + <?php if ( count( $fields ) < 5 && MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-client-fields-tip' ) ) : ?>
1287 + <div class="ui message">
1288 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-client-fields-tip"></i>
1289 + <?php
1290 + // translators: 1: Bulb emoji element. 2: Opening anchor tag. 3: Closing anchor tag.
1291 + printf( esc_html__( '%1$s Tip: Custom Client Fields let you store extra details unique to your workflow, such as billing info, project type, or renewal dates. Once added, these fields will appear when adding or editing a client. %2$sLearn more%3$s about how custom fields work.', 'mainwp' ), '<em data-emoji=":bulb:" class="small"></em>', '<a href="https://docs.mainwp.com/clients/manage-clients#client-fields" target="_blank">', '</a>' );
1292 + ?>
1293 + </div>
1294 + <?php endif; ?>
1295 + <table id="mainwp-clients-custom-fields-table" class="ui table" style="width:100%">
1296 + <thead>
1297 + <tr>
1298 + <th scope="col" class="no-sort collapsing check-column">
1299 + <div class="ui checkbox">
1300 + <input type="checkbox" id="mainwp-client-fields-select-all">
1301 + <label></label>
1302 + </div>
1303 + </th>
1304 + <th scope="col"><?php esc_html_e( 'Field Name', 'mainwp' ); ?></th>
1305 + <th scope="col"><?php esc_html_e( 'Field Description', 'mainwp' ); ?></th>
1306 + <th scope="col" class="no-sort collapsing"></th>
938 1307 </tr>
939 - <?php endforeach; ?>
940 - <?php endif; ?>
941 - </tbody>
942 - <tfoot>
943 - <tr>
944 - <th scope="col" ><a class="ui mini green button" href="javascript:void(0);" id="mainwp-clients-new-custom-field-button"><?php esc_html_e( 'New Field', 'mainwp' ); ?></a></th>
945 - <th scope="col" ><?php esc_html_e( '', 'mainwp' ); ?></th>
946 - <th scope="col" ><?php esc_html_e( '', 'mainwp' ); ?></th>
947 - </tr>
948 - </tfoot>
949 - </table>
1308 + </thead>
1309 + <tbody>
1310 + <?php if ( is_array( $fields ) && ! empty( $fields ) ) : ?>
1311 + <?php foreach ( $fields as $field ) : ?>
1312 + <?php
1313 + if ( ! $field ) {
1314 + continue;
1315 + }
1316 + ?>
1317 + <tr class="mainwp-field none-selected-color" field-id="<?php echo intval( $field->field_id ); ?>">
1318 + <td class="check-column">
1319 + <div class="ui checkbox">
1320 + <input type="checkbox" class="mainwp-client-field-checkbox" value="<?php echo intval( $field->field_id ); ?>">
1321 + <label></label>
1322 + </div>
1323 + </td>
1324 + <td class="field-name">[<?php echo esc_html( stripslashes( $field->field_name ) ); ?>]</td>
1325 + <td class="field-description"><?php echo esc_html( stripslashes( $field->field_desc ) ); ?></td>
1326 + <td>
1327 + <div class="ui right pointing dropdown">
1328 + <i class="ellipsis vertical icon"></i>
1329 + <div class="menu">
1330 + <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
1331 + <a class="item" id="mainwp-clients-delete-general-field" href="#"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1332 + </div>
1333 + </div>
1334 + </td>
1335 + </tr>
1336 + <?php endforeach; ?>
1337 + <?php endif; ?>
1338 + </tbody>
1339 + </table>
950 1340
951 - <script type="text/javascript">
952 - // Init datatables
953 - jQuery( '#mainwp-clients-custom-fields-table' ).DataTable( {
954 - "stateSave": true,
955 - "stateDuration": 0,
956 - "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
957 - "columnDefs": [ { "orderable": false, "targets": "no-sort" } ],
958 - "order": [ [ 0, "asc" ] ],
959 - "language": { "emptyTable": "No fields found." },
960 - "drawCallback" : function( settings ) {
961 - jQuery( '#mainwp-clients-custom-fields-table .ui.dropdown').dropdown();
962 - },
963 - } );
964 - </script>
1341 + <script type="text/javascript">
1342 + // Init datatables
1343 + jQuery( '#mainwp-clients-custom-fields-table' ).DataTable( {
1344 + "stateSave": true,
1345 + "stateDuration": 0,
1346 + "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
1347 + "columnDefs": [ { "orderable": false, "targets": "no-sort" } ],
1348 + "order": [ [ 0, "asc" ] ],
1349 + "language": { "emptyTable": "No fields found." },
1350 + "drawCallback" : function( settings ) {
1351 + jQuery( '#mainwp-clients-custom-fields-table .ui.dropdown').dropdown();
1352 + jQuery( '#mainwp-clients-custom-fields-table .ui.checkbox').checkbox();
1353 + },
1354 + stateSaveParams: function (settings, data) {
1355 + data._mwpv = mainwpParams.mainwpVersion || 'dev';
1356 + },
1357 + stateLoadParams: function (settings, data) {
1358 + if ((mainwpParams.mainwpVersion || 'dev') !== data._mwpv) return false;
1359 + },
1360 + search: { regex: false, smart: false },
1361 + orderMulti: false,
1362 + searchDelay: 350
1363 + } );
1364 +
1365 + // Initialize header checkbox
1366 + jQuery( '#mainwp-clients-custom-fields-table thead .ui.checkbox' ).checkbox();
1367 + </script>
1368 + <?php endif; ?>
965 1369 </div>
966 1370
967 1371 <?php
968 1372 static::render_add_field_modal();
@@ -977,24 +1381,24 @@
977 1381 * @param int $client_id The client id.
978 1382 */
979 1383 public static function render_add_field_modal( $client_id = 0 ) {
980 1384 ?>
981 - <div class="ui modal" id="mainwp-clients-custom-field-modal">
1385 + <div class="ui small modal" id="mainwp-clients-custom-field-modal">
982 1386 <i class="close icon"></i>
983 1387 <div class="header"><?php esc_html_e( 'Custom Field', 'mainwp' ); ?></div>
984 1388 <div class="content ui mini form">
985 1389 <div class="ui yellow message" style="display:none"></div>
986 1390 <div class="field">
987 - <label><?php esc_html_e( 'Field Name', 'mainwp' ); ?></label>
1391 + <label><?php esc_html_e( 'Field Name', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
988 1392 <input type="text" value="" class="field-name" name="field-name" placeholder="<?php esc_attr_e( 'Enter field name (without of square brackets)', 'mainwp' ); ?>">
989 1393 </div>
990 1394 <div class="field">
991 - <label><?php esc_html_e( 'Field Description', 'mainwp' ); ?></label>
1395 + <label><?php esc_html_e( 'Field Description', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
992 1396 <input type="text" value="" class="field-description" name="field-description" placeholder="<?php esc_attr_e( 'Enter field description', 'mainwp' ); ?>">
993 1397 </div>
994 1398 </div>
995 1399 <div class="actions">
996 - <input type="button" class="ui green button" client-id="<?php echo intval( $client_id ); ?>" id="mainwp-clients-save-new-custom-field" value="<?php esc_attr_e( 'Save Field', 'mainwp' ); ?>">
1400 + <input type="button" class="ui green mini button disabled" client-id="<?php echo intval( $client_id ); ?>" id="mainwp-clients-save-new-custom-field" value="<?php esc_attr_e( 'Save Field', 'mainwp' ); ?>" disabled>
997 1401 </div>
998 1402 <input type="hidden" value="0" name="field-id">
999 1403 </div>
1000 1404 <?php
@@ -1013,8 +1417,14 @@
1013 1417 if ( ! is_array( $client_fields ) ) {
1014 1418 $client_fields = array();
1015 1419 }
1016 1420
1421 + $editing_client_id = isset( $client_fields['client_id'] ) ? intval( $client_fields['client_id'] ) : 0;
1422 +
1423 + if ( ! empty( $editing_client_id ) && ! wp_verify_nonce( $_POST['nonce_client_id'], 'editing-client-' . $editing_client_id ) ) { //phpcs:ignore -- NOSONAR - ok.
1424 + die( 'Invalid nonce!' );
1425 + }
1426 +
1017 1427 if ( ! isset( $client_fields['default_field']['client.name'] ) || empty( $client_fields['default_field']['client.name'] ) ) {
1018 1428 echo wp_json_encode( array( 'error' => esc_html__( 'Client name are empty. Please try again.', 'mainwp' ) ) );
1019 1429 return;
1020 1430 }
@@ -1044,8 +1454,24 @@
1044 1454 if ( isset( $client_to_add['created'] ) && ! empty( $client_to_add['created'] ) ) {
1045 1455 $client_to_add['created'] = strtotime( $client_to_add['created'] );
1046 1456 }
1047 1457 $add_new = false;
1458 +
1459 + $current_sites_ids = array();
1460 + $current_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $client_id, array( 'no_perm_check' => true ) );
1461 +
1462 + if ( ! empty( $current_sites ) ) {
1463 + $current_sites_ids = array_values(
1464 + array_map(
1465 + function ( $item ) {
1466 + return $item->id;
1467 + },
1468 + $current_sites
1469 + )
1470 + );
1471 + }
1472 +
1473 + $selected_sites = MainWP_System::get_selected_sites_with_allowed_sites( $selected_sites, $current_sites_ids );
1048 1474 } else {
1049 1475 $client_to_add['created'] = time();
1050 1476 }
1051 1477
@@ -1063,8 +1489,11 @@
1063 1489 $client_id = $inserted->client_id;
1064 1490 }
1065 1491
1066 1492 if ( is_object( $inserted ) ) {
1493 +
1494 + static::invalidate_warm_cache();
1495 +
1067 1496 /**
1068 1497 * Add client
1069 1498 *
1070 1499 * Fires after add a client.
@@ -1105,10 +1534,10 @@
1105 1534 $client_image = sanitize_text_field( wp_unslash( $_POST['mainwp_add_edit_client_uploaded_icon_hidden'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1106 1535 }
1107 1536
1108 1537 // compatible with quick setup.
1109 - if ( isset( $_FILES['mainwp_client_image_uploader'] ) && isset( $_FILES['mainwp_client_image_uploader']['error']['client_field'] ) && UPLOAD_ERR_OK === $_FILES['mainwp_client_image_uploader']['error']['client_field'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1110 - $output = MainWP_System_Utility::handle_upload_image( 'client-images', $_FILES['mainwp_client_image_uploader'], 'client_field' ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1538 + if ( isset( $_FILES['mainwp_client_image_uploader']['error']['client_field'] ) && UPLOAD_ERR_OK === $_FILES['mainwp_client_image_uploader']['error']['client_field'] ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1539 + $output = MainWP_System_Utility::handle_upload_image( 'client-images', $_FILES['mainwp_client_image_uploader'], 'client_field' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1111 1540 if ( is_array( $output ) && isset( $output['filename'] ) && ! empty( $output['filename'] ) ) {
1112 1541 $client_image = $output['filename'];
1113 1542 }
1114 1543 }
@@ -1145,11 +1574,11 @@
1145 1574 $contact_to_add = array();
1146 1575 if ( empty( $contact_name ) ) {
1147 1576 continue;
1148 1577 }
1149 - $contact_to_add['contact_name'] = $contact_name;
1578 + $contact_to_add['contact_name'] = sanitize_text_field( wp_unslash( $contact_name ) );
1150 1579
1151 - $contact_email = $client_fields['contacts_field']['contact.email'][ $indx ];
1580 + $contact_email = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.email'][ $indx ] ) );
1152 1581 if ( empty( $contact_email ) ) {
1153 1582 continue;
1154 1583 }
1155 1584
@@ -1158,16 +1587,22 @@
1158 1587 if ( empty( $contact_id ) ) {
1159 1588 continue;
1160 1589 }
1161 1590
1591 + $editing_contact_nonce_id = sanitize_key( $client_fields['contacts_field']['nonce_contact_id'][ $indx ] );
1592 +
1593 + if ( ! wp_verify_nonce( $editing_contact_nonce_id, 'editing-' . $client_id . '-contact-' . $contact_id ) ) {
1594 + continue;
1595 + }
1596 +
1162 1597 $contact_to_add['contact_email'] = $contact_email;
1163 1598
1164 - $contact_to_add['contact_phone'] = $client_fields['contacts_field']['contact.phone'][ $indx ];
1165 - $contact_to_add['contact_role'] = $client_fields['contacts_field']['contact.role'][ $indx ];
1166 - $contact_to_add['facebook'] = $client_fields['contacts_field']['contact.facebook'][ $indx ];
1167 - $contact_to_add['twitter'] = $client_fields['contacts_field']['contact.twitter'][ $indx ];
1168 - $contact_to_add['instagram'] = $client_fields['contacts_field']['contact.instagram'][ $indx ];
1169 - $contact_to_add['linkedin'] = $client_fields['contacts_field']['contact.linkedin'][ $indx ];
1599 + $contact_to_add['contact_phone'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.phone'][ $indx ] ) );
1600 + $contact_to_add['contact_role'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.role'][ $indx ] ) );
1601 + $contact_to_add['facebook'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.facebook'][ $indx ] ) );
1602 + $contact_to_add['twitter'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.twitter'][ $indx ] ) );
1603 + $contact_to_add['instagram'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.instagram'][ $indx ] ) );
1604 + $contact_to_add['linkedin'] = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.linkedin'][ $indx ] ) );
1170 1605
1171 1606 $cust_icon = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['selected_icon'][ $indx ] ) );
1172 1607 $cust_color = sanitize_hex_color( wp_unslash( $client_fields['contacts_field']['selected_color'][ $indx ] ) );
1173 1608
@@ -1276,8 +1711,21 @@
1276 1711 delete_transient( 'mainwp_transient_just_connected_site_id' );
1277 1712 }
1278 1713 //phpcs:enable
1279 1714
1715 + $snapshot_info = MainWP_DB_Client::instance()->get_clients_snapshot_info();
1716 +
1717 + /**
1718 + * Action: mainwp_insert_update_client
1719 + *
1720 + * @since 6.0
1721 + *
1722 + * @param int $client_id Client ID.
1723 + * @param bool $add_new True if adding a new client, false if updating an existing one.
1724 + * @param array $snapshot_info Snapshot information.
1725 + */
1726 + do_action( 'mainwp_insert_update_client', $client_id, $add_new, $snapshot_info );
1727 +
1280 1728 echo wp_json_encode(
1281 1729 array(
1282 1730 'success' => 'yes',
1283 1731 'client_id' => $client_id,
@@ -1285,8 +1733,15 @@
1285 1733 );
1286 1734 }
1287 1735
1288 1736 /**
1737 + * Method invalidate_warm_cache()
1738 + */
1739 + public static function invalidate_warm_cache() {
1740 + MainWP_Cache_Warm_Helper::invalidate_manage_pages( array( 'ManageClients', 'ClientAddField' ) );
1741 + }
1742 +
1743 + /**
1289 1744 * Method render_add_client_modal().
1290 1745 *
1291 1746 * Renders add client Modal window.
1292 1747 */
@@ -1345,23 +1800,34 @@
1345 1800 if ( ! empty( $client_image ) ) {
1346 1801 $uploaded_icon_src = MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'uploaded_icon' );
1347 1802 }
1348 1803
1804 + $field_groups = array(
1805 + 'client_info' => array( 'client.name', 'client.email', 'client.suspended' ),
1806 + 'contact_details' => array( 'client.phone', 'client.contact.address.1', 'client.contact.address.2', 'client.city', 'client.state', 'client.zip', 'client.country' ),
1807 + 'social_links' => array( 'client.facebook', 'client.twitter', 'client.instagram', 'client.linkedin' ),
1808 + 'notes_meta' => array( 'client.note', 'client.created' ),
1809 + );
1810 +
1349 1811 ?>
1350 - <h3 class="ui dividing header">
1351 - <?php if ( $client_id ) : ?>
1352 - <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-edit-client' ); ?>
1353 - <?php echo esc_html__( 'Edit Client', 'mainwp' ); ?>
1354 - <div class="sub header"><?php esc_html_e( 'Edit client information.', 'mainwp' ); ?></div>
1355 - <?php else : ?>
1356 - <?php esc_html_e( 'Add New Client', 'mainwp' ); ?>
1357 - <div class="sub header"><?php esc_html_e( 'Enter the client information.', 'mainwp' ); ?></div>
1358 - <?php endif; ?>
1359 - </h3>
1360 1812 <div class="ui form">
1813 + <input type="hidden" name="nonce_client_id" value="<?php echo esc_attr( wp_create_nonce( 'editing-client-' . $client_id ) ); ?>">
1814 +
1815 + <div class="ui basic accordion mainwp-blank-accordion mainwp-sidebar-accordion" id="mainwp-client-info-accordion">
1816 + <h2 class="ui dividing header active title">
1817 + <i class="right dropdown icon"></i>
1818 + <?php esc_html_e( 'Client Info', 'mainwp' ); ?>
1819 + <div class="sub header">
1820 + <?php esc_html_e( 'Set the basics used to identify this client in your dashboard, name and email are primary, logo is optional, and status controls whether they\'re active.', 'mainwp' ); ?>
1821 + </div>
1822 + </h2>
1823 + <div class="content active">
1361 1824 <?php
1362 -
1363 - foreach ( $default_client_fields as $field_name => $field ) {
1825 + foreach ( $field_groups['client_info'] as $field_name ) {
1826 + if ( ! isset( $default_client_fields[ $field_name ] ) ) {
1827 + continue;
1828 + }
1829 + $field = $default_client_fields[ $field_name ];
1364 1830 $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
1365 1831 $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
1366 1832 $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
1367 1833 ?>
@@ -1370,22 +1836,20 @@
1370 1836 <?php
1371 1837 $indi_val = $val && $edit_client ? 1 : 0;
1372 1838 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1373 1839 echo esc_html( $field['title'] );
1840 + if ( ! empty( $field['required'] ) ) {
1841 + echo ' <span class="ui small red text">' . esc_html__( '(Required)', 'mainwp' ) . '</span>';
1842 + }
1374 1843 ?>
1375 1844 </label>
1376 1845 <div class="ui six wide column">
1377 1846 <div class="ui left labeled input">
1378 1847 <?php
1379 - if ( 'client.note' === $field_name ) {
1848 + if ( 'client.suspended' === $field_name ) {
1849 + $el_id_fln_2 = $field_name;
1380 1850 ?>
1381 - <div class="editor">
1382 - <textarea class="code settings-field-value-change-handler" cols="80" rows="10" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"><?php echo esc_html( $val ); ?></textarea>
1383 - </div>
1384 - <?php
1385 - } elseif ( 'client.suspended' === $field_name ) {
1386 - ?>
1387 - <select class="ui dropdown settings-field-value-change-handler" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" >
1851 + <select class="ui dropdown settings-field-value-change-handler" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" id="client_fields[default_field][<?php echo esc_attr( $el_id_fln_2 ); ?>]" >
1388 1852 <option value="0" <?php echo '0' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Active', 'mainwp' ); ?></option>
1389 1853 <option value="1" <?php echo '1' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Suspended', 'mainwp' ); ?></option>
1390 1854 <option value="2" <?php echo '2' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lead', 'mainwp' ); ?></option>
1391 1855 <option value="3" <?php echo '3' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lost', 'mainwp' ); ?></option>
@@ -1390,18 +1854,8 @@
1390 1854 <option value="2" <?php echo '2' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lead', 'mainwp' ); ?></option>
1391 1855 <option value="3" <?php echo '3' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lost', 'mainwp' ); ?></option>
1392 1856 </select>
1393 1857 <?php
1394 - } elseif ( $client_id && 'client.created' === $field_name ) {
1395 - $created = empty( $val ) ? time() : $val;
1396 - ?>
1397 - <div class="ui calendar mainwp_datepicker" >
1398 - <div class="ui input left icon">
1399 - <i class="calendar icon"></i>
1400 - <input type="text" autocomplete="off" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" placeholder="<?php esc_attr_e( 'Added date', 'mainwp' ); ?>" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" value="<?php echo esc_attr( date( 'Y-m-d', $created ) ); // phpcs:ignore -- local time. ?>"/>
1401 - </div>
1402 - </div>
1403 - <?php
1404 1858 } else {
1405 1859 ?>
1406 1860 <input type="text" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" class="regular-text settings-field-value-change-handler" value="<?php echo esc_html( $val ); ?>" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"/>
1407 1861 <?php
@@ -1416,30 +1870,38 @@
1416 1870 <?php } ?>
1417 1871 </div>
1418 1872 <?php endif; ?>
1419 1873 </div>
1420 - <?php
1421 1874
1422 - if ( 'client.email' === $field_name ) {
1423 - ?>
1875 + <?php if ( 'client.email' === $field_name ) { ?>
1424 1876 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1425 1877 <label class="six wide column middle aligned">
1426 1878 <?php
1427 1879 $indi_val = $client_image && $edit_client ? 1 : 0;
1428 1880 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1881 + $delnonce = MainWP_System_Utility::get_custom_nonce( 'client', esc_attr( $client_image ) );
1429 1882 ?>
1430 - <?php esc_html_e( 'Client photo', 'mainwp' ); ?>
1883 + <?php esc_html_e( 'Client logo (photo)', 'mainwp' ); ?>
1431 1884 </label>
1432 1885 <input type="hidden" name="mainwp_add_edit_client_uploaded_icon_hidden" class="settings-field-value-change-handler" id="mainwp_add_edit_client_uploaded_icon_hidden" value="<?php echo esc_attr( $client_image ); ?>">
1433 - <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Upload a client photo.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1434 - <div class="ui green button basic mainwp-add-edit-client-icon-customable" iconItemId="<?php echo intval( $client_id ); ?>" iconFileSlug="<?php echo esc_attr( $client_image ); ?>" icon-src="<?php echo esc_attr( $uploaded_icon_src ); ?>"><?php esc_html_e( 'Upload Icon', 'mainwp' ); ?></div>
1435 - <?php if ( ! empty( $client_image ) ) { ?>
1436 - <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'display_edit' ); //phpcs:ignore --ok. ?>
1437 - <?php } else { ?>
1438 - <div style="display:inline-block;" id="mainwp_add_edit_client_upload_custom_icon"></div> <?php // used for icon holder. ?>
1439 - <?php } ?>
1886 + <div class="ui six wide column">
1887 + <span class="ui circular bordered image">
1888 + <?php if ( ! empty( $client_image ) ) { ?>
1889 + <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'display_edit' ); //phpcs:ignore --ok. ?>
1890 + <?php } else { ?>
1891 + <div style="display:inline-block;" id="mainwp_add_edit_client_upload_custom_icon"></div> <?php // used for icon holder. ?>
1892 + <?php } ?>
1893 + </span>
1894 + <div class="ui basic button mainwp-add-edit-client-icon-customable"
1895 + iconItemId="<?php echo intval( $client_id ); ?>"
1896 + iconFileSlug="<?php echo esc_attr( $client_image ); ?>"
1897 + del-icon-nonce="<?php echo esc_attr( $delnonce ); ?>"
1898 + icon-src="<?php echo esc_attr( $uploaded_icon_src ); ?>">
1899 + <i class="image icon"></i> <?php echo ! empty( $client_image ) ? esc_html__( 'Change Image', 'mainwp' ) : esc_html__( 'Upload Image', 'mainwp' ); ?>
1900 + </div>
1440 1901 </div>
1441 1902 </div>
1903 +
1442 1904 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client" default-indi-indi-value="wordpress">
1443 1905 <label class="six wide column middle aligned">
1444 1906 <?php
1445 1907 $default_icons = MainWP_UI::get_default_icons();
@@ -1476,21 +1938,185 @@
1476 1938 </div>
1477 1939 <div class="one wide column"></div>
1478 1940 </div>
1479 1941 <?php
1942 + }
1943 + }
1944 + ?>
1945 + </div>
1946 + </div>
1947 +
1948 + <div class="ui basic accordion mainwp-blank-accordion mainwp-sidebar-accordion" id="mainwp-contact-details-accordion">
1949 + <h2 class="ui dividing header active title">
1950 + <i class="right dropdown icon"></i>
1951 + <?php esc_html_e( 'Contact Details', 'mainwp' ); ?>
1952 + <div class="sub header">
1953 + <?php esc_html_e( 'Add the best ways to reach the client and where they\'re located. Include phone and full address details to keep records consistent.', 'mainwp' ); ?>
1954 + </div>
1955 + </h2>
1956 + <div class="content active">
1957 + <?php
1958 + foreach ( $field_groups['contact_details'] as $field_name ) {
1959 + if ( ! isset( $default_client_fields[ $field_name ] ) ) {
1960 + continue;
1961 + }
1962 + $field = $default_client_fields[ $field_name ];
1963 + $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
1964 + $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
1965 + $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
1966 + ?>
1967 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1968 + <label class="six wide column middle aligned" for="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" <?php echo ! empty( $tip ) ? 'data-tooltip="' . esc_attr( $tip ) . '" data-inverted="" data-position="top left"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>>
1969 + <?php
1970 + $indi_val = $val && $edit_client ? 1 : 0;
1971 + MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1972 + echo esc_html( $field['title'] );
1973 + if ( ! empty( $field['required'] ) ) {
1974 + echo ' <span class="ui small red text">' . esc_html__( '(Required)', 'mainwp' ) . '</span>';
1480 1975 }
1976 + ?>
1977 + </label>
1978 + <div class="ui six wide column">
1979 + <div class="ui left labeled input">
1980 + <input type="text" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" class="regular-text settings-field-value-change-handler" value="<?php echo esc_html( $val ); ?>" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"/>
1981 + </div>
1982 + </div>
1983 + <?php if ( $client_id ) : ?>
1984 + <div class="ui four wide middle aligned hidden token column" style="display:none">
1985 + [<?php echo esc_html( $field_name ); ?>]
1986 + </div>
1987 + <?php endif; ?>
1988 + </div>
1989 + <?php
1481 1990 }
1991 + ?>
1992 + </div>
1993 + </div>
1482 1994
1995 + <div class="ui basic accordion mainwp-blank-accordion mainwp-sidebar-accordion" id="mainwp-social-links-accordion">
1996 + <h2 class="ui dividing header active title">
1997 + <i class="right dropdown icon"></i>
1998 + <?php esc_html_e( 'Social Links', 'mainwp' ); ?>
1999 + <div class="sub header">
2000 + <?php esc_html_e( 'Link the client\'s public profiles for quick access. Paste full URLs (including https://) and leave anything you don\'t use blank.', 'mainwp' ); ?>
2001 + </div>
2002 + </h2>
2003 + <div class="content active">
2004 + <?php
2005 + foreach ( $field_groups['social_links'] as $field_name ) {
2006 + if ( ! isset( $default_client_fields[ $field_name ] ) ) {
2007 + continue;
2008 + }
2009 + $field = $default_client_fields[ $field_name ];
2010 + $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
2011 + $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
2012 + $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
2013 + ?>
2014 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
2015 + <label class="six wide column middle aligned" for="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" <?php echo ! empty( $tip ) ? 'data-tooltip="' . esc_attr( $tip ) . '" data-inverted="" data-position="top left"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>>
2016 + <?php
2017 + $indi_val = $val && $edit_client ? 1 : 0;
2018 + MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2019 + echo esc_html( $field['title'] );
2020 + if ( ! empty( $field['required'] ) ) {
2021 + echo ' <span class="ui small red text">' . esc_html__( '(Required)', 'mainwp' ) . '</span>';
2022 + }
2023 + ?>
2024 + </label>
2025 + <div class="ui six wide column">
2026 + <div class="ui left labeled input">
2027 + <input type="text" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" class="regular-text settings-field-value-change-handler" value="<?php echo esc_html( $val ); ?>" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"/>
2028 + </div>
2029 + </div>
2030 + <?php if ( $client_id ) : ?>
2031 + <div class="ui four wide middle aligned hidden token column" style="display:none">
2032 + [<?php echo esc_html( $field_name ); ?>]
2033 + </div>
2034 + <?php endif; ?>
2035 + </div>
2036 + <?php
2037 + }
2038 + ?>
2039 + </div>
2040 + </div>
2041 +
2042 + <div class="ui basic accordion mainwp-blank-accordion mainwp-sidebar-accordion" id="mainwp-notes-meta-accordion">
2043 + <h2 class="ui dividing header active title">
2044 + <i class="right dropdown icon"></i>
2045 + <?php esc_html_e( 'Notes & Meta', 'mainwp' ); ?>
2046 + <div class="sub header">
2047 + <?php esc_html_e( 'Store internal context for your team, notes, when the client was added, and any extra contact details that don\'t fit elsewhere.', 'mainwp' ); ?>
2048 + </div>
2049 + </h2>
2050 + <div class="content active">
2051 + <?php
2052 + foreach ( $field_groups['notes_meta'] as $field_name ) {
2053 + if ( ! isset( $default_client_fields[ $field_name ] ) ) {
2054 + continue;
2055 + }
2056 + $field = $default_client_fields[ $field_name ];
2057 + $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
2058 + $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
2059 + $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
2060 + ?>
2061 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
2062 + <label class="six wide column middle aligned" for="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" <?php echo ! empty( $tip ) ? 'data-tooltip="' . esc_attr( $tip ) . '" data-inverted="" data-position="top left"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>>
2063 + <?php
2064 + $indi_val = $val && $edit_client ? 1 : 0;
2065 + MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2066 + echo esc_html( $field['title'] );
2067 + if ( ! empty( $field['required'] ) ) {
2068 + echo ' <span class="ui small red text">' . esc_html__( '(Required)', 'mainwp' ) . '</span>';
2069 + }
2070 + ?>
2071 + </label>
2072 + <div class="ui six wide column">
2073 + <div class="ui left labeled input">
2074 + <?php
2075 + if ( 'client.note' === $field_name ) {
2076 + $el_id_fln_1 = $field_name;
2077 + ?>
2078 + <div class="editor">
2079 + <textarea class="code settings-field-value-change-handler" cols="80" rows="10" id="client_fields[default_field][<?php echo esc_attr( $el_id_fln_1 ); ?>]" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"><?php echo esc_html( $val ); ?></textarea>
2080 + </div>
2081 + <?php
2082 + } elseif ( $client_id && 'client.created' === $field_name ) {
2083 + $created = empty( $val ) ? time() : $val;
2084 + ?>
2085 + <div class="ui calendar mainwp_datepicker" >
2086 + <div class="ui input left icon">
2087 + <i class="calendar icon"></i>
2088 + <input type="text" autocomplete="off" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" placeholder="<?php esc_attr_e( 'Added date', 'mainwp' ); ?>" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" value="<?php echo esc_attr( date( 'Y-m-d', $created ) ); // phpcs:ignore -- local time. ?>"/>
2089 + </div>
2090 + </div>
2091 + <?php
2092 + } else {
2093 + ?>
2094 + <input type="text" id="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]" class="regular-text settings-field-value-change-handler" value="<?php echo esc_html( $val ); ?>" name="client_fields[default_field][<?php echo esc_attr( $field_name ); ?>]"/>
2095 + <?php
2096 + }
2097 + ?>
2098 + </div>
2099 + </div>
2100 + <?php if ( $client_id ) : ?>
2101 + <div class="ui four wide middle aligned hidden token column" style="display:none">
2102 + [<?php echo esc_html( $field_name ); ?>]
2103 + </div>
2104 + <?php endif; ?>
2105 + </div>
2106 + <?php
2107 + }
2108 +
1483 2109 $client_contacts = array();
1484 2110 if ( $client_id ) {
1485 2111 $client_contacts = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'client_id', $client_id );
1486 2112 ?>
1487 - <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
2113 + <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1488 2114 <label class="six wide column middle aligned">
1489 2115 <?php
1490 2116 $indi_val = $edit_client && $client_contacts ? 1 : 0;
1491 2117 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1492 - echo esc_html_e( 'Client primary contact', 'mainwp' );
2118 + esc_html_e( 'Client primary contact', 'mainwp' );
1493 2119 ?>
1494 2120 </label>
1495 2121 <div class="ui six wide column">
1496 2122 <div class="ui left labeled">
@@ -1542,10 +2168,10 @@
1542 2168 </div>
1543 2169 </div>
1544 2170 <div class="ui four wide column">
1545 2171 <?php if ( $client_id > 0 && $field->client_id > 0 ) { // edit client and it is individual field, then show to edit/delete field buttons. ?>
1546 - <div class="ui left pointing dropdown icon mini basic green button">
1547 - <i class="ellipsis horizontal icon"></i>
2172 + <div class="ui right pointing dropdown">
2173 + <i class="ellipsis vertical icon"></i>
1548 2174 <div class="menu">
1549 2175 <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
1550 2176 <a class="item" client-id="<?php echo intval( $client_id ); ?>" id="mainwp-clients-delete-individual-field" href="#"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1551 2177 </div>
@@ -1561,9 +2187,9 @@
1561 2187 $temp = static::get_add_contact_temp( false, false );
1562 2188
1563 2189 if ( $client_id && $client_contacts ) {
1564 2190 foreach ( $client_contacts as $client_contact ) {
1565 - static::get_add_contact_temp( $client_contact, true );
2191 + static::get_add_contact_temp( $client_contact, true, $client_id );
1566 2192 }
1567 2193 }
1568 2194 ?>
1569 2195 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
@@ -1569,17 +2195,21 @@
1569 2195 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1570 2196 <label class="six wide column middle aligned"><?php esc_html_e( 'Create a new contact for this client', 'mainwp' ); ?></label>
1571 2197 <div class="ui six wide column">
1572 2198 <div class="ui left labeled input">
1573 - <a href="javascript:void(0);" class="ui green button mainwp-client-add-contact" add-contact-temp="<?php echo esc_attr( $temp ); ?>"><?php esc_html_e( 'Add Additional Contact', 'mainwp' ); ?></a>
2199 + <a href="javascript:void(0);" class="ui basic button mainwp-client-add-contact" add-contact-temp="<?php echo esc_attr( $temp ); ?>"><i class="user icon"></i><?php esc_html_e( 'Add Contact', 'mainwp' ); ?></a>
1574 2200 </div>
1575 2201 </div>
1576 2202 </div>
1577 2203 <div class="ui section hidden divider after-add-contact-field"></div>
2204 + </div>
2205 + </div>
1578 2206 </div>
1579 2207 <input type="hidden" name="client_fields[client_id]" value="<?php echo intval( $client_id ); ?>">
1580 2208 <script type="text/javascript">
1581 2209 jQuery( document ).ready( function () {
2210 + mainwp_sidebar_accordion_init();
2211 +
1582 2212 // to fix issue not loaded calendar js library
1583 2213 if (jQuery('.ui.calendar').length > 0) {
1584 2214 if (mainwpParams.use_wp_datepicker == 1) {
1585 2215 jQuery('#mainwp-add-new-client-form .ui.calendar input[type=text]').datepicker({ dateFormat: "yy-mm-dd" });
@@ -1658,8 +2288,9 @@
1658 2288 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
1659 2289 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
1660 2290 iconObj.attr('icon-src', icon_src);
1661 2291 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2292 + iconObj.attr('del-icon-nonce', response.iconnonce);
1662 2293 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
1663 2294 jQuery('#mainwp_add_edit_client_upload_custom_icon').html(icon_img);
1664 2295 jQuery('#mainwp_add_edit_client_upload_custom_icon').show();
1665 2296 }
@@ -1664,10 +2295,9 @@
1664 2295 jQuery('#mainwp_add_edit_client_upload_custom_icon').show();
1665 2296 }
1666 2297 }
1667 2298 setTimeout(function () {
1668 - //window.location.href = location.href;
1669 - jQuery('#mainwp-upload-custom-icon-modal').modal('hide')
2299 + jQuery('#mainwp-upload-custom-icon-modal').modal('hide');
1670 2300 }, 1000);
1671 2301 });
1672 2302 return false;
1673 2303 }
@@ -1697,14 +2327,14 @@
1697 2327 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
1698 2328 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
1699 2329 iconObj.attr('icon-src', icon_src);
1700 2330 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2331 + iconObj.attr('del-icon-nonce', response.iconnonce);
1701 2332 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
1702 2333 jQuery(parent).find('.mainwp_add_edit_contact_upload_custom_icon').html(icon_img).show();
1703 2334 }
1704 2335 }
1705 2336 setTimeout(function () {
1706 - //window.location.href = location.href;
1707 2337 jQuery('#mainwp-upload-custom-icon-modal').modal('hide')
1708 2338 }, 1000);
1709 2339 });
1710 2340 return false;
@@ -1735,11 +2365,11 @@
1735 2365 if ( empty( $color ) ) {
1736 2366 $color = '#34424D';
1737 2367 }
1738 2368
1739 - $icon_cls = 'large icon custom-icon';
2369 + $icon_cls = 'circular inverted icon';
1740 2370 if ( 'card' === $what ) {
1741 - $icon_cls = 'icon huge custom-icon';
2371 + $icon_cls = 'huge circular inverted icon';
1742 2372 }
1743 2373
1744 2374 $output = '';
1745 2375 if ( 'selected' === $type ) {
@@ -1748,15 +2378,15 @@
1748 2378 $output = $color;
1749 2379 } elseif ( 'display' === $type || 'display_edit' === $what ) {
1750 2380 $color_style = '';
1751 2381 if ( ! empty( $color ) ) {
1752 - $color_style = 'color:' . esc_attr( $color ) . ';';
2382 + $color_style = 'background-color:' . esc_attr( $color ) . ';';
1753 2383 }
1754 2384 $icon_wrapper_attr = 'class="mainwp_client_icon_display"';
1755 2385 if ( 'display_edit' === $what ) {
1756 2386 $icon_wrapper_attr = ' id="mainwp_add_edit_client_upload_custom_icon" ' . $icon_wrapper_attr;
1757 2387 }
1758 - $output = '<div style="display:inline-block;' . $color_style . '" ' . $icon_wrapper_attr . ' ><i class="' . esc_attr( $selected_icon ) . ' ' . $icon_cls . '" ></i></div>';
2388 + $output = '<div style="display:inline-block;" ' . $icon_wrapper_attr . ' ><i class="' . esc_attr( $selected_icon ) . ' ' . $icon_cls . '" style="' . $color_style . '"></i></div>';
1759 2389 }
1760 2390 return $output;
1761 2391 }
1762 2392
@@ -1766,10 +2396,11 @@
1766 2396 * Get add contact template.
1767 2397 *
1768 2398 * @param mixed $edit_contact The contact data to edit.
1769 2399 * @param bool $echo_out Echo template or not.
2400 + * @param int $client_id Client id.
1770 2401 */
1771 - public static function get_add_contact_temp( $edit_contact = false, $echo_out = false ) { //phpcs:ignore -- NOSONAR - complex.
2402 + public static function get_add_contact_temp( $edit_contact = false, $echo_out = false, $client_id = 0 ) { //phpcs:ignore -- NOSONAR - complex.
1772 2403
1773 2404 $input_name = 'new_contacts_field';
1774 2405 $contact_id = 0;
1775 2406 $contact_image = '';
@@ -1813,8 +2444,11 @@
1813 2444 <?php
1814 2445 $indi_val = $edit_contact && $val ? 1 : 0;
1815 2446 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1816 2447 echo esc_html( $field['title'] );
2448 + if ( ! empty( $field['required'] ) ) {
2449 + echo ' <span class="ui small red text">' . esc_html__( '(Required)', 'mainwp' ) . '</span>';
2450 + }
1817 2451 ?>
1818 2452 </label>
1819 2453 <div class="ui six wide column">
1820 2454 <div class="ui left labeled input">
@@ -1834,14 +2468,15 @@
1834 2468 <label class="six wide column middle aligned">
1835 2469 <?php
1836 2470 $indi_val = $edit_contact && $contact_image ? 1 : 0;
1837 2471 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2472 + $delnonce = MainWP_System_Utility::get_custom_nonce( 'contact', esc_attr( $contact_image ) );
1838 2473 ?>
1839 2474 <?php esc_html_e( 'Contact photo', 'mainwp' ); ?>
1840 2475 </label>
1841 2476 <input type="hidden" name="mainwp_add_edit_contact_uploaded_icon_hidden[<?php echo esc_html( $input_name ); ?>][]" class="settings-field-value-change-handler mainwp_add_edit_contact_uploaded_icon_hidden" value="<?php echo esc_attr( $contact_image ); ?>">
1842 2477 <div class="three wide middle aligned column" data-tooltip="<?php esc_attr_e( 'Upload a contact photo.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1843 - <div class="ui green button basic mainwp-add-edit-contact-icon-customable" iconItemId="<?php echo intval( $contact_id ); ?>" iconFileSlug="<?php echo esc_attr( $contact_image ); ?>" icon-src="<?php echo esc_attr( $uploaded_icon_src ); ?>"><?php esc_html_e( 'Upload Icon', 'mainwp' ); ?></div>
2478 + <div class="ui green button basic mainwp-add-edit-contact-icon-customable" iconItemId="<?php echo intval( $contact_id ); ?>" iconFileSlug="<?php echo esc_attr( $contact_image ); ?>" del-icon-nonce="<?php echo esc_attr( $delnonce ); ?>" icon-src="<?php echo esc_attr( $uploaded_icon_src ); ?>"><?php esc_html_e( 'Upload Icon', 'mainwp' ); ?></div>
1844 2479 <?php
1845 2480 if ( ! empty( $contact_image ) ) {
1846 2481 ?>
1847 2482 <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'contact', 'display_edit' ); //phpcs:ignore --ok. ?>
@@ -1898,10 +2533,11 @@
1898 2533 </div>
1899 2534 <?php
1900 2535 if ( $edit_contact ) {
1901 2536 ?>
1902 - <input type="hidden" value="<?php echo intval( $edit_contact->contact_id ); ?>" name="client_fields[contacts_field][contact_id][]"/>
1903 - <?php
2537 + <input type="hidden" value="<?php echo intval( $edit_contact->contact_id ); ?>" name="client_fields[contacts_field][contact_id][]"/>
2538 + <input type="hidden" value="<?php echo esc_attr( wp_create_nonce( 'editing-' . $client_id . '-contact-' . $edit_contact->contact_id ) ); ?>" name="client_fields[contacts_field][nonce_contact_id][]"/>
2539 + <?php
1904 2540 }
1905 2541 ?>
1906 2542 </div>
1907 2543 </div>
@@ -2000,9 +2636,16 @@
2000 2636 'client_id' => intval( $_POST['clientid'] ), // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2001 2637 'note' => $esc_note,
2002 2638 );
2003 2639 MainWP_DB_Client::instance()->update_client( $update );
2004 - die( wp_json_encode( array( 'result' => 'SUCCESS' ) ) );
2640 + die(
2641 + wp_json_encode(
2642 + array(
2643 + 'result' => 'SUCCESS',
2644 + 'esc_note_content' => $esc_note,
2645 + )
2646 + )
2647 + );
2005 2648 }
2006 2649 die( wp_json_encode( array( 'undefined_error' => true ) ) );
2007 2650 }
2008 2651 }