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
mainwp / pages / page-mainwp-client.php

page-mainwp-client.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.2, at pages/page-mainwp-client.php

2,652 lines 142.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Clients Page
4 *
5 * This page is used to Manage Clients.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class MainWP_client
19 *
20 * @uses page-mainwp-bulk-add::MainWP_Bulk_Add()
21 */
22 class MainWP_Client { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
23
24 /**
25 * Get Class Name
26 *
27 * @return string __CLASS__
28 */
29 public static function get_class_name() {
30 return __CLASS__;
31 }
32
33 /**
34 * Current page.
35 *
36 * @static
37 * @var string $page Current page.
38 */
39 public static $page;
40
41 /**
42 * Public static varable to hold Subpages information.
43 *
44 * @var array $subPages
45 */
46 public static $subPages;
47
48
49 /**
50 * Magage Sites table
51 *
52 * @var $itemsTable Magage Sites table.
53 */
54 public static $itemsTable;
55
56 /**
57 * Method init()
58 *
59 * Initiate hooks for the clients page.
60 */
61 public static function init() {
62 /**
63 * This hook allows you to render the client page header via the 'mainwp_pageheader_client' action.
64 *
65 * This hook is normally used in the same context of 'mainwp_pageheader_client'
66 *
67 * @see \MainWP_client::render_header
68 */
69 add_action( 'mainwp_pageheader_client', array( static::get_class_name(), 'render_header' ) );
70
71 /**
72 * This hook allows you to render the client page footer via the 'mainwp_pagefooter_client' action.
73 *
74 * This hook is normally used in the same context of 'mainwp_pagefooter_client'
75 *
76 * @see \MainWP_client::render_footer
77 */
78 add_action( 'mainwp_pagefooter_client', array( static::get_class_name(), 'render_footer' ) );
79
80 MainWP_Post_Handler::instance()->add_action( 'mainwp_add_edit_client_upload_client_icon', array( static::class, 'ajax_upload_client_icon' ) );
81 MainWP_Post_Handler::instance()->add_action( 'mainwp_add_edit_contact_upload_contact_icon', array( static::class, 'ajax_upload_contact_icon' ) );
82 }
83
84 /**
85 * Method init_menu()
86 *
87 * Initiate menu.
88 *
89 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
90 */
91 public static function init_menu() {
92 static::$page = add_submenu_page(
93 'mainwp_tab',
94 esc_html__( 'Clients', 'mainwp' ),
95 '<span id="mainwp-clients">' . esc_html__( 'Clients', 'mainwp' ) . '</span>',
96 'read',
97 'ManageClients',
98 array(
99 static::get_class_name(),
100 'render_manage_clients',
101 )
102 );
103
104 add_submenu_page(
105 'mainwp_tab',
106 esc_html__( 'Clients', 'mainwp' ),
107 '<div class="mainwp-hidden">' . esc_html__( 'Add Client', 'mainwp' ) . '</div>',
108 'read',
109 'ClientAddNew',
110 array(
111 static::get_class_name(),
112 'render_add_client',
113 )
114 );
115
116 add_submenu_page(
117 'mainwp_tab',
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' ),
131 '<div class="mainwp-hidden">' . esc_html__( 'Client Fields', 'mainwp' ) . '</div>',
132 'read',
133 'ClientAddField',
134 array(
135 static::get_class_name(),
136 'render_client_fields',
137 )
138 );
139
140 /**
141 * This hook allows you to add extra sub pages to the client page via the 'mainwp-getsubpages-client' filter.
142 *
143 * @link http://codex.mainwp.com/#mainwp-getsubpages-client
144 */
145 $sub_pages = array();
146 static::$subPages = apply_filters( 'mainwp_getsubpages_client', $sub_pages );
147
148 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
149 foreach ( static::$subPages as $subPage ) {
150 if ( MainWP_Menu::is_disable_menu_item( 3, 'ManageClients' . $subPage['slug'] ) ) {
151 continue;
152 }
153 add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . esc_html( $subPage['title'] ) . '</div>', 'read', 'ManageClients' . $subPage['slug'], $subPage['callback'] );
154 }
155 }
156
157 static::init_left_menu( static::$subPages );
158
159 add_action( 'load-' . static::$page, array( static::get_class_name(), 'on_load_page' ) );
160 }
161
162 /**
163 * Method on_load_page()
164 *
165 * Run on page load.
166 */
167 public static function on_load_page() {
168
169 if ( isset( $_GET['client_id'] ) && ! empty( $_GET['client_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
170 MainWP_Client_Overview::instance()->on_load_page( static::$page );
171 return;
172 }
173
174 add_filter( 'mainwp_header_actions_right', array( static::get_class_name(), 'screen_options' ), 10, 2 );
175
176 static::$itemsTable = new MainWP_Client_List_Table();
177 }
178
179 /**
180 * Method screen_options()
181 *
182 * Create Page Settings button.
183 *
184 * @param mixed $input Page Settings button HTML.
185 *
186 * @return mixed Screen sptions button.
187 */
188 public static function screen_options( $input ) {
189 return $input .
190 '<a class="ui button basic icon" onclick="mainwp_manage_clients_screen_options(); return false;" data-inverted="" data-position="bottom right" href="#" target="_blank" data-tooltip="' . esc_html__( 'Page Settings', 'mainwp' ) . '" aria-label="' . esc_html__( 'Page Settings', 'mainwp' ) . '">
191 <i class="cog icon"></i>
192 </a>';
193 }
194
195 /**
196 * Initiates sub pages menu.
197 *
198 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
199 */
200 public static function init_subpages_menu() {
201 ?>
202 <div id="menu-mainwp-Clients" class="mainwp-submenu-wrapper">
203 <div class="wp-submenu sub-open" style="">
204 <div class="mainwp_boxout">
205 <div class="mainwp_boxoutin"></div>
206 <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) { ?>
207 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ManageClients' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Clients', 'mainwp' ); ?></a>
208 <?php } ?>
209 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddNew' ) ) { ?>
210 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddNew' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Add Client', 'mainwp' ); ?></a>
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 } ?>
215 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) { ?>
216 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ClientAddField' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Client Properties', 'mainwp' ); ?></a>
217 <?php } ?>
218 <?php
219 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
220 foreach ( static::$subPages as $subPage ) {
221 if ( MainWP_Menu::is_disable_menu_item( 3, 'ManageClients' . $subPage['slug'] ) ) {
222 continue;
223 }
224 ?>
225 <a href="<?php echo esc_url( admin_url( 'admin.php?page=ManageClients' . $subPage['slug'] ) ); ?>" class="mainwp-submenu"><?php echo esc_html( $subPage['title'] ); ?></a>
226 <?php
227 }
228 }
229 ?>
230 </div>
231 </div>
232 </div>
233 <?php
234 }
235
236 /**
237 * Initiates Clients menu.
238 *
239 * @param array $subPages Sub pages array.
240 *
241 * @uses \MainWP\Dashboard\MainWP_Menu::add_left_menu()
242 * @uses \MainWP\Dashboard\MainWP_Menu::init_subpages_left_menu()
243 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
244 */
245 public static function init_left_menu( $subPages = array() ) {
246 MainWP_Menu::add_left_menu(
247 array(
248 'title' => esc_html__( 'Clients', 'mainwp' ),
249 'parent_key' => 'mainwp_tab',
250 'slug' => 'ManageClients',
251 'href' => 'admin.php?page=ManageClients',
252 'icon' => '<i class="users icon"></i>',
253 'desc' => 'Manage clients on your child sites',
254 ),
255 0
256 );
257
258 $init_sub_subleftmenu = array(
259 array(
260 'title' => esc_html__( 'Clients', 'mainwp' ),
261 'parent_key' => 'ManageClients',
262 'href' => 'admin.php?page=ManageClients',
263 'slug' => 'ManageClients',
264 'right' => 'manage_clients',
265 'leftsub_order_level2' => 1,
266 ),
267 array(
268 'title' => esc_html__( 'Add Client', 'mainwp' ),
269 'parent_key' => 'ManageClients',
270 'href' => 'admin.php?page=ClientAddNew',
271 'slug' => 'ClientAddNew',
272 'right' => '',
273 'leftsub_order_level2' => 2,
274 ),
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(
284 'title' => esc_html__( 'Client Fields', 'mainwp' ),
285 'parent_key' => 'ManageClients',
286 'href' => 'admin.php?page=ClientAddField',
287 'slug' => 'ClientAddField',
288 'right' => '',
289 'leftsub_order_level2' => 4,
290 ),
291 );
292
293 MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'ManageClients', 'ManageClients' );
294
295 foreach ( $init_sub_subleftmenu as $item ) {
296 if ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) {
297 continue;
298 }
299 MainWP_Menu::add_left_menu( $item, 2 );
300 }
301 }
302
303 /**
304 * Method ajax_upload_client_icon()
305 */
306 public static function ajax_upload_client_icon() { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR - complexity.
307 MainWP_Post_Handler::instance()->secure_request( 'mainwp_add_edit_client_upload_client_icon' );
308
309 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
310 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
311 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
312 $client_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
313 $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
314
315 if ( $delete ) {
316 if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'client', $iconfile_slug, $delnonce ) ) {
317 die( 'Invalid nonce!' );
318 }
319 if ( $client_id ) {
320 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
321 if ( $client && ! empty( $client->image ) ) {
322 $update = array(
323 'image' => '',
324 'client_id' => $client_id,
325 );
326 MainWP_DB_Client::instance()->update_client( $update );
327 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $client->image );
328 }
329 } elseif ( ! empty( $iconfile_slug ) ) {
330 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $iconfile_slug );
331 }
332 wp_die( wp_json_encode( array( 'result' => 'success' ) ) );
333 }
334
335 $output = isset( $_FILES['mainwp_upload_icon_uploader'] ) ? MainWP_System_Utility::handle_upload_image( 'client-images', $_FILES['mainwp_upload_icon_uploader'] ) : null;
336 // phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
337
338 $uploaded_icon = 'NOTCHANGE';
339 if ( is_array( $output ) && isset( $output['filename'] ) && ! empty( $output['filename'] ) ) {
340 $uploaded_icon = $output['filename'];
341 }
342
343 if ( 'NOTCHANGE' !== $uploaded_icon ) {
344 $dirs = MainWP_System_Utility::get_mainwp_dir( 'client-images', true );
345 $icon_url = $dirs[1] . $uploaded_icon;
346 wp_die(
347 wp_json_encode(
348 array(
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 ) ),
354 )
355 )
356 );
357 } else {
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 ) );
366 }
367 }
368
369
370 /**
371 * Method ajax_upload_contact_icon()
372 */
373 public static function ajax_upload_contact_icon() { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR - complexity.
374 MainWP_Post_Handler::instance()->secure_request( 'mainwp_add_edit_contact_upload_contact_icon' );
375 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
376 $iconfile_slug = isset( $_POST['iconFileSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['iconFileSlug'] ) ) : '';
377 $delete = isset( $_POST['delete'] ) ? intval( $_POST['delete'] ) : 0;
378 $contact_id = isset( $_POST['iconItemId'] ) ? intval( $_POST['iconItemId'] ) : 0;
379 $delnonce = isset( $_POST['delnonce'] ) ? sanitize_key( $_POST['delnonce'] ) : '';
380
381 if ( $delete ) {
382 if ( ! MainWP_System_Utility::is_valid_custom_nonce( 'contact', $iconfile_slug, $delnonce ) ) {
383 die( 'Invalid nonce!' );
384 }
385 if ( $contact_id ) {
386 $contact_data = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'contact_id', $contact_id );
387 if ( $contact_data && ! empty( $contact_data->contact_image ) ) {
388 $update = array(
389 'contact_image' => '',
390 'contact_id' => $contact_id,
391 );
392 MainWP_DB_Client::instance()->update_client_contact( $update );
393 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $contact_data->contact_image );
394 }
395 } elseif ( ! empty( $iconfile_slug ) ) {
396 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $iconfile_slug );
397 }
398 wp_die( wp_json_encode( array( 'result' => 'success' ) ) );
399 }
400
401 $output = isset( $_FILES['mainwp_upload_icon_uploader'] ) ? MainWP_System_Utility::handle_upload_image( 'client-images', $_FILES['mainwp_upload_icon_uploader'] ) : null;
402 // phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
403
404 $uploaded_icon = 'NOTCHANGE';
405 if ( is_array( $output ) && isset( $output['filename'] ) && ! empty( $output['filename'] ) ) {
406 $uploaded_icon = $output['filename'];
407 }
408
409 if ( 'NOTCHANGE' !== $uploaded_icon ) {
410 $dirs = MainWP_System_Utility::get_mainwp_dir( 'client-images', true );
411 $icon_url = $dirs[1] . $uploaded_icon;
412 wp_die(
413 wp_json_encode(
414 array(
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 ) ),
420 )
421 )
422 );
423 } else {
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 ) );
432 }
433 }
434
435
436 /**
437 * Method render_header()
438 *
439 * Render Clients page header.
440 *
441 * @param string $shownPage The page slug shown at this moment.
442 *
443 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
444 * @uses \MainWP\Dashboard\MainWP_UI::render_top_header()
445 * @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation()
446 */
447 public static function render_header( $shownPage = '' ) { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
448 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
449 $client_id = isset( $_GET['client_id'] ) ? intval( $_GET['client_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
450
451 $params = array(
452 'title' => esc_html__( 'Clients', 'mainwp' ),
453 'which' => 'overview' === $shownPage ? 'page_clients_overview' : '',
454 );
455
456 $client = false;
457 if ( $client_id ) {
458 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
459 if ( $client ) {
460 $arr_client = MainWP_Utility::map_fields( $client, array( 'image', 'selected_icon_info' ), false ); // array map.
461 $client_pic = MainWP_Client_Handler::get_client_contact_image( $arr_client );
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>';
463 }
464 }
465
466 MainWP_UI::render_top_header( $params );
467
468 $renderItems = array();
469
470 if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
471 $renderItems[] = array(
472 'title' => esc_html__( 'Clients', 'mainwp' ),
473 'href' => 'admin.php?page=ManageClients',
474 'active' => ( '' === $shownPage ) ? true : false,
475 );
476 }
477
478 if ( $client_id ) {
479 $renderItems[] = array(
480 'title' => $client ? $client->name : esc_html__( 'Operations', 'mainwp' ),
481 'href' => 'admin.php?page=ManageClients&client_id=' . $client_id,
482 'active' => ( 'overview' === $shownPage ),
483 );
484 $renderItems[] = array(
485 'title' => $client ? esc_html__( 'Edit', 'mainwp' ) . ' ' . $client->name : esc_html__( 'Edit Client', 'mainwp' ),
486 'href' => 'admin.php?page=ClientAddNew&client_id=' . $client_id,
487 'active' => ( 'Edit' === $shownPage ) ? true : false,
488 );
489 }
490
491 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddNew' ) ) {
492 $renderItems[] = array(
493 'title' => esc_html__( 'Add Client', 'mainwp' ),
494 'href' => 'admin.php?page=ClientAddNew',
495 'active' => ( 'Add' === $shownPage ) ? true : false,
496 );
497 }
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
507 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ClientAddField' ) ) {
508 $renderItems[] = array(
509 'title' => esc_html__( 'Client Fields', 'mainwp' ),
510 'href' => 'admin.php?page=ClientAddField',
511 'active' => ( 'AddField' === $shownPage ) ? true : false,
512 );
513 }
514
515 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
516 foreach ( static::$subPages as $subPage ) {
517 if ( MainWP_Menu::is_disable_menu_item( 3, 'ManageClients' . $subPage['slug'] ) ) {
518 continue;
519 }
520
521 if ( ! empty( $subPage['individual_settings'] ) && empty( $client_id ) ) {
522 continue;
523 }
524
525 $client_param = $client_id ? '&client_id=' . $client_id : '';
526 $item = array();
527 $item['title'] = $subPage['title'];
528 $item['href'] = 'admin.php?page=ManageClients' . $subPage['slug'] . $client_param;
529 $item['active'] = ( $subPage['slug'] === $shownPage ) ? true : false;
530 $renderItems[] = $item;
531 }
532 }
533 // phpcs:enable
534 MainWP_UI::render_page_navigation( $renderItems );
535 }
536
537 /**
538 * Method render_footer()
539 *
540 * Render Clients page footer. Closes the page container.
541 */
542 public static function render_footer() {
543 echo '</div>';
544 }
545
546 /**
547 * Renders manage clients dashboard.
548 *
549 * @return void
550 */
551 public static function render_manage_clients() {
552
553 if ( isset( $_GET['client_id'] ) && ! empty( $_GET['client_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
554 MainWP_Client_Overview::instance()->on_show_page( intval( $_GET['client_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
555 return;
556 }
557
558 if ( ! \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
559 \mainwp_do_not_have_permissions( esc_html__( 'manage clients', 'mainwp' ) );
560 return;
561 }
562
563 static::$itemsTable->prepare_items();
564
565 $has_no_clients = ( 0 === static::$itemsTable->total_items );
566
567 static::render_header( '' );
568
569 if ( ! $has_no_clients ) {
570 static::render_second_top_header();
571 }
572
573 ?>
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; ?>
619 </div>
620 <?php
621 static::render_footer( '' );
622
623 if ( ! $has_no_clients ) {
624 static::render_screen_options();
625 }
626 }
627
628 /**
629 * Method render_second_top_header()
630 *
631 * Render second top header.
632 *
633 * @return void Render second top header html.
634 */
635 public static function render_second_top_header() {
636 ?>
637 <div class="mainwp-sub-header ui mini form">
638 <?php
639 do_action( 'mainwp_manageclients_tabletop' );
640 ?>
641 </div>
642 <?php
643 }
644
645
646 /**
647 * Renders Edit Clients Modal window.
648 */
649 public static function render_update_clients() {
650
651 ?>
652 <div id="mainwp-edit-clients-modal" class="ui modal">
653 <i class="close icon"></i>
654 <div class="header"><?php esc_html_e( 'Edit client', 'mainwp' ); ?></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" />
665 </div>
666 </div>
667 </div>
668
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" />
674 </div>
675 </div>
676 </div>
677
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" />
683 </div>
684 </div>
685 </div>
686
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>
692 </div>
693 </div>
694 </div>
695
696 <h3 class="ui header"><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
697
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" />
703 </div>
704 </div>
705 </div>
706
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" />
712 </div>
713 </div>
714 </div>
715
716 <h3 class="ui header"><?php esc_html_e( 'About the user', 'mainwp' ); ?></h3>
717
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>
724 </div>
725 </div>
726 </div>
727
728 <h3 class="ui header"><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
729
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="">
736 </div>
737 </div>
738 </div>
739
740 </form>
741 </div>
742 <div class="actions">
743 <div id="mainwp_update_password_error" style="display: none"></div>
744 <span id="mainwp_clients_updating"><i class="ui active inline loader tiny"></i></span>
745 <input type="button" class="ui green button" id="mainwp_btn_update_client" value="<?php esc_attr_e( 'Update', 'mainwp' ); ?>">
746 </div>
747 </div>
748 <?php
749 }
750
751
752 /**
753 * Method render_screen_options()
754 *
755 * Render Page Settings Modal.
756 */
757 public static function render_screen_options() { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
758
759 $columns = static::$itemsTable->get_columns();
760
761 if ( isset( $columns['cb'] ) ) {
762 unset( $columns['cb'] );
763 }
764
765 $sites_per_page = get_option( 'mainwp_default_manage_clients_per_page', 25 );
766
767 if ( isset( $columns['site_actions'] ) && empty( $columns['site_actions'] ) ) {
768 $columns['site_actions'] = esc_html__( 'Actions', 'mainwp' );
769 }
770
771 $show_cols = get_user_option( 'mainwp_settings_show_manage_clients_columns' );
772
773 if ( false === $show_cols ) { // to backwards.
774 $show_cols = array();
775 foreach ( $columns as $name => $title ) {
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 }
781 }
782 $user = wp_get_current_user();
783 if ( $user ) {
784 update_user_option( $user->ID, 'mainwp_settings_show_manage_clients_columns', $show_cols, true );
785 }
786 }
787
788 if ( ! is_array( $show_cols ) ) {
789 $show_cols = array();
790 }
791
792 ?>
793 <div class="ui modal" id="mainwp-manage-sites-screen-options-modal">
794 <i class="close icon"></i>
795 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
796 <div class="scrolling content ui form">
797 <form method="POST" action="" id="manage-sites-screen-options-form" name="manage_sites_screen_options_form">
798 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
799 <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'ManageClientsScrOptions' ) ); ?>" />
800 <div class="ui grid field">
801 <label class="six wide column"><?php esc_html_e( 'Default items per page value', 'mainwp' ); ?></label>
802 <div class="ten wide column">
803 <div class="ui info message">
804 <ul>
805 <li><?php esc_html_e( 'Based on your Dashboard server default large numbers can severely impact page load times.', 'mainwp' ); ?></li>
806 <li><?php esc_html_e( 'Do not add commas for thousands (ex 1000).', 'mainwp' ); ?></li>
807 <li><?php esc_html_e( '-1 to default to All of your Child Sites.', 'mainwp' ); ?></li>
808 </ul>
809 </div>
810 <input type="text" name="mainwp_default_manage_clients_per_page" id="mainwp_default_manage_clients_per_page" saved-value="<?php echo intval( $sites_per_page ); ?>" value="<?php echo intval( $sites_per_page ); ?>"/>
811 </div>
812 </div>
813 <div class="ui grid field">
814 <label class="six wide column"><?php esc_html_e( 'Show columns', 'mainwp' ); ?></label>
815 <div class="ten wide column">
816 <ul class="mainwp_hide_wpmenu_checkboxes">
817 <?php
818 foreach ( $columns as $name => $title ) {
819 if ( empty( $title ) ) {
820 continue;
821 }
822 ?>
823 <li>
824 <div class="ui checkbox <?php echo ( 'site_preview' === $name ) ? 'site_preview not-auto-init' : ''; ?>">
825 <input type="checkbox"
826 <?php
827 $show_col = ! isset( $show_cols[ $name ] ) || ( 1 === (int) $show_cols[ $name ] );
828 if ( $show_col ) {
829 echo 'checked="checked"';
830 }
831 ?>
832 id="mainwp_show_column_<?php echo esc_attr( $name ); ?>" name="mainwp_show_column_<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $name ); ?>">
833 <label for="mainwp_show_column_<?php echo esc_attr( $name ); ?>" ><?php echo $title; // phpcs:ignore WordPress.Security.EscapeOutput ?></label>
834 <input type="hidden" value="<?php echo esc_attr( $name ); ?>" name="show_columns_name[]" />
835 </div>
836 </li>
837 <?php
838 }
839 ?>
840 </ul>
841 </div>
842 </div>
843 </div>
844 <div class="actions">
845 <div class="ui two columns grid">
846 <div class="left aligned column">
847 <span data-tooltip="<?php esc_attr_e( 'Resets the page to its original layout and reinstates relocated columns.', 'mainwp' ); ?>" data-inverted="" data-position="top center"><input type="button" class="ui button" name="reset" id="reset-manageclients-settings" value="<?php esc_attr_e( 'Reset Page', 'mainwp' ); ?>" /></span>
848 </div>
849 <div class="ui right aligned column">
850 <input type="submit" class="ui green button" name="btnSubmit" id="submit-manageclients-settings" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>" />
851 </div>
852 </div>
853 </div>
854 <input type="hidden" name="reset_manageclients_columns_order" value="0">
855 </form>
856 </div>
857 <div class="ui small modal" id="mainwp-monitoring-sites-site-preview-screen-options-modal">
858 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
859 <div class="scrolling content ui form">
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' ); ?>
861 </div>
862 <div class="actions">
863 <div class="ui ok button"><?php esc_html_e( 'Yes', 'mainwp' ); ?></div>
864 <div class="ui cancel button"><?php esc_html_e( 'No', 'mainwp' ); ?></div>
865 </div>
866 </div>
867 <script type="text/javascript">
868 jQuery( document ).ready( function () {
869 jQuery( '.ui.checkbox.not-auto-init.site_preview' ).checkbox( {
870 onChecked : function() {
871 let $chk = jQuery( this );
872 jQuery( '#mainwp-monitoring-sites-site-preview-screen-options-modal' ).modal( {
873 allowMultiple: true, // multiple modals.
874 width: 100,
875 onDeny: function () {
876 $chk.prop('checked', false);
877 }
878 } ).modal( 'show' );
879 }
880 } );
881 jQuery('#reset-manageclients-settings').on( 'click', function () {
882 mainwp_confirm(__( 'Are you sure?' ), function(){
883 jQuery('input[name=mainwp_default_manage_clients_per_page]').val(25);
884 jQuery('.mainwp_hide_wpmenu_checkboxes input[id^="mainwp_show_column_"]').prop( 'checked', false );
885 //default columns.
886 let cols = [ 'suspended','image','client','websites','contact_name','created'];
887 jQuery.each( cols, function ( index, value ) {
888 jQuery('.mainwp_hide_wpmenu_checkboxes input[id="mainwp_show_column_' + value + '"]').prop( 'checked', true );
889 } );
890 jQuery('input[name=reset_manageclients_columns_order]').attr('value',1);
891 jQuery('#submit-manageclients-settings').click();
892 }, false, false, true );
893 return false;
894 });
895 } );
896 </script>
897 <?php
898 }
899
900 /**
901 * Renders the Add New Client form.
902 */
903 public static function render_add_client() {
904 $show = 'Add';
905 $client_id = 0;
906 $selected_sites = array();
907 $edit_client = false;
908
909 if ( isset( $_GET['client_id'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
910 $show = 'Edit';
911 $client_id = intval( $_GET['client_id'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
912 $edit_client = $client_id ? MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id ) : false;
913 $client_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $client_id );
914
915 if ( $client_sites ) {
916 foreach ( $client_sites as $site ) {
917 $selected_sites[] = $site->id;
918 }
919 }
920 }
921
922 static::render_header( $show );
923 ?>
924 <div class="ui alt segment" id="mainwp-add-clients">
925 <form action="" method="post" enctype="multipart/form-data" name="createclient_form" id="createclient_form" class="add:clients: validate">
926 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
927 <div class="mainwp-main-content">
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>
933 </div>
934 </div>
935 <div class="mainwp-side-content mainwp-no-padding">
936 <?php if ( $client_id ) : ?>
937 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
938 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Tokens Info', 'mainwp' ); ?></div>
939 <div class="content active">
940 <div class="ui info message">
941 <?php esc_html_e( 'Client info is available as tokens for reports and boilerplate content. Toggle the switch to see available tokens.', 'mainwp' ); ?>
942 </div>
943 <div class="ui toggle checkbox">
944 <input type="checkbox" name="mainwp_toggle_tokens_info" id="mainwp_toggle_tokens_info">
945 <label><?php esc_html_e( 'Toggle available tokens', 'mainwp' ); ?></label>
946 </div>
947 </div>
948 </div>
949 <script type="text/javascript">
950 jQuery( document ).ready( function() {
951 jQuery( '#mainwp_toggle_tokens_info' ).on( 'change', function() {
952 jQuery( '.hidden.token.column' ).toggle();
953 } );
954 } );
955 </script>
956 <div class="ui fitted divider"></div>
957 <?php endif; ?>
958
959 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
960 <div class="title active"><i class="dropdown icon"></i>
961 <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
962 <div class="content active">
963 <?php
964 $sel_params = array(
965 'selected_sites' => $selected_sites,
966 'show_group' => false,
967 'add_edit_client_id' => $client_id,
968 'enable_offline_sites' => $client_id ? true : false,
969 );
970
971 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
972 ?>
973 </div>
974 </div>
975 <div class="ui fitted divider"></div>
976 <div class="mainwp-search-submit">
977 <input type="button" name="createclient" current-page="add-new" id="bulk_add_createclient" class="ui big green fluid button" value="<?php echo $client_id ? esc_attr__( 'Update Client', 'mainwp' ) : esc_attr__( 'Add Client', 'mainwp' ); ?> "/>
978 </div>
979 </div>
980 <div style="clear:both"></div>
981 </form>
982 </div>
983 <?php
984 static::render_footer( $show );
985 static::render_add_field_modal( $client_id );
986 MainWP_UI::render_modal_upload_icon();
987 }
988
989 /**
990 * Renders the Import Client form.
991 */
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
996
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 }
1002 ?>
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>
1042 <?php
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 }
1064 ?>
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>
1078 </div>
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();
1086 }
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>
1265 </div>
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>
1307 </tr>
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>
1340
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; ?>
1369 </div>
1370
1371 <?php
1372 static::render_add_field_modal();
1373 static::render_footer( 'AddField' );
1374 }
1375
1376 /**
1377 * Method render_add_field_modal()
1378 *
1379 * Render add custom field modal.
1380 *
1381 * @param int $client_id The client id.
1382 */
1383 public static function render_add_field_modal( $client_id = 0 ) {
1384 ?>
1385 <div class="ui small modal" id="mainwp-clients-custom-field-modal">
1386 <i class="close icon"></i>
1387 <div class="header"><?php esc_html_e( 'Custom Field', 'mainwp' ); ?></div>
1388 <div class="content ui mini form">
1389 <div class="ui yellow message" style="display:none"></div>
1390 <div class="field">
1391 <label><?php esc_html_e( 'Field Name', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
1392 <input type="text" value="" class="field-name" name="field-name" placeholder="<?php esc_attr_e( 'Enter field name (without of square brackets)', 'mainwp' ); ?>">
1393 </div>
1394 <div class="field">
1395 <label><?php esc_html_e( 'Field Description', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
1396 <input type="text" value="" class="field-description" name="field-description" placeholder="<?php esc_attr_e( 'Enter field description', 'mainwp' ); ?>">
1397 </div>
1398 </div>
1399 <div class="actions">
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>
1401 </div>
1402 <input type="hidden" value="0" name="field-id">
1403 </div>
1404 <?php
1405 }
1406
1407 /**
1408 * Method add_client()
1409 *
1410 * Bulk client addition $_POST Handler.
1411 */
1412 public static function add_client() { // phpcs:ignore -- NOSONAR -Current complexity is required to achieve desired results. Pull request solutions appreciated.
1413
1414 $selected_sites = ( isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_sites'] ) ) : array(); //phpcs:ignore WordPress.Security.NonceVerification.Missing
1415 $client_fields = isset( $_POST['client_fields'] ) ? wp_unslash( $_POST['client_fields'] ) : array(); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1416
1417 if ( ! is_array( $client_fields ) ) {
1418 $client_fields = array();
1419 }
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
1427 if ( ! isset( $client_fields['default_field']['client.name'] ) || empty( $client_fields['default_field']['client.name'] ) ) {
1428 echo wp_json_encode( array( 'error' => esc_html__( 'Client name are empty. Please try again.', 'mainwp' ) ) );
1429 return;
1430 }
1431
1432 $add_new = true;
1433
1434 $default_client_fields = MainWP_Client_Handler::get_default_client_fields();
1435 $client_to_add = array();
1436 foreach ( $default_client_fields as $field_name => $item ) {
1437 if ( ! empty( $item['db_field'] ) && isset( $client_fields['default_field'][ $field_name ] ) ) {
1438 $client_to_add[ $item['db_field'] ] = sanitize_text_field( wp_unslash( $client_fields['default_field'][ $field_name ] ) );
1439 }
1440 }
1441
1442 $client_to_add['primary_contact_id'] = isset( $client_fields['default_field']['primary_contact_id'] ) ? intval( $client_fields['default_field']['primary_contact_id'] ) : 0;
1443
1444 $client_id = isset( $client_fields['client_id'] ) ? intval( $client_fields['client_id'] ) : 0;
1445
1446 $new_suspended = isset( $client_to_add['suspended'] ) ? (int) $client_to_add['suspended'] : 0;
1447 $old_suspended = $new_suspended;
1448
1449 if ( $client_id ) {
1450 $current_client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
1451 $old_suspended = $current_client->suspended;
1452
1453 $client_to_add['client_id'] = $client_id; // update client.
1454 if ( isset( $client_to_add['created'] ) && ! empty( $client_to_add['created'] ) ) {
1455 $client_to_add['created'] = strtotime( $client_to_add['created'] );
1456 }
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 );
1474 } else {
1475 $client_to_add['created'] = time();
1476 }
1477
1478 try {
1479 $inserted = MainWP_DB_Client::instance()->update_client( $client_to_add, true );
1480 } catch ( \Exception $e ) {
1481 echo wp_json_encode( array( 'error' => $e->getMessage() ) );
1482 return;
1483 }
1484
1485 if ( $client_id ) {
1486 MainWP_DB_Client::instance()->update_selected_sites_for_client( $client_id, $selected_sites );
1487 } elseif ( is_object( $inserted ) ) {
1488 MainWP_DB_Client::instance()->update_selected_sites_for_client( $inserted->client_id, $selected_sites );
1489 $client_id = $inserted->client_id;
1490 }
1491
1492 if ( is_object( $inserted ) ) {
1493
1494 static::invalidate_warm_cache();
1495
1496 /**
1497 * Add client
1498 *
1499 * Fires after add a client.
1500 *
1501 * @param object $inserted client data.
1502 * @param bool $add_new true add new, false updated.
1503 *
1504 * @since 4.5.1.1
1505 */
1506 do_action( 'mainwp_client_updated', $inserted, $add_new );
1507
1508 if ( ! $add_new && $new_suspended != $old_suspended ) { //phpcs:ignore -- to valid.
1509 /**
1510 * Fires immediately after update client suspend/unsuspend.
1511 *
1512 * @since 4.5.1.1
1513 *
1514 * @param object $client client data.
1515 * @param bool $new_suspended true|false.
1516 */
1517 do_action( 'mainwp_client_suspend', $inserted, $new_suspended );
1518 }
1519 }
1520
1521 if ( $client_id && isset( $client_fields['custom_fields'] ) && is_array( $client_fields['custom_fields'] ) ) {
1522 foreach ( $client_fields['custom_fields'] as $field_val ) {
1523 $field_id = array_key_first( $field_val );
1524 // update custom field value for client.
1525 if ( $field_id ) {
1526 $val = $field_val[ $field_id ];
1527 MainWP_DB_Client::instance()->update_client_field_value( $field_id, $val, $client_id );
1528 }
1529 }
1530 }
1531
1532 $client_image = '';
1533 if ( isset( $_POST['mainwp_add_edit_client_uploaded_icon_hidden'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1534 $client_image = sanitize_text_field( wp_unslash( $_POST['mainwp_add_edit_client_uploaded_icon_hidden'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1535 }
1536
1537 // compatible with quick setup.
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
1540 if ( is_array( $output ) && isset( $output['filename'] ) && ! empty( $output['filename'] ) ) {
1541 $client_image = $output['filename'];
1542 }
1543 }
1544
1545 $client_data = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $client_id );
1546 if ( $client_data && $client_data->image !== $client_image && $client_id ) {
1547 $old_file = $client_data->image;
1548 if ( $old_file !== $client_image && ! empty( $old_file ) ) {
1549 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $old_file );
1550 }
1551 $update = array(
1552 'client_id' => $client_id,
1553 'image' => $client_image,
1554 );
1555 MainWP_DB_Client::instance()->update_client( $update );
1556 }
1557
1558 if ( $client_id && isset( $client_fields['default_field']['selected_icon'] ) ) {
1559 $cust_icon = sanitize_text_field( wp_unslash( $client_fields['default_field']['selected_icon'] ) );
1560 $cust_color = sanitize_hex_color( wp_unslash( $client_fields['default_field']['selected_color'] ) );
1561 $update = array(
1562 'client_id' => $client_id,
1563 'selected_icon_info' => 'selected:' . $cust_icon . ';color:' . $cust_color,
1564 );
1565 MainWP_DB_Client::instance()->update_client( $update );
1566 }
1567
1568 $is_first_contact = true;
1569 $auto_assign_contact_id = 0;
1570
1571 if ( $client_id && isset( $client_fields['contacts_field'] ) ) {
1572
1573 foreach ( $client_fields['contacts_field']['client.contact.name'] as $indx => $contact_name ) {
1574 $contact_to_add = array();
1575 if ( empty( $contact_name ) ) {
1576 continue;
1577 }
1578 $contact_to_add['contact_name'] = sanitize_text_field( wp_unslash( $contact_name ) );
1579
1580 $contact_email = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['contact.email'][ $indx ] ) );
1581 if ( empty( $contact_email ) ) {
1582 continue;
1583 }
1584
1585 $contact_id = isset( $client_fields['contacts_field']['contact_id'][ $indx ] ) ? intval( $client_fields['contacts_field']['contact_id'][ $indx ] ) : 0;
1586
1587 if ( empty( $contact_id ) ) {
1588 continue;
1589 }
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
1597 $contact_to_add['contact_email'] = $contact_email;
1598
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 ] ) );
1605
1606 $cust_icon = sanitize_text_field( wp_unslash( $client_fields['contacts_field']['selected_icon'][ $indx ] ) );
1607 $cust_color = sanitize_hex_color( wp_unslash( $client_fields['contacts_field']['selected_color'][ $indx ] ) );
1608
1609 $contact_to_add['contact_icon_info'] = 'selected:' . $cust_icon . ';color:' . $cust_color;
1610
1611 $contact_to_add['contact_client_id'] = $client_id;
1612 $contact_to_add['contact_id'] = $contact_id;
1613
1614 $updated = MainWP_DB_Client::instance()->update_client_contact( $contact_to_add );
1615
1616 $is_first_contact = false;
1617
1618 if ( $updated ) {
1619 $contact_data = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'contact_id', $contact_id );
1620 $contact_image = '';
1621 if ( isset( $_POST['mainwp_add_edit_contact_uploaded_icon_hidden']['contacts_field'][ $indx ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1622 $contact_image = sanitize_text_field( wp_unslash( $_POST['mainwp_add_edit_contact_uploaded_icon_hidden']['contacts_field'][ $indx ] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1623 }
1624 if ( $contact_data && $contact_data->contact_image !== $contact_image && $contact_id ) {
1625 $old_file = $contact_data->contact_image;
1626 if ( $old_file !== $contact_image && ! empty( $old_file ) ) {
1627 MainWP_Utility::instance()->delete_uploaded_icon_file( 'client-images', $old_file );
1628 }
1629 $update = array(
1630 'contact_id' => $contact_id,
1631 'contact_image' => $contact_image,
1632 );
1633 MainWP_DB_Client::instance()->update_client_contact( $update );
1634 }
1635 }
1636 }
1637 }
1638
1639 if ( $client_id && isset( $client_fields['new_contacts_field'] ) ) {
1640
1641 foreach ( $client_fields['new_contacts_field']['client.contact.name'] as $indx => $contact_name ) {
1642 $contact_to_add = array();
1643 if ( empty( $contact_name ) ) {
1644 continue;
1645 }
1646 $contact_to_add['contact_name'] = $contact_name;
1647
1648 $contact_email = $client_fields['new_contacts_field']['contact.email'][ $indx ];
1649 if ( empty( $contact_email ) ) {
1650 continue;
1651 }
1652 $contact_to_add['contact_email'] = $contact_email;
1653
1654 $contact_to_add['contact_phone'] = isset( $client_fields['new_contacts_field']['contact.phone'][ $indx ] ) ? $client_fields['new_contacts_field']['contact.phone'][ $indx ] : '';
1655 $contact_to_add['contact_role'] = $client_fields['new_contacts_field']['contact.role'][ $indx ];
1656 $contact_to_add['facebook'] = isset( $client_fields['new_contacts_field']['contact.facebook'][ $indx ] ) ? $client_fields['new_contacts_field']['contact.facebook'][ $indx ] : '';
1657 $contact_to_add['twitter'] = isset( $client_fields['new_contacts_field']['contact.twitter'][ $indx ] ) ? $client_fields['new_contacts_field']['contact.twitter'][ $indx ] : '';
1658 $contact_to_add['instagram'] = isset( $client_fields['new_contacts_field']['contact.instagram'][ $indx ] ) ? $client_fields['new_contacts_field']['contact.instagram'][ $indx ] : '';
1659 $contact_to_add['linkedin'] = isset( $client_fields['new_contacts_field']['contact.linkedin'][ $indx ] ) ? $client_fields['new_contacts_field']['contact.linkedin'][ $indx ] : '';
1660
1661 $cust_icon = isset( $client_fields['new_contacts_field']['selected_icon'][ $indx ] ) ? sanitize_text_field( wp_unslash( $client_fields['new_contacts_field']['selected_icon'][ $indx ] ) ) : '';
1662 $cust_color = isset( $client_fields['new_contacts_field']['selected_color'][ $indx ] ) ? sanitize_hex_color( wp_unslash( $client_fields['new_contacts_field']['selected_color'][ $indx ] ) ) : '';
1663
1664 $contact_to_add['contact_icon_info'] = 'selected:' . $cust_icon . ';color:' . $cust_color;
1665
1666 $contact_to_add['contact_client_id'] = $client_id;
1667
1668 $inserted = MainWP_DB_Client::instance()->update_client_contact( $contact_to_add );
1669
1670 if ( $inserted ) {
1671
1672 $contact_id = $inserted->contact_id;
1673 $contact_image = '';
1674 if ( isset( $_POST['mainwp_add_edit_contact_uploaded_icon_hidden']['new_contacts_field'][ $indx ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1675 $contact_image = sanitize_text_field( wp_unslash( $_POST['mainwp_add_edit_contact_uploaded_icon_hidden']['new_contacts_field'][ $indx ] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1676 }
1677
1678 if ( '' !== $contact_image && $contact_id ) {
1679 $update = array(
1680 'contact_id' => $contact_id,
1681 'contact_image' => $contact_image,
1682 );
1683 MainWP_DB_Client::instance()->update_client_contact( $update );
1684 }
1685
1686 if ( $is_first_contact && empty( $auto_assign_contact_id ) ) {
1687 $auto_assign_contact_id = $contact_id;
1688 }
1689 }
1690 }
1691 }
1692
1693 if ( $client_id && isset( $client_fields['delele_contacts'] ) && is_array( $client_fields['delele_contacts'] ) ) {
1694 foreach ( $client_fields['delele_contacts'] as $delete_id ) {
1695 MainWP_DB_Client::instance()->delete_client_contact( $client_id, $delete_id );
1696 $is_first_contact = false;
1697 }
1698 }
1699
1700 if ( $is_first_contact && $auto_assign_contact_id && $client_id ) {
1701 // auto assign.
1702 $update = array(
1703 'client_id' => $client_id,
1704 'primary_contact_id' => $auto_assign_contact_id,
1705 );
1706 MainWP_DB_Client::instance()->update_client( $update );
1707 }
1708
1709 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1710 if ( isset( $_POST['is_first_client'] ) && ! empty( $_POST['is_first_client'] ) ) {
1711 delete_transient( 'mainwp_transient_just_connected_site_id' );
1712 }
1713 //phpcs:enable
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
1728 echo wp_json_encode(
1729 array(
1730 'success' => 'yes',
1731 'client_id' => $client_id,
1732 )
1733 );
1734 }
1735
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 /**
1744 * Method render_add_client_modal().
1745 *
1746 * Renders add client Modal window.
1747 */
1748 public static function render_add_client_modal() {
1749 ?>
1750 <div id="mainwp-creating-new-client-modal" class="ui modal">
1751 <i class="close icon"></i>
1752 <div class="header"><?php esc_html_e( 'New client', 'mainwp' ); ?></div>
1753 <div class="ui message" id="mainwp-message-zone-client" style="display:none;"></div>
1754 <div class="scrolling content mainwp-modal-content">
1755 <form action="" method="post" enctype="multipart/form-data" name="createclient_form" id="createclient_form" class="add:clients: validate">
1756 <?php
1757 static::render_add_client_content();
1758 ?>
1759 </form>
1760 </div>
1761 <div class="actions">
1762 <div class="ui button green" current-page="modal-add" id="bulk_add_createclient"><?php esc_html_e( 'Add Client', 'mainwp' ); ?></div>
1763 </div>
1764 </div>
1765
1766 <script type="text/javascript">
1767 jQuery(document).on('click', '.edit-site-new-client-button', function () {
1768 jQuery('#mainwp-creating-new-client-modal').modal({
1769 allowMultiple: true,
1770 }).modal('show');
1771 return false;
1772 });
1773 </script>
1774 <?php
1775 }
1776
1777 /**
1778 * Method render_add_client_content().
1779 *
1780 * Renders add client content window.
1781 *
1782 * @param mixed $edit_client The client data.
1783 */
1784 public static function render_add_client_content( $edit_client = false ) { // phpcs:ignore -- NOSONAR -Current complexity is required to achieve desired results. Pull request solutions appreciated.
1785 $client_id = $edit_client ? $edit_client->client_id : 0;
1786 $default_client_fields = MainWP_Client_Handler::get_default_client_fields();
1787 $custom_fields = MainWP_DB_Client::instance()->get_client_fields( true, $client_id, true );
1788 $client_image = $edit_client ? $edit_client->image : '';
1789
1790 $icon_info_array = array();
1791 if ( $edit_client ) {
1792 $arr_fields = array(
1793 'image',
1794 'selected_icon_info',
1795 );
1796 $icon_info_array = MainWP_Utility::map_fields( $edit_client, $arr_fields, false );
1797 }
1798
1799 $uploaded_icon_src = '';
1800 if ( ! empty( $client_image ) ) {
1801 $uploaded_icon_src = MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'client', 'uploaded_icon' );
1802 }
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
1811 ?>
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">
1824 <?php
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 ];
1830 $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
1831 $val = $edit_client && '' !== $db_field && property_exists( $edit_client, $db_field ) ? $edit_client->{$db_field} : '';
1832 $tip = isset( $field['tooltip'] ) ? $field['tooltip'] : '';
1833 ?>
1834 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1835 <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 ?>>
1836 <?php
1837 $indi_val = $val && $edit_client ? 1 : 0;
1838 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
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 }
1843 ?>
1844 </label>
1845 <div class="ui six wide column">
1846 <div class="ui left labeled input">
1847 <?php
1848 if ( 'client.suspended' === $field_name ) {
1849 $el_id_fln_2 = $field_name;
1850 ?>
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 ); ?>]" >
1852 <option value="0" <?php echo '0' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Active', 'mainwp' ); ?></option>
1853 <option value="1" <?php echo '1' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Suspended', 'mainwp' ); ?></option>
1854 <option value="2" <?php echo '2' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lead', 'mainwp' ); ?></option>
1855 <option value="3" <?php echo '3' === $val ? 'selected' : ''; ?>><?php esc_html_e( 'Lost', 'mainwp' ); ?></option>
1856 </select>
1857 <?php
1858 } else {
1859 ?>
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 ); ?>]"/>
1861 <?php
1862 }
1863 ?>
1864 </div>
1865 </div>
1866 <?php if ( $client_id ) : ?>
1867 <div class="ui four wide middle aligned hidden token column" style="display:none">
1868 <?php if ( 'client.suspended' !== $field_name ) { ?>
1869 [<?php echo esc_html( $field_name ); ?>]
1870 <?php } ?>
1871 </div>
1872 <?php endif; ?>
1873 </div>
1874
1875 <?php if ( 'client.email' === $field_name ) { ?>
1876 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
1877 <label class="six wide column middle aligned">
1878 <?php
1879 $indi_val = $client_image && $edit_client ? 1 : 0;
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 ) );
1882 ?>
1883 <?php esc_html_e( 'Client logo (photo)', 'mainwp' ); ?>
1884 </label>
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 ); ?>">
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>
1901 </div>
1902 </div>
1903
1904 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client" default-indi-indi-value="wordpress">
1905 <label class="six wide column middle aligned">
1906 <?php
1907 $default_icons = MainWP_UI::get_default_icons();
1908 $selected_icon = 'wordpress'; //phpcs:ignore -- WP icon.
1909 $selected_color = '#34424D';
1910
1911 $icon_info = $edit_client ? $edit_client->selected_icon_info : '';
1912 if ( ! empty( $icon_info ) ) {
1913 $selected_icon = static::get_cust_client_icon( $icon_info, 'selected' );
1914 $selected_color = static::get_cust_client_icon( $icon_info, 'color' );
1915 }
1916
1917 $indi_val = 'wordpress' !== $selected_icon ? 1 : 0; //phpcs:ignore -- WP icon.
1918 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
1919 esc_html_e( 'Select icon', 'mainwp' );
1920 ?>
1921 </label>
1922 <input type="hidden" name="client_fields[default_field][selected_icon]" class="settings-field-value-change-handler" id="client_fields[default_field][selected_icon]" value="<?php echo esc_attr( $selected_icon ); ?>">
1923 <div class="six wide column" data-tooltip="<?php esc_attr_e( 'Select an icon if not using original client icon.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1924 <div class="ui left action input mainwp-dropdown-color-picker-field">
1925 <div class="ui five column selection search dropdown not-auto-init" id="mainwp_edit_clients_icon_select">
1926 <div class="text">
1927 <span style="color:<?php echo esc_attr( $selected_color ); ?>" ><?php echo ! empty( $selected_icon ) ? '<i class="' . esc_attr( $selected_icon ) . ' icon"></i>' : ''; ?></span>
1928 </div>
1929 <i class="dropdown icon"></i>
1930 <div class="menu">
1931 <?php foreach ( $default_icons as $icon ) : ?>
1932 <?php echo '<div class="item" style="color:' . esc_attr( $selected_color ) . '" data-value="' . esc_attr( $icon ) . '"><i class="' . esc_attr( $icon ) . ' icon"></i></div>'; ?>
1933 <?php endforeach; ?>
1934 </div>
1935 </div>
1936 <input type="color" data-tooltip="Color will update on save" data-position="top center" data-inverted="" name="client_fields[default_field][selected_color]" class="mainwp-color-picker-input" id="client_fields[default_field][selected_color]" value="<?php echo esc_attr( $selected_color ); ?>" />
1937 </div>
1938 </div>
1939 <div class="one wide column"></div>
1940 </div>
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>';
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
1990 }
1991 ?>
1992 </div>
1993 </div>
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
2109 $client_contacts = array();
2110 if ( $client_id ) {
2111 $client_contacts = MainWP_DB_Client::instance()->get_wp_client_contact_by( 'client_id', $client_id );
2112 ?>
2113 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
2114 <label class="six wide column middle aligned">
2115 <?php
2116 $indi_val = $edit_client && $client_contacts ? 1 : 0;
2117 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2118 esc_html_e( 'Client primary contact', 'mainwp' );
2119 ?>
2120 </label>
2121 <div class="ui six wide column">
2122 <div class="ui left labeled">
2123 <div class="ui search selection dropdown" init-value="" id="client_fields[default_field][primary_contact_id]">
2124 <input type="hidden" name="client_fields[default_field][primary_contact_id]" value="<?php echo $edit_client ? intval( $edit_client->primary_contact_id ) : 0; ?>">
2125 <i class="dropdown icon"></i>
2126 <div class="default text"><?php esc_attr_e( 'Select primary contact', 'mainwp' ); ?></div>
2127 <div class="menu">
2128 <div class="item" data-value="0"><?php esc_attr_e( 'Select primary contact', 'mainwp' ); ?></div>
2129 <?php if ( $client_contacts ) : ?>
2130 <?php foreach ( $client_contacts as $contact ) { ?>
2131 <div class="item" data-value="<?php echo intval( $contact->contact_id ); ?>"><?php echo esc_html( stripslashes( $contact->contact_name ) ); ?></div>
2132 <?php } ?>
2133 <?php endif; ?>
2134 </div>
2135 </div>
2136 </div>
2137 </div>
2138 <div class="ui four wide column">
2139 </div>
2140 </div>
2141 <div class="ui section hidden divider"></div>
2142 <?php
2143 }
2144
2145 if ( is_array( $custom_fields ) && count( $custom_fields ) > 0 ) {
2146 $compatible_tokens = MainWP_Client_Handler::get_compatible_tokens();
2147 foreach ( $custom_fields as $field ) {
2148 if ( isset( $default_client_fields[ $field->field_name ] ) ) {
2149 continue;
2150 }
2151 // do not show these tokens.
2152 if ( isset( $compatible_tokens[ $field->field_name ] ) ) {
2153 continue;
2154 }
2155 $field_val = ( property_exists( $field, 'field_value' ) && '' !== $field->field_value ) ? esc_html( $field->field_value ) : '';
2156 ?>
2157 <div class="ui grid field mainwp-field settings-field-indicator-wrapper settings-field-indicator-edit-client" field-id="<?php echo intval( $field->field_id ); ?>">
2158 <label class="six wide column middle aligned field-description">
2159 <?php
2160 $indi_val = $edit_client && $field_val ? 1 : 0;
2161 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2162 echo esc_html( $field->field_desc );
2163 ?>
2164 </label>
2165 <div class="ui six wide column">
2166 <div class="ui left labeled input">
2167 <input type="text" value="<?php echo esc_attr( $field_val ); ?>" class="regular-text" name="client_fields[custom_fields][<?php echo esc_html( $field->field_name ); ?>][<?php echo esc_html( $field->field_id ); ?>]"/>
2168 </div>
2169 </div>
2170 <div class="ui four wide column">
2171 <?php if ( $client_id > 0 && $field->client_id > 0 ) { // edit client and it is individual field, then show to edit/delete field buttons. ?>
2172 <div class="ui right pointing dropdown">
2173 <i class="ellipsis vertical icon"></i>
2174 <div class="menu">
2175 <a class="item" id="mainwp-clients-edit-custom-field" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
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>
2177 </div>
2178 </div>
2179 <?php } ?>
2180 <span class="field-name">[<?php echo esc_html( $field->field_name ); ?>]</span>
2181 </div>
2182 </div>
2183 <?php
2184 }
2185 }
2186
2187 $temp = static::get_add_contact_temp( false, false );
2188
2189 if ( $client_id && $client_contacts ) {
2190 foreach ( $client_contacts as $client_contact ) {
2191 static::get_add_contact_temp( $client_contact, true, $client_id );
2192 }
2193 }
2194 ?>
2195 <div class="ui grid field settings-field-indicator-wrapper settings-field-indicator-edit-client">
2196 <label class="six wide column middle aligned"><?php esc_html_e( 'Create a new contact for this client', 'mainwp' ); ?></label>
2197 <div class="ui six wide column">
2198 <div class="ui left labeled input">
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>
2200 </div>
2201 </div>
2202 </div>
2203 <div class="ui section hidden divider after-add-contact-field"></div>
2204 </div>
2205 </div>
2206 </div>
2207 <input type="hidden" name="client_fields[client_id]" value="<?php echo intval( $client_id ); ?>">
2208 <script type="text/javascript">
2209 jQuery( document ).ready( function () {
2210 mainwp_sidebar_accordion_init();
2211
2212 // to fix issue not loaded calendar js library
2213 if (jQuery('.ui.calendar').length > 0) {
2214 if (mainwpParams.use_wp_datepicker == 1) {
2215 jQuery('#mainwp-add-new-client-form .ui.calendar input[type=text]').datepicker({ dateFormat: "yy-mm-dd" });
2216 } else {
2217 mainwp_init_ui_calendar( '#mainwp-add-new-client-form .ui.calendar' );
2218 }
2219 }
2220
2221 let current_iconObj;
2222
2223 jQuery(document).on('click', '.mainwp-add-edit-client-icon-customable', function () {
2224 current_iconObj = jQuery(this);
2225 jQuery('#mainwp_delete_image_field').hide();
2226 jQuery('#mainwp-upload-custom-icon-modal').modal({
2227 allowMultiple: true, // multiple modals.
2228 closable: false,
2229 }).modal('show');
2230 jQuery('#update_custom_icon_btn').attr('uploading-icon', 'client');
2231 jQuery('#update_custom_icon_btn').removeAttr('disabled');
2232 jQuery('#mainwp_delete_image_field').find('#mainwp_delete_image_chk').attr('iconItemId', current_iconObj.attr('iconItemId') ); // @see used by mainwp_upload_custom_types_icon().
2233 jQuery('#mainwp_delete_image_field').find('#mainwp_delete_image_chk').attr('iconFileSlug', current_iconObj.attr('iconFileSlug') ); // @see used by mainwp_upload_custom_types_icon().
2234
2235 if (current_iconObj.attr('icon-src') != '') {
2236 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', current_iconObj.attr('icon-src'));
2237 jQuery('#mainwp_delete_image_field').show();
2238 }
2239 });
2240
2241 jQuery(document).on('click', '.mainwp-add-edit-contact-icon-customable', function () {
2242 current_iconObj = jQuery(this);
2243 jQuery('#mainwp_delete_image_field').hide();
2244 jQuery('#mainwp-upload-custom-icon-modal').modal({
2245 allowMultiple: true, // multiple modals.
2246 closable: false,
2247 }).modal('show');
2248 jQuery('#update_custom_icon_btn').attr('uploading-icon', 'contact');
2249 jQuery('#update_custom_icon_btn').removeAttr('disabled');
2250 jQuery('#mainwp_delete_image_field').find('#mainwp_delete_image_chk').attr('iconItemId', current_iconObj.attr('iconItemId') ); // @see used by mainwp_upload_custom_types_icon().
2251 jQuery('#mainwp_delete_image_field').find('#mainwp_delete_image_chk').attr('iconFileSlug', current_iconObj.attr('iconFileSlug') ); // @see used by mainwp_upload_custom_types_icon().
2252
2253 if (current_iconObj.attr('icon-src') != '') {
2254 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', current_iconObj.attr('icon-src'));
2255 jQuery('#mainwp_delete_image_field').show();
2256 }
2257 });
2258
2259 // to fix conflict with other update custom icon click event.
2260 jQuery(document).on('click', '#update_custom_icon_btn', function () {
2261 if( 'client' === jQuery(this).attr( 'uploading-icon' ) ){
2262 mainwp_update_custom_icon_client( current_iconObj );
2263 } else if( 'contact' === jQuery(this).attr( 'uploading-icon' ) ){
2264 mainwp_update_custom_icon_contact( current_iconObj );
2265 }
2266 });
2267
2268 mainwp_update_custom_icon_client = function( iconObj ){
2269 let deleteIcon = jQuery('#mainwp_delete_image_chk').is(':checked');
2270 let iconItemId = iconObj.attr('iconItemId');
2271 let iconFileSlug = iconObj.attr('iconFileSlug'); // to support delete file when iconItemId = 0.
2272
2273 // upload/delete lient icon action.
2274 mainwp_upload_custom_types_icon(iconObj, 'mainwp_add_edit_client_upload_client_icon', iconItemId, iconFileSlug, deleteIcon, function(response){
2275 if (jQuery('#mainwp_add_edit_client_uploaded_icon_hidden').length > 0) {
2276 if (typeof response.iconfile !== undefined) {
2277 jQuery('#mainwp_add_edit_client_uploaded_icon_hidden').val(response.iconfile);
2278 } else {
2279 jQuery('#mainwp_add_edit_client_uploaded_icon_hidden').val('');
2280 }
2281 jQuery( '#mainwp_add_edit_client_uploaded_icon_hidden' ).trigger('change');
2282 }
2283 let deleteIcon = jQuery('#mainwp_delete_image_chk').is(':checked'); // to delete.
2284 if(deleteIcon){
2285 jQuery('#mainwp_add_edit_client_upload_custom_icon').hide();
2286 } else if (jQuery('#mainwp_add_edit_client_upload_custom_icon').length > 0) {
2287 if (typeof response.iconfile !== undefined) {
2288 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
2289 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
2290 iconObj.attr('icon-src', icon_src);
2291 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2292 iconObj.attr('del-icon-nonce', response.iconnonce);
2293 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
2294 jQuery('#mainwp_add_edit_client_upload_custom_icon').html(icon_img);
2295 jQuery('#mainwp_add_edit_client_upload_custom_icon').show();
2296 }
2297 }
2298 setTimeout(function () {
2299 jQuery('#mainwp-upload-custom-icon-modal').modal('hide');
2300 }, 1000);
2301 });
2302 return false;
2303 }
2304
2305 mainwp_update_custom_icon_contact = function( iconObj ){
2306 let deleteIcon = jQuery('#mainwp_delete_image_chk').is(':checked');
2307 let iconItemId = iconObj.attr('iconItemId');
2308 let iconFileSlug = iconObj.attr('iconFileSlug'); // to support delete file when iconItemId = 0.
2309
2310 // upload/delete lient icon action.
2311 mainwp_upload_custom_types_icon(iconObj, 'mainwp_add_edit_contact_upload_contact_icon', iconItemId, iconFileSlug, deleteIcon, function(response){
2312 let parent = jQuery(iconObj).closest('.mainwp_edit_clients_contact_uploaded_icon_wrapper');
2313
2314 if (jQuery('#mainwp_add_edit_client_uploaded_icon_hidden').length > 0) {
2315 if (typeof response.iconfile !== undefined) {
2316 jQuery(parent).find('.mainwp_add_edit_contact_uploaded_icon_hidden').val(response.iconfile);
2317 } else {
2318 jQuery(parent).find('.mainwp_add_edit_contact_uploaded_icon_hidden').val('');
2319 }
2320 jQuery(parent).find( '.mainwp_add_edit_contact_uploaded_icon_hidden' ).trigger('change');
2321 }
2322 let deleteIcon = jQuery('#mainwp_delete_image_chk').is(':checked'); // to delete.
2323 if(deleteIcon){
2324 jQuery(parent).find('.mainwp_add_edit_contact_upload_custom_icon').hide();
2325 } else if (jQuery(parent).find('.mainwp_add_edit_contact_upload_custom_icon').length > 0) {
2326 if (typeof response.iconfile !== undefined) {
2327 let icon_img = typeof response.iconimg !== undefined ? response.iconimg : '';
2328 let icon_src = typeof response.iconsrc !== undefined ? response.iconsrc : '';
2329 iconObj.attr('icon-src', icon_src);
2330 iconObj.attr('iconFileSlug', response.iconfile); // to support delete file when iconItemId = 0.
2331 iconObj.attr('del-icon-nonce', response.iconnonce);
2332 jQuery('#mainwp_delete_image_field').find('.ui.image').attr('src', icon_src);
2333 jQuery(parent).find('.mainwp_add_edit_contact_upload_custom_icon').html(icon_img).show();
2334 }
2335 }
2336 setTimeout(function () {
2337 jQuery('#mainwp-upload-custom-icon-modal').modal('hide')
2338 }, 1000);
2339 });
2340 return false;
2341 }
2342
2343 } );
2344 </script>
2345 <?php
2346 }
2347
2348 /**
2349 * Method get_cust_client_icon()
2350 *
2351 * Get site icon.
2352 *
2353 * @param string $icon_data icon data.
2354 * @param string $type Type: selected|color|display.
2355 * @param string $what Icon display for what.
2356 */
2357 public static function get_cust_client_icon( $icon_data, $type = 'display', $what = 'default' ) {
2358 if ( empty( $icon_data ) ) {
2359 return '';
2360 }
2361 $data = explode( ';', $icon_data );
2362 $selected_icon = str_replace( 'selected:', '', $data[0] );
2363 $color = str_replace( 'color:', '', $data[1] );
2364
2365 if ( empty( $color ) ) {
2366 $color = '#34424D';
2367 }
2368
2369 $icon_cls = 'circular inverted icon';
2370 if ( 'card' === $what ) {
2371 $icon_cls = 'huge circular inverted icon';
2372 }
2373
2374 $output = '';
2375 if ( 'selected' === $type ) {
2376 $output = $selected_icon;
2377 } elseif ( 'color' === $type ) {
2378 $output = $color;
2379 } elseif ( 'display' === $type || 'display_edit' === $what ) {
2380 $color_style = '';
2381 if ( ! empty( $color ) ) {
2382 $color_style = 'background-color:' . esc_attr( $color ) . ';';
2383 }
2384 $icon_wrapper_attr = 'class="mainwp_client_icon_display"';
2385 if ( 'display_edit' === $what ) {
2386 $icon_wrapper_attr = ' id="mainwp_add_edit_client_upload_custom_icon" ' . $icon_wrapper_attr;
2387 }
2388 $output = '<div style="display:inline-block;" ' . $icon_wrapper_attr . ' ><i class="' . esc_attr( $selected_icon ) . ' ' . $icon_cls . '" style="' . $color_style . '"></i></div>';
2389 }
2390 return $output;
2391 }
2392
2393 /**
2394 * Method get_add_contact_temp().
2395 *
2396 * Get add contact template.
2397 *
2398 * @param mixed $edit_contact The contact data to edit.
2399 * @param bool $echo_out Echo template or not.
2400 * @param int $client_id Client id.
2401 */
2402 public static function get_add_contact_temp( $edit_contact = false, $echo_out = false, $client_id = 0 ) { //phpcs:ignore -- NOSONAR - complex.
2403
2404 $input_name = 'new_contacts_field';
2405 $contact_id = 0;
2406 $contact_image = '';
2407 if ( $edit_contact ) {
2408 $input_name = 'contacts_field';
2409 $contact_id = $edit_contact->contact_id;
2410 $contact_image = $edit_contact->contact_image;
2411 }
2412
2413 $uploaded_icon_src = '';
2414 if ( ! empty( $contact_image ) ) {
2415 $arr_fields = array(
2416 'contact_image',
2417 'contact_icon_info',
2418 );
2419 $icon_info_array = MainWP_Utility::map_fields( $edit_contact, $arr_fields, false );
2420 $uploaded_icon_src = MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'contact', 'uploaded_icon' );
2421 }
2422
2423 ob_start();
2424 ?>
2425 <h3 class="ui dividing header top-contact-fields"> <?php // must have class: top-contact-fields. ?>
2426 <?php if ( $edit_contact ) : ?>
2427 <?php echo esc_html__( 'Edit Contact', 'mainwp' ); ?>
2428 <div class="sub header"><?php esc_html_e( 'Edit contact person information.', 'mainwp' ); ?></div>
2429 <?php else : ?>
2430 <?php esc_html_e( 'Add Contact', 'mainwp' ); ?>
2431 <div class="sub header"><?php esc_html_e( 'Enter contact person information.', 'mainwp' ); ?></div>
2432 <?php endif; ?>
2433 </h3>
2434 <?php
2435 $default_icons = MainWP_UI::get_default_icons();
2436 $contact_fields = MainWP_Client_Handler::get_default_contact_fields();
2437 foreach ( $contact_fields as $field_name => $field ) {
2438 $db_field = isset( $field['db_field'] ) ? $field['db_field'] : '';
2439 $val = $edit_contact && '' !== $db_field && property_exists( $edit_contact, $db_field ) ? $edit_contact->{$db_field} : '';
2440 $contact_id = $edit_contact && property_exists( $edit_contact, 'contact_id' ) ? $edit_contact->contact_id : '';
2441 ?>
2442 <div class="ui grid field settings-field-indicator-wrapper">
2443 <label class="six wide column middle aligned">
2444 <?php
2445 $indi_val = $edit_contact && $val ? 1 : 0;
2446 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
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 }
2451 ?>
2452 </label>
2453 <div class="ui six wide column">
2454 <div class="ui left labeled input">
2455 <input type="text" value="<?php echo esc_attr( $val ); ?>" class="regular-text settings-field-value-change-handler" name="client_fields[<?php echo esc_attr( $input_name ); ?>][<?php echo esc_attr( $field_name ); ?>][]"/>
2456 </div>
2457 </div>
2458 <?php if ( $edit_contact ) : ?>
2459 <div class="ui four wide middle aligned hidden token column" style="display:none">
2460 [<?php echo esc_html( $field_name ); ?>]
2461 </div>
2462 <?php endif; ?>
2463 </div>
2464 <?php
2465 if ( 'contact.role' === $field_name ) {
2466 ?>
2467 <div class="ui grid field mainwp_edit_clients_contact_uploaded_icon_wrapper settings-field-indicator-wrapper">
2468 <label class="six wide column middle aligned">
2469 <?php
2470 $indi_val = $edit_contact && $contact_image ? 1 : 0;
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 ) );
2473 ?>
2474 <?php esc_html_e( 'Contact photo', 'mainwp' ); ?>
2475 </label>
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 ); ?>">
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">
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>
2479 <?php
2480 if ( ! empty( $contact_image ) ) {
2481 ?>
2482 <?php echo MainWP_Client_Handler::get_client_contact_image( $icon_info_array, 'contact', 'display_edit' ); //phpcs:ignore --ok. ?>
2483 <?php } else { ?>
2484 <div style="display:inline-block;" class="mainwp_add_edit_contact_upload_custom_icon"></div> <?php // used for icon holder. ?>
2485 <?php } ?>
2486 </div>
2487 </div>
2488 <div class="ui grid field mainwp_edit_clients_contact_icon_wrapper settings-field-indicator-wrapper" input-name="<?php echo esc_attr( $input_name ); ?>" default-indi-indi-value="wordpress">
2489 <label class="six wide column middle aligned">
2490 <?php
2491 $selected_icon = 'wordpress'; //phpcs:ignore -- WP icon.
2492 $selected_color = '#34424D';
2493 $icon_info = $edit_contact ? $edit_contact->contact_icon_info : '';
2494
2495 if ( ! empty( $icon_info ) ) {
2496 $selected_icon = static::get_cust_client_icon( $icon_info, 'selected' );
2497 $selected_color = static::get_cust_client_icon( $icon_info, 'color' );
2498 }
2499 $indi_val = 'wordpress' !== $selected_icon ? 1 : 0; //phpcs:ignore -- WP icon.
2500 MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $indi_val );
2501 esc_html_e( 'Select icon', 'mainwp' );
2502 ?>
2503 </label>
2504 <div class="six wide column" data-tooltip="<?php esc_attr_e( 'Select an icon if not using original contact icon.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
2505 <input type="hidden" class="settings-field-value-change-handler" name="client_fields[<?php echo esc_html( $input_name ); ?>][selected_icon][]" id="client_fields[<?php echo esc_attr( $input_name ); ?>][selected_icon][]" value="<?php echo esc_attr( $selected_icon ); ?>">
2506 <div class="ui left action input mainwp-dropdown-color-picker-field">
2507 <div class="ui five column selection search dropdown not-auto-init mainwp-edit-clients-select-contact-icon" style="min-width:21em">
2508 <div class="text">
2509 <span style="color:<?php echo esc_attr( $selected_color ); ?>" ><?php echo ! empty( $selected_icon ) ? '<i class="' . esc_attr( $selected_icon ) . ' icon"></i>' : ''; ?></span>
2510 </div>
2511 <i class="dropdown icon"></i>
2512 <div class="menu">
2513 <?php foreach ( $default_icons as $icon ) : ?>
2514 <?php echo '<div class="item" style="color:' . esc_attr( $selected_color ) . '" data-value="' . esc_attr( $icon ) . '"><i class="' . esc_attr( $icon ) . ' icon"></i></div>'; ?>
2515 <?php endforeach; ?>
2516 </div>
2517 </div>
2518 <input type="color" data-tooltip="Color will update on save" data-position="top center" data-inverted="" name="client_fields[<?php echo esc_html( $input_name ); ?>][selected_color][]" class="mainwp-color-picker-input" id="client_fields[<?php echo esc_html( $input_name ); ?>][selected_color][]" value="<?php echo esc_attr( $selected_color ); ?>" />
2519 </div>
2520 </div>
2521 <div class="one wide column"></div>
2522 </div>
2523 <?php
2524 }
2525 }
2526
2527 ?>
2528 <div class="ui grid field remove-contact-field-parent">
2529 <label class="six wide column middle aligned"><?php esc_html_e( 'Remove contact', 'mainwp' ); ?></label>
2530 <div class="ui six wide column">
2531 <div class="ui left labeled input">
2532 <a href="javascript:void(0);" contact-id="<?php echo intval( $contact_id ); ?>" class="ui basic button mainwp-client-remove-contact"><?php esc_html_e( 'Remove contact', 'mainwp' ); ?></a>
2533 </div>
2534 <?php
2535 if ( $edit_contact ) {
2536 ?>
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
2540 }
2541 ?>
2542 </div>
2543 </div>
2544 <div class="ui section hidden divider bottom-contact-fields"></div>
2545 <?php
2546 $html = ob_get_clean();
2547
2548 if ( $echo_out ) {
2549 echo $html; //phpcs:ignore -- validated content.
2550 }
2551
2552 return $html;
2553 }
2554
2555 /**
2556 * Method save_client_field().
2557 *
2558 * Save custom fields.
2559 */
2560 public static function save_client_field() { //phpcs:ignore -- NOSONAR - complex.
2561
2562 $return = array(
2563 'success' => false,
2564 'error' => '',
2565 'message' => '',
2566 );
2567
2568 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2569 $client_id = isset( $_POST['client_id'] ) ? intval( $_POST['client_id'] ) : 0; // 0 is global client's field.
2570 $field_id = isset( $_POST['field_id'] ) ? intval( $_POST['field_id'] ) : 0;
2571 $field_desc = isset( $_POST['field_desc'] ) ? sanitize_text_field( wp_unslash( $_POST['field_desc'] ) ) : '';
2572 $field_name = isset( $_POST['field_name'] ) ? sanitize_text_field( wp_unslash( $_POST['field_name'] ) ) : '';
2573 $field_name = trim( $field_name, '[]' );
2574 // phpcs:enable
2575
2576 // update general or individual client field.
2577 if ( $field_id ) {
2578 $current = MainWP_DB_Client::instance()->get_client_fields_by( 'field_id', $field_id );
2579 if ( $current && $current->field_name === $field_name && $current->field_desc === $field_desc ) {
2580 $return['success'] = true;
2581 $return['message'] = esc_html__( 'Field has been saved without changes.', 'mainwp' );
2582 } else {
2583 $current = MainWP_DB_Client::instance()->get_client_fields_by( 'field_name', $field_name, $client_id ); // check if other field with the same name existed.
2584 if ( $current && (int) $current->field_id !== $field_id ) {
2585 $return['error'] = esc_html__( 'Field already exists, try different field name.', 'mainwp' );
2586 } else {
2587 // update general or individual field name.
2588 $field = MainWP_DB_Client::instance()->update_client_field(
2589 $field_id,
2590 array(
2591 'field_name' => $field_name,
2592 'field_desc' => $field_desc,
2593 'client_id' => $client_id,
2594 )
2595 );
2596 if ( $field ) {
2597 $return['success'] = true;
2598 }
2599 }
2600 }
2601 } else { // add new.
2602 $current = MainWP_DB_Client::instance()->get_client_fields_by( 'field_name', $field_name, $client_id );
2603 if ( $current ) { // checking general or individual field name.
2604 $return['error'] = esc_html__( 'Field already exists, try different field name.', 'mainwp' );
2605 } else {
2606 // insert general or individual field name.
2607 $field = MainWP_DB_Client::instance()->add_client_field(
2608 array(
2609 'field_name' => $field_name,
2610 'field_desc' => $field_desc,
2611 'client_id' => $client_id,
2612 )
2613 );
2614
2615 if ( $field ) {
2616 $return['success'] = true;
2617 } else {
2618 $return['error'] = esc_html__( 'Undefined error occurred. Please try again.', 'mainwp' );
2619 }
2620 }
2621 }
2622 echo wp_json_encode( $return );
2623 exit;
2624 }
2625
2626 /**
2627 * Method save_note()
2628 *
2629 * Save Client Note.
2630 */
2631 public static function save_note() {
2632 if ( isset( $_POST['clientid'] ) && ! empty( $_POST['clientid'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2633 $note = isset( $_POST['note'] ) ? wp_unslash( $_POST['note'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2634 $esc_note = MainWP_Utility::esc_content( $note );
2635 $update = array(
2636 'client_id' => intval( $_POST['clientid'] ), // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2637 'note' => $esc_note,
2638 );
2639 MainWP_DB_Client::instance()->update_client( $update );
2640 die(
2641 wp_json_encode(
2642 array(
2643 'result' => 'SUCCESS',
2644 'esc_note_content' => $esc_note,
2645 )
2646 )
2647 );
2648 }
2649 die( wp_json_encode( array( 'undefined_error' => true ) ) );
2650 }
2651 }
2652