PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
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 -274 5.1 → 6.2.2 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()
@@ -71,9 +76,8 @@
71 76 * @see \MainWP_client::render_footer
72 77 */
73 78 add_action( 'mainwp_pagefooter_client', array( static::get_class_name(), 'render_footer' ) );
74 79
75 - add_action( 'mainwp_help_sidebar_content', array( static::get_class_name(), 'mainwp_help_content' ) );
76 80 MainWP_Post_Handler::instance()->add_action( 'mainwp_add_edit_client_upload_client_icon', array( static::class, 'ajax_upload_client_icon' ) );
77 81 MainWP_Post_Handler::instance()->add_action( 'mainwp_add_edit_contact_upload_contact_icon', array( static::class, 'ajax_upload_contact_icon' ) );
78 82 }
79 83
@@ -111,8 +115,20 @@
111 115
112 116 add_submenu_page(
113 117 'mainwp_tab',
114 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' ),
115 131 '<div class="mainwp-hidden">' . esc_html__( 'Client Fields', 'mainwp' ) . '</div>',
116 132 'read',
117 133 'ClientAddField',
118 134 array(
@@ -186,14 +202,17 @@
186 202 <div id="menu-mainwp-Clients" class="mainwp-submenu-wrapper">
187 203 <div class="wp-submenu sub-open" style="">
188 204 <div class="mainwp_boxout">
189 205 <div class="mainwp_boxoutin"></div>
190 - <?php if ( mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) { ?>
206 + <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) { ?>
191 207 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ManageClients' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Clients', 'mainwp' ); ?></a>
192 208 <?php } ?>
193 209 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddNew' ) ) { ?>
194 210 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddNew' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Add Client', 'mainwp' ); ?></a>
195 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 } ?>
196 215 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) { ?>
197 216 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddField' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Client Properties', 'mainwp' ); ?></a>
198 217 <?php } ?>
199 218 <?php
@@ -253,14 +272,22 @@
253 272 'right' => '',
254 273 'leftsub_order_level2' => 2,
255 274 ),
256 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(
257 284 'title' => esc_html__( 'Client Fields', 'mainwp' ),
258 285 'parent_key' => 'ManageClients',
259 286 'href' => 'admin.php?page=ClientAddField',
260 287 'slug' => 'ClientAddField',
261 288 'right' => '',
262 - 'leftsub_order_level2' => 3,
289 + 'leftsub_order_level2' => 4,
263 290 ),
264 291 );
265 292
266 293 MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'ManageClients', 'ManageClients' );
@@ -282,10 +309,14 @@
282 309 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
283 310 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
284 311 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
285 312 $client_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
313 + $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
286 314
287 315 if ( $delete ) {
316 + if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'client', $iconfile_slug, $delnonce ) ) {
317 + die( 'Invalid nonce!' );
318 + }
288 319 if ( $client_id ) {
289 320 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
290 321 if ( $client && ! empty( $client->image ) ) {
291 322 $update = array(
@@ -314,17 +345,25 @@
314 345 $icon_url = $dirs[1] . $uploaded_icon;
315 346 wp_die(
316 347 wp_json_encode(
317 348 array(
318 - 'result' => 'success',
319 - 'iconfile' => esc_html( $uploaded_icon ),
320 - 'iconsrc' => esc_html( $icon_url ),
321 - '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 ) ),
322 354 )
323 355 )
324 356 );
325 357 } else {
326 - 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 ) );
327 366 }
328 367 }
329 368
330 369
@@ -336,10 +375,14 @@
336 375 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
337 376 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
338 377 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
339 378 $contact_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
379 + $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
340 380
341 381 if ( $delete ) {
382 + if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'contact', $iconfile_slug, $delnonce ) ) {
383 + die( 'Invalid nonce!' );
384 + }
342 385 if ( $contact_id ) {
343 386 $contact_data = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'contact_id', $contact_id );
344 387 if ( $contact_data && ! empty( $contact_data->contact_image ) ) {
345 388 $update = array(
@@ -368,17 +411,25 @@
368 411 $icon_url = $dirs[1] . $uploaded_icon;
369 412 wp_die(
370 413 wp_json_encode(
371 414 array(
372 - 'result' => 'success',
373 - 'iconfile' => esc_html( $uploaded_icon ),
374 - 'iconsrc' => esc_html( $icon_url ),
375 - '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 ) ),
376 420 )
377 421 )
378 422 );
379 423 } else {
380 - 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 ) );
381 432 }
382 433 }
383 434
384 435
@@ -407,9 +458,9 @@
407 458 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
408 459 if ( $client ) {
409 460 $arr_client = MainWP_Utility::map_fields( $client, array( 'image', 'selected_icon_info' ), false ); // array map.
410 461 $client_pic = MainWP_Client_Handler::get_client_contact_image( $arr_client );
411 - $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>';
412 463 }
413 464 }
414 465
415 466 MainWP_UI::render_top_header( $params );
@@ -415,9 +466,9 @@
415 466 MainWP_UI::render_top_header( $params );
416 467
417 468 $renderItems = array();
418 469
419 - if ( mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) {
470 + if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
420 471 $renderItems[] = array(
421 472 'title' => esc_html__( 'Clients', 'mainwp' ),
422 473 'href' => 'admin.php?page=ManageClients',
423 474 'active' => ( '' === $shownPage ) ? true : false,
@@ -425,9 +476,9 @@
425 476 }
426 477
427 478 if ( $client_id ) {
428 479 $renderItems[] = array(
429 - 'title' => $client ? $client->name : esc_html__( 'Overview', 'mainwp' ),
480 + 'title' => $client ? $client->name : esc_html__( 'Operations', 'mainwp' ),
430 481 'href' => 'admin.php?page=ManageClients&client_id=' . $client_id,
431 482 'active' => ( 'overview' === $shownPage ),
432 483 );
433 484 $renderItems[] = array(
@@ -444,8 +495,16 @@
444 495 'active' => ( 'Add' === $shownPage ) ? true : false,
445 496 );
446 497 }
447 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 +
448 507 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) {
449 508 $renderItems[] = array(
450 509 'title' => esc_html__( 'Client Fields', 'mainwp' ),
451 510 'href' => 'admin.php?page=ClientAddField',
@@ -495,32 +554,76 @@
495 554 MainWP_Client_Overview::instance()->on_show_page( intval( $_GET['client_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
496 555 return;
497 556 }
498 557
499 - if ( ! mainwp_current_user_have_right( 'dashboard', 'manage_clients' ) ) {
500 - 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' ) );
501 560 return;
502 561 }
503 562
504 563 static::$itemsTable->prepare_items();
505 564
565 + $has_no_clients = ( 0 === static::$itemsTable->total_items );
566 +
506 567 static::render_header( '' );
507 - static::render_second_top_header();
508 568
569 + if ( ! $has_no_clients ) {
570 + static::render_second_top_header();
571 + }
572 +
509 573 ?>
510 - <div id="mainwp-manage-sites-content" class="ui segment">
511 - <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
512 - <form method="post" class="mainwp-table-container">
513 - <?php
514 - wp_nonce_field( 'mainwp-admin-nonce' );
515 - static::$itemsTable->display();
516 - static::$itemsTable->clear_items();
517 - ?>
518 - </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; ?>
519 619 </div>
520 620 <?php
521 621 static::render_footer( '' );
522 - static::render_screen_options();
622 +
623 + if ( ! $has_no_clients ) {
624 + static::render_screen_options();
625 + }
523 626 }
524 627
525 628 /**
526 629 * Method render_second_top_header()
@@ -548,96 +651,95 @@
548 651 ?>
549 652 <div id="mainwp-edit-clients-modal" class="ui modal">
550 653 <i class="close icon"></i>
551 654 <div class="header"><?php esc_html_e( 'Edit client', 'mainwp' ); ?></div>
552 - <div class="ui message"><?php esc_html_e( 'Empty fields will not be passed to child sites.', 'mainwp' ); ?></div>
553 - <form id="update_client_profile">
554 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
555 - <div class="ui segment">
556 - <div class="ui form">
557 - <h3><?php esc_html_e( 'Name', 'mainwp' ); ?></h3>
558 - <div class="ui grid field">
559 - <label class="six wide column middle aligned"><?php esc_html_e( 'First Name', 'mainwp' ); ?></label>
560 - <div class="ui six wide column">
561 - <div class="ui left labeled input">
562 - <input type="text" name="first_name" id="first_name" value="" class="regular-text" />
563 - </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" />
564 665 </div>
565 666 </div>
667 + </div>
566 668
567 - <div class="ui grid field">
568 - <label class="six wide column middle aligned"><?php esc_html_e( 'Last Name', 'mainwp' ); ?></label>
569 - <div class="ui six wide column">
570 - <div class="ui left labeled input">
571 - <input type="text" name="last_name" id="last_name" value="" class="regular-text" />
572 - </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" />
573 674 </div>
574 675 </div>
676 + </div>
575 677
576 - <div class="ui grid field">
577 - <label class="six wide column middle aligned"><?php esc_html_e( 'Nickname', 'mainwp' ); ?></label>
578 - <div class="ui six wide column">
579 - <div class="ui left labeled input">
580 - <input type="text" name="nickname" id="nickname" value="" class="regular-text" />
581 - </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" />
582 683 </div>
583 684 </div>
685 + </div>
584 686
585 - <div class="ui grid field">
586 - <label class="six wide column middle aligned"><?php esc_html_e( 'Display name publicly as', 'mainwp' ); ?></label>
587 - <div class="ui six wide column">
588 - <div class="ui left labeled input">
589 - <select name="display_name" id="display_name"></select>
590 - </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>
591 692 </div>
592 693 </div>
694 + </div>
593 695
594 - <h3><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
696 + <h3 class="ui header"><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
595 697
596 - <div class="ui grid field">
597 - <label class="six wide column middle aligned"><?php esc_html_e( 'Email', 'mainwp' ); ?></label>
598 - <div class="ui six wide column">
599 - <div class="ui left labeled input">
600 - <input type="email" name="email" id="email" value="" class="regular-text ltr" />
601 - </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" />
602 703 </div>
603 704 </div>
705 + </div>
604 706
605 - <div class="ui grid field">
606 - <label class="six wide column middle aligned"><?php esc_html_e( 'Website', 'mainwp' ); ?></label>
607 - <div class="ui six wide column">
608 - <div class="ui left labeled input">
609 - <input type="url" name="url" id="url" value="" class="regular-text code" />
610 - </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" />
611 712 </div>
612 713 </div>
714 + </div>
613 715
614 - <h3><?php esc_html_e( 'About the client', 'mainwp' ); ?></h3>
716 + <h3 class="ui header"><?php esc_html_e( 'About the user', 'mainwp' ); ?></h3>
615 717
616 - <div class="ui grid field">
617 - <label class="six wide column middle aligned"><?php esc_html_e( 'Biographical Info', 'mainwp' ); ?></label>
618 - <div class="ui six wide column">
619 - <div class="ui left labeled input">
620 - <textarea name="description" id="description" rows="5" cols="30"></textarea>
621 - <p class="description"><?php esc_html_e( 'Share a little biographical information to fill out your profile. This may be shown publicly.', 'mainwp' ); ?></p>
622 - </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>
623 724 </div>
624 725 </div>
726 + </div>
625 727
626 - <h3><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
728 + <h3 class="ui header"><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
627 729
628 - <div class="ui grid field">
629 - <label class="six wide column middle aligned"><?php esc_html_e( 'Password', 'mainwp' ); ?></label>
630 - <div class="ui six wide column">
631 - <div class="ui left labeled action input">
632 - <input class="hidden" value=" "/>
633 - <input type="text" id="password" name="password" autocomplete="off" value="">
634 - </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="">
635 736 </div>
636 737 </div>
637 738 </div>
638 - </div>
639 - </form>
739 +
740 + </form>
741 + </div>
640 742 <div class="actions">
641 743 <div id="mainwp_update_password_error" style="display: none"></div>
642 744 <span id="mainwp_clients_updating"><i class="ui active inline loader tiny"></i></span>
643 745 <input type="button" class="ui green button" id="mainwp_btn_update_client" value="<?php esc_attr_e( 'Update', 'mainwp' ); ?>">
@@ -670,9 +772,13 @@
670 772
671 773 if ( false === $show_cols ) { // to backwards.
672 774 $show_cols = array();
673 775 foreach ( $columns as $name => $title ) {
674 - $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 + }
675 781 }
676 782 $user = wp_get_current_user();
677 783 if ( $user ) {
678 784 update_user_option( $user->ID, 'mainwp_settings_show_manage_clients_columns', $show_cols, true );
@@ -688,9 +794,9 @@
688 794 <i class="close icon"></i>
689 795 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
690 796 <div class="scrolling content ui form">
691 797 <form method="POST" action="" id="manage-sites-screen-options-form" name="manage_sites_screen_options_form">
692 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
798 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
693 799 <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'ManageClientsScrOptions' ) ); ?>" />
694 800 <div class="ui grid field">
695 801 <label class="six wide column"><?php esc_html_e( 'Default items per page value', 'mainwp' ); ?></label>
696 802 <div class="ten wide column">
@@ -750,9 +856,9 @@
750 856 </div>
751 857 <div class="ui small modal" id="mainwp-monitoring-sites-site-preview-screen-options-modal">
752 858 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
753 859 <div class="scrolling content ui form">
754 - <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' ); ?>
755 861 </div>
756 862 <div class="actions">
757 863 <div class="ui ok button"><?php esc_html_e( 'Yes', 'mainwp' ); ?></div>
758 864 <div class="ui cancel button"><?php esc_html_e( 'No', 'mainwp' ); ?></div>
@@ -772,13 +878,13 @@
772 878 } ).modal( 'show' );
773 879 }
774 880 } );
775 881 jQuery('#reset-manageclients-settings').on( 'click', function () {
776 - mainwp_confirm(__( 'Are you sure.' ), function(){
882 + mainwp_confirm(__( 'Are you sure?' ), function(){
777 883 jQuery('input[name=mainwp_default_manage_clients_per_page]').val(25);
778 884 jQuery('.mainwp_hide_wpmenu_checkboxes input[id^="mainwp_show_column_"]').prop( 'checked', false );
779 885 //default columns.
780 - let cols = ['name','email','phone','websites'];
886 + let cols = [ 'suspended','image','client','websites','contact_name','created'];
781 887 jQuery.each( cols, function ( index, value ) {
782 888 jQuery('.mainwp_hide_wpmenu_checkboxes input[id="mainwp_show_column_' + value + '"]').prop( 'checked', true );
783 889 } );
784 890 jQuery('input[name=reset_manageclients_columns_order]').attr('value',1);
@@ -816,27 +922,18 @@
816 922 static::render_header( $show );
817 923 ?>
818 924 <div class="ui alt segment" id="mainwp-add-clients">
819 925 <form action="" method="post" enctype="multipart/form-data" name="createclient_form" id="createclient_form" class="add:clients: validate">
820 - <?php wp_nonce_field( 'mainwp-admin-nonce' ); ?>
926 + <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
821 927 <div class="mainwp-main-content">
822 - <div class="ui segment">
823 - <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-add-client-info-message' ) ) : ?>
824 - <div class="ui info message">
825 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-add-client-info-message"></i>
826 - <?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>
827 933 </div>
828 - <?php endif; ?>
829 - <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
830 - <div id="mainwp-add-new-client-form" >
831 - <?php
832 - static::render_add_client_content( $edit_client );
833 - ?>
834 - </div>
835 934 </div>
836 - </div>
837 935 <div class="mainwp-side-content mainwp-no-padding">
838 -
839 936 <?php if ( $client_id ) : ?>
840 937 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
841 938 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Tokens Info', 'mainwp' ); ?></div>
842 939 <div class="content active">
@@ -881,10 +978,8 @@
881 978 </div>
882 979 </div>
883 980 <div style="clear:both"></div>
884 981 </form>
885 -
886 -
887 982 </div>
888 983 <?php
889 984 static::render_footer( $show );
890 985 static::render_add_field_modal( $client_id );
@@ -890,80 +985,388 @@
890 985 static::render_add_field_modal( $client_id );
891 986 MainWP_UI::render_modal_upload_icon();
892 987 }
893 988
894 -
895 989 /**
896 - * Renders the Add New Client Fields form.
990 + * Renders the Import Client form.
897 991 */
898 - 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
899 996
900 - 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 + }
901 1002 ?>
902 - <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>
903 1042 <?php
904 - $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 + }
905 1064 ?>
906 - <div class="ui info message" <?php echo ! MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-clients-manage-fields' ) ? 'style="display: none"' : ''; ?>>
907 - <?php esc_html_e( 'Create and manage custom Client fields.', 'mainwp' ); ?>
908 - <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>
909 1078 </div>
910 - <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
911 - <table id="mainwp-clients-custom-fields-table" class="ui selectable compact table" style="width:100%">
912 - <thead>
913 - <tr>
914 - <th scope="col" ><?php esc_html_e( 'Field Name', 'mainwp' ); ?></th>
915 - <th scope="col" ><?php esc_html_e( 'Field Description', 'mainwp' ); ?></th>
916 - <th scope="col" class="no-sort collapsing"><?php esc_html_e( '', 'mainwp' ); ?></th>
917 - </tr>
918 - </thead>
919 - <tbody>
920 - <?php if ( is_array( $fields ) && ! empty( $fields ) ) : ?>
921 - <?php foreach ( $fields as $field ) : ?>
922 - <?php
923 - if ( ! $field ) {
924 - 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();
925 1086 }
926 - ?>
927 - <tr class="mainwp-field none-selected-color" field-id="<?php echo intval( $field->field_id ); ?>">
928 - <td class="field-name">[<?php echo esc_html( stripslashes( $field->field_name ) ); ?>]</td>
929 - <td class="field-description"><?php echo esc_html( stripslashes( $field->field_desc ) ); ?></td>
930 - <td>
931 - <div class="ui right pointing dropdown icon mini basic green button">
932 - <i class="ellipsis horizontal icon"></i>
933 - <div class="menu">
934 - <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
935 - <a class="item" id="mainwp-clients-delete-general-field" href="#"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
936 - </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>
937 1265 </div>
938 - </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>
939 1307 </tr>
940 - <?php endforeach; ?>
941 - <?php endif; ?>
942 - </tbody>
943 - <tfoot>
944 - <tr>
945 - <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>
946 - <th scope="col" ><?php esc_html_e( '', 'mainwp' ); ?></th>
947 - <th scope="col" ><?php esc_html_e( '', 'mainwp' ); ?></th>
948 - </tr>
949 - </tfoot>
950 - </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>
951 1340
952 - <script type="text/javascript">
953 - // Init datatables
954 - jQuery( '#mainwp-clients-custom-fields-table' ).DataTable( {
955 - "stateSave": true,
956 - "stateDuration": 0,
957 - "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
958 - "columnDefs": [ { "orderable": false, "targets": "no-sort" } ],
959 - "order": [ [ 0, "asc" ] ],
960 - "language": { "emptyTable": "No fields found." },
961 - "drawCallback" : function( settings ) {
962 - jQuery( '#mainwp-clients-custom-fields-table .ui.dropdown').dropdown();
963 - },
964 - } );
965 - </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; ?>
966 1369 </div>
967 1370
968 1371 <?php
969 1372 static::render_add_field_modal();
@@ -978,24 +1381,24 @@
978 1381 * @param int $client_id The client id.
979 1382 */
980 1383 public static function render_add_field_modal( $client_id = 0 ) {
981 1384 ?>
982 - <div class="ui modal" id="mainwp-clients-custom-field-modal">
1385 + <div class="ui small modal" id="mainwp-clients-custom-field-modal">
983 1386 <i class="close icon"></i>
984 1387 <div class="header"><?php esc_html_e( 'Custom Field', 'mainwp' ); ?></div>
985 1388 <div class="content ui mini form">
986 1389 <div class="ui yellow message" style="display:none"></div>
987 1390 <div class="field">
988 - <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>
989 1392 <input type="text" value="" class="field-name" name="field-name" placeholder="<?php esc_attr_e( 'Enter field name (without of square brackets)', 'mainwp' ); ?>">
990 1393 </div>
991 1394 <div class="field">
992 - <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>
993 1396 <input type="text" value="" class="field-description" name="field-description" placeholder="<?php esc_attr_e( 'Enter field description', 'mainwp' ); ?>">
994 1397 </div>
995 1398 </div>
996 1399 <div class="actions">
997 - <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>
998 1401 </div>
999 1402 <input type="hidden" value="0" name="field-id">
1000 1403 </div>
1001 1404 <?php
@@ -1014,8 +1417,14 @@
1014 1417 if ( ! is_array( $client_fields ) ) {
1015 1418 $client_fields = array();
1016 1419 }
1017 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 +
1018 1427 if ( ! isset( $client_fields['default_field']['client.name'] ) || empty( $client_fields['default_field']['client.name'] ) ) {
1019 1428 echo wp_json_encode( array( 'error' => esc_html__( 'Client name are empty. Please try again.', 'mainwp' ) ) );
1020 1429 return;
1021 1430 }
@@ -1045,8 +1454,24 @@
1045 1454 if ( isset( $client_to_add['created'] ) && ! empty( $client_to_add['created'] ) ) {
1046 1455 $client_to_add['created'] = strtotime( $client_to_add['created'] );
1047 1456 }
1048 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 );
1049 1474 } else {
1050 1475 $client_to_add['created'] = time();
1051 1476 }
1052 1477
@@ -1064,8 +1489,11 @@
1064 1489 $client_id = $inserted->client_id;
1065 1490 }
1066 1491
1067 1492 if ( is_object( $inserted ) ) {
1493 +
1494 + static::invalidate_warm_cache();
1495 +
1068 1496 /**
1069 1497 * Add client
1070 1498 *
1071 1499 * Fires after add a client.
@@ -1106,10 +1534,10 @@
1106 1534 $client_image = sanitize_text_field( wp_unslash( $_POST['mainwp_add_edit_client_uploaded_icon_hidden'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1107 1535 }
1108 1536
1109 1537 // compatible with quick setup.
1110 - 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
1111 - $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
1112 1540 if ( is_array( $output ) && isset( $output['filename'] ) && ! empty( $output['filename'] ) ) {
1113 1541 $client_image = $output['filename'];
1114 1542 }
1115 1543 }
@@ -1146,11 +1574,11 @@
1146 1574 $contact_to_add = array();
1147 1575 if ( empty( $contact_name ) ) {
1148 1576 continue;
1149 1577 }
1150 - $contact_to_add['contact_name'] = $contact_name;
1578 + $contact_to_add['contact_name'] = sanitize_text_field( wp_unslash( $contact_name ) );
1151 1579
1152 - $contact_email = $client_fields['contacts_field']['contact.email'][ $indx ];
1580 + $contact_email = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.email'][ $indx ] ) );
1153 1581 if ( empty( $contact_email ) ) {
1154 1582 continue;
1155 1583 }
1156 1584
@@ -1159,16 +1587,22 @@
1159 1587 if ( empty( $contact_id ) ) {
1160 1588 continue;
1161 1589 }
1162 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 +
1163 1597 $contact_to_add['contact_email'] = $contact_email;
1164 1598
1165 - $contact_to_add['contact_phone'] = $client_fields['contacts_field']['contact.phone'][ $indx ];
1166 - $contact_to_add['contact_role'] = $client_fields['contacts_field']['contact.role'][ $indx ];
1167 - $contact_to_add['facebook'] = $client_fields['contacts_field']['contact.facebook'][ $indx ];
1168 - $contact_to_add['twitter'] = $client_fields['contacts_field']['contact.twitter'][ $indx ];
1169 - $contact_to_add['instagram'] = $client_fields['contacts_field']['contact.instagram'][ $indx ];
1170 - $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 ] ) );
1171 1605
1172 1606 $cust_icon = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['selected_icon'][ $indx ] ) );
1173 1607 $cust_color = sanitize_hex_color( wp_unslash( $client_fields['contacts_field']['selected_color'][ $indx ] ) );
1174 1608
@@ -1277,8 +1711,21 @@
1277 1711 delete_transient( 'mainwp_transient_just_connected_site_id' );
1278 1712 }
1279 1713 //phpcs:enable
1280 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 +
1281 1728 echo wp_json_encode(
1282 1729 array(
1283 1730 'success' => 'yes',
1284 1731 'client_id' => $client_id,
@@ -1286,8 +1733,15 @@
1286 1733 );
1287 1734 }
1288 1735
1289 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 + /**
1290 1744 * Method render_add_client_modal().
1291 1745 *
1292 1746 * Renders add client Modal window.
1293 1747 */
@@ -1346,23 +1800,34 @@
1346 1800 if ( ! empty( $client_image ) ) {
1347 1801 $uploaded_icon_src = MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'uploaded_icon' );
1348 1802 }
1349 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 +
1350 1811 ?>
1351 - <h3 class="ui dividing header">
1352 - <?php if ( $client_id ) : ?>
1353 - <?php MainWP_Settings_Indicator::render_indicator( 'header', 'settings-field-indicator-edit-client' ); ?>
1354 - <?php echo esc_html__( 'Edit Client', 'mainwp' ); ?>
1355 - <div class="sub header"><?php esc_html_e( 'Edit client information.', 'mainwp' ); ?></div>
1356 - <?php else : ?>
1357 - <?php esc_html_e( 'Add New Client', 'mainwp' ); ?>
1358 - <div class="sub header"><?php esc_html_e( 'Enter the client information.', 'mainwp' ); ?></div>
1359 - <?php endif; ?>
1360 - </h3>
1361 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">
1362 1824 <?php
1363 -
1364 - 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 ];
1365 1830 $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
1366 1831 $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
1367 1832 $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
1368 1833 ?>
@@ -1371,22 +1836,20 @@
1371 1836 <?php
1372 1837 $indi_val = $val && $edit_client ? 1 : 0;
1373 1838 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1374 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 + }
1375 1843 ?>
1376 1844 </label>
1377 1845 <div class="ui six wide column">
1378 1846 <div class="ui left labeled input">
1379 1847 <?php
1380 - if ( 'client.note' === $field_name ) {
1848 + if ( 'client.suspended' === $field_name ) {
1849 + $el_id_fln_2 = $field_name;
1381 1850 ?>
1382 - <div class="editor">
1383 - <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>
1384 - </div>
1385 - <?php
1386 - } elseif ( 'client.suspended' === $field_name ) {
1387 - ?>
1388 - <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 ); ?>]" >
1389 1852 <option value="0" <?php echo '0' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Active', 'mainwp' ); ?></option>
1390 1853 <option value="1" <?php echo '1' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Suspended', 'mainwp' ); ?></option>
1391 1854 <option value="2" <?php echo '2' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lead', 'mainwp' ); ?></option>
1392 1855 <option value="3" <?php echo '3' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lost', 'mainwp' ); ?></option>
@@ -1391,18 +1854,8 @@
1391 1854 <option value="2" <?php echo '2' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lead', 'mainwp' ); ?></option>
1392 1855 <option value="3" <?php echo '3' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lost', 'mainwp' ); ?></option>
1393 1856 </select>
1394 1857 <?php
1395 - } elseif ( $client_id && 'client.created' === $field_name ) {
1396 - $created = empty( $val ) ? time() : $val;
1397 - ?>
1398 - <div class="ui calendar mainwp_datepicker" >
1399 - <div class="ui input left icon">
1400 - <i class="calendar icon"></i>
1401 - <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. ?>"/>
1402 - </div>
1403 - </div>
1404 - <?php
1405 1858 } else {
1406 1859 ?>
1407 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 ); ?>]"/>
1408 1861 <?php
@@ -1417,30 +1870,38 @@
1417 1870 <?php } ?>
1418 1871 </div>
1419 1872 <?php endif; ?>
1420 1873 </div>
1421 - <?php
1422 1874
1423 - if ( 'client.email' === $field_name ) {
1424 - ?>
1875 + <?php if ( 'client.email' === $field_name ) { ?>
1425 1876 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1426 1877 <label class="six wide column middle aligned">
1427 1878 <?php
1428 1879 $indi_val = $client_image && $edit_client ? 1 : 0;
1429 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 ) );
1430 1882 ?>
1431 - <?php esc_html_e( 'Client photo', 'mainwp' ); ?>
1883 + <?php esc_html_e( 'Client logo (photo)', 'mainwp' ); ?>
1432 1884 </label>
1433 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 ); ?>">
1434 - <div class="ui six wide column" data-tooltip="<?php esc_attr_e( 'Upload a client photo.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1435 - <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>
1436 - <?php if ( ! empty( $client_image ) ) { ?>
1437 - <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'display_edit' ); //phpcs:ignore --ok. ?>
1438 - <?php } else { ?>
1439 - <div style="display:inline-block;" id="mainwp_add_edit_client_upload_custom_icon"></div> <?php // used for icon holder. ?>
1440 - <?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>
1441 1901 </div>
1442 1902 </div>
1903 +
1443 1904 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client" default-indi-indi-value="wordpress">
1444 1905 <label class="six wide column middle aligned">
1445 1906 <?php
1446 1907 $default_icons = MainWP_UI::get_default_icons();
@@ -1477,21 +1938,185 @@
1477 1938 </div>
1478 1939 <div class="one wide column"></div>
1479 1940 </div>
1480 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>';
1481 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
1482 1990 }
1991 + ?>
1992 + </div>
1993 + </div>
1483 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 +
1484 2109 $client_contacts = array();
1485 2110 if ( $client_id ) {
1486 2111 $client_contacts = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'client_id', $client_id );
1487 2112 ?>
1488 - <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">
1489 2114 <label class="six wide column middle aligned">
1490 2115 <?php
1491 2116 $indi_val = $edit_client && $client_contacts ? 1 : 0;
1492 2117 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1493 - echo esc_html_e( 'Client primary contact', 'mainwp' );
2118 + esc_html_e( 'Client primary contact', 'mainwp' );
1494 2119 ?>
1495 2120 </label>
1496 2121 <div class="ui six wide column">
1497 2122 <div class="ui left labeled">
@@ -1543,10 +2168,10 @@
1543 2168 </div>
1544 2169 </div>
1545 2170 <div class="ui four wide column">
1546 2171 <?php if ( $client_id > 0 && $field->client_id > 0 ) { // edit client and it is individual field, then show to edit/delete field buttons. ?>
1547 - <div class="ui left pointing dropdown icon mini basic green button">
1548 - <i class="ellipsis horizontal icon"></i>
2172 + <div class="ui right pointing dropdown">
2173 + <i class="ellipsis vertical icon"></i>
1549 2174 <div class="menu">
1550 2175 <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
1551 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>
1552 2177 </div>
@@ -1562,9 +2187,9 @@
1562 2187 $temp = static::get_add_contact_temp( false, false );
1563 2188
1564 2189 if ( $client_id && $client_contacts ) {
1565 2190 foreach ( $client_contacts as $client_contact ) {
1566 - static::get_add_contact_temp( $client_contact, true );
2191 + static::get_add_contact_temp( $client_contact, true, $client_id );
1567 2192 }
1568 2193 }
1569 2194 ?>
1570 2195 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
@@ -1570,17 +2195,21 @@
1570 2195 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1571 2196 <label class="six wide column middle aligned"><?php esc_html_e( 'Create a new contact for this client', 'mainwp' ); ?></label>
1572 2197 <div class="ui six wide column">
1573 2198 <div class="ui left labeled input">
1574 - <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>
1575 2200 </div>
1576 2201 </div>
1577 2202 </div>
1578 2203 <div class="ui section hidden divider after-add-contact-field"></div>
2204 + </div>
2205 + </div>
1579 2206 </div>
1580 2207 <input type="hidden" name="client_fields[client_id]" value="<?php echo intval( $client_id ); ?>">
1581 2208 <script type="text/javascript">
1582 2209 jQuery( document ).ready( function () {
2210 + mainwp_sidebar_accordion_init();
2211 +
1583 2212 // to fix issue not loaded calendar js library
1584 2213 if (jQuery('.ui.calendar').length > 0) {
1585 2214 if (mainwpParams.use_wp_datepicker == 1) {
1586 2215 jQuery('#mainwp-add-new-client-form .ui.calendar input[type=text]').datepicker({ dateFormat: "yy-mm-dd" });
@@ -1659,8 +2288,9 @@
1659 2288 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
1660 2289 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
1661 2290 iconObj.attr('icon-src', icon_src);
1662 2291 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2292 + iconObj.attr('del-icon-nonce', response.iconnonce);
1663 2293 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
1664 2294 jQuery('#mainwp_add_edit_client_upload_custom_icon').html(icon_img);
1665 2295 jQuery('#mainwp_add_edit_client_upload_custom_icon').show();
1666 2296 }
@@ -1665,10 +2295,9 @@
1665 2295 jQuery('#mainwp_add_edit_client_upload_custom_icon').show();
1666 2296 }
1667 2297 }
1668 2298 setTimeout(function () {
1669 - //window.location.href = location.href;
1670 - jQuery('#mainwp-upload-custom-icon-modal').modal('hide')
2299 + jQuery('#mainwp-upload-custom-icon-modal').modal('hide');
1671 2300 }, 1000);
1672 2301 });
1673 2302 return false;
1674 2303 }
@@ -1698,14 +2327,14 @@
1698 2327 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
1699 2328 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
1700 2329 iconObj.attr('icon-src', icon_src);
1701 2330 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2331 + iconObj.attr('del-icon-nonce', response.iconnonce);
1702 2332 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
1703 2333 jQuery(parent).find('.mainwp_add_edit_contact_upload_custom_icon').html(icon_img).show();
1704 2334 }
1705 2335 }
1706 2336 setTimeout(function () {
1707 - //window.location.href = location.href;
1708 2337 jQuery('#mainwp-upload-custom-icon-modal').modal('hide')
1709 2338 }, 1000);
1710 2339 });
1711 2340 return false;
@@ -1736,11 +2365,11 @@
1736 2365 if ( empty( $color ) ) {
1737 2366 $color = '#34424D';
1738 2367 }
1739 2368
1740 - $icon_cls = 'large icon custom-icon';
2369 + $icon_cls = 'circular inverted icon';
1741 2370 if ( 'card' === $what ) {
1742 - $icon_cls = 'icon huge custom-icon';
2371 + $icon_cls = 'huge circular inverted icon';
1743 2372 }
1744 2373
1745 2374 $output = '';
1746 2375 if ( 'selected' === $type ) {
@@ -1749,15 +2378,15 @@
1749 2378 $output = $color;
1750 2379 } elseif ( 'display' === $type || 'display_edit' === $what ) {
1751 2380 $color_style = '';
1752 2381 if ( ! empty( $color ) ) {
1753 - $color_style = 'color:' . esc_attr( $color ) . ';';
2382 + $color_style = 'background-color:' . esc_attr( $color ) . ';';
1754 2383 }
1755 2384 $icon_wrapper_attr = 'class="mainwp_client_icon_display"';
1756 2385 if ( 'display_edit' === $what ) {
1757 2386 $icon_wrapper_attr = ' id="mainwp_add_edit_client_upload_custom_icon" ' . $icon_wrapper_attr;
1758 2387 }
1759 - $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>';
1760 2389 }
1761 2390 return $output;
1762 2391 }
1763 2392
@@ -1767,10 +2396,11 @@
1767 2396 * Get add contact template.
1768 2397 *
1769 2398 * @param mixed $edit_contact The contact data to edit.
1770 2399 * @param bool $echo_out Echo template or not.
2400 + * @param int $client_id Client id.
1771 2401 */
1772 - 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.
1773 2403
1774 2404 $input_name = 'new_contacts_field';
1775 2405 $contact_id = 0;
1776 2406 $contact_image = '';
@@ -1814,8 +2444,11 @@
1814 2444 <?php
1815 2445 $indi_val = $edit_contact && $val ? 1 : 0;
1816 2446 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1817 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 + }
1818 2451 ?>
1819 2452 </label>
1820 2453 <div class="ui six wide column">
1821 2454 <div class="ui left labeled input">
@@ -1835,14 +2468,15 @@
1835 2468 <label class="six wide column middle aligned">
1836 2469 <?php
1837 2470 $indi_val = $edit_contact && $contact_image ? 1 : 0;
1838 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 ) );
1839 2473 ?>
1840 2474 <?php esc_html_e( 'Contact photo', 'mainwp' ); ?>
1841 2475 </label>
1842 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 ); ?>">
1843 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">
1844 - <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>
1845 2479 <?php
1846 2480 if ( ! empty( $contact_image ) ) {
1847 2481 ?>
1848 2482 <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'contact', 'display_edit' ); //phpcs:ignore --ok. ?>
@@ -1899,10 +2533,11 @@
1899 2533 </div>
1900 2534 <?php
1901 2535 if ( $edit_contact ) {
1902 2536 ?>
1903 - <input type="hidden" value="<?php echo intval( $edit_contact->contact_id ); ?>" name="client_fields[contacts_field][contact_id][]"/>
1904 - <?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
1905 2540 }
1906 2541 ?>
1907 2542 </div>
1908 2543 </div>
@@ -2001,37 +2636,16 @@
2001 2636 'client_id' => intval( $_POST['clientid'] ), // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2002 2637 'note' => $esc_note,
2003 2638 );
2004 2639 MainWP_DB_Client::instance()->update_client( $update );
2005 - 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 + );
2006 2648 }
2007 2649 die( wp_json_encode( array( 'undefined_error' => true ) ) );
2008 - }
2009 -
2010 - /**
2011 - * Hooks the section help content to the Help Sidebar element.
2012 - */
2013 - public static function mainwp_help_content() {
2014 - if ( isset( $_GET['page'] ) && ( 'ManageClients' === $_GET['page'] || 'ClientAddNew' === $_GET['page'] || 'UpdateAdminPasswords' === $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2015 - ?>
2016 - <p><?php esc_html_e( 'If you need help with managing clients, please review following help documents', 'mainwp' ); ?></p>
2017 - <div class="ui relaxed bulleted list">
2018 - <div class="item"><a href="https://kb.mainwp.com/docs/manage-clients/" target="_blank">Manage Clients</a> <i class="external alternate icon"></i></div> <?php // NOSONAR - noopener - open safe. ?>
2019 - <?php
2020 - /**
2021 - * Action: mainwp_clients_help_item
2022 - *
2023 - * Fires at the bottom of the help articles list in the Help sidebar on the Clients page.
2024 - *
2025 - * Suggested HTML markup:
2026 - *
2027 - * <div class="item"><a href="Your custom URL">Your custom text</a></div>
2028 - *
2029 - * @since 4.1
2030 - */
2031 - do_action( 'mainwp_clients_help_item' );
2032 - ?>
2033 - </div>
2034 - <?php
2035 - }
2036 2650 }
2037 2651 }