__CLASS__, 'save-key' => 'id', ); return $classes; } /** * Add custom field type to list * * @param array $cf_types - custom field types array. * @return array */ public static function add_cf_type( $cf_types ) { $cf_types[ self::$slug ] = array( 'label' => esc_attr__( 'Dropdown (multi-select)', 'supportcandy' ), 'class' => __CLASS__, ); return $cf_types; } /** * Print operators for ticket form filter * * @param WPSC_Custom_Field $cf - custom field object. * @param array $filter - Existing filters (if any). * @return void */ public static function get_operators( $cf, $filter = array() ) { ?>
get_options(); $unique_id = uniqid( 'wpsc_' ); ?>
$value ) { if ( $value == '' ) { $val[ $index ] = '^$'; } } $str = self::get_sql_slug( $cf ) . ' RLIKE \'(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])\''; break; case 'NOT IN': foreach ( $val as $index => $value ) { if ( $value == '' ) { $val[ $index ] = '^$'; } } $str = self::get_sql_slug( $cf ) . ' NOT RLIKE \'(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])\''; break; default: $str = '1=1'; } return $str; } /** * Check ticket condition * * @param array $condition - array with condition data. * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @return boolean */ public static function is_valid_ticket_condition( $condition, $cf, $ticket ) { $flag = true; $cf_ids = array_map( fn( $option ) => $option->id, $ticket->{$cf->slug} ); switch ( $condition['operator'] ) { case '=': $flag = in_array( $condition['operand_val_1'], $cf_ids ); break; case 'IN': $flag = false; foreach ( $cf_ids as $id ) { if ( in_array( $id, $condition['operand_val_1'] ) ) { $flag = true; break; } } break; case 'NOT IN': foreach ( $cf_ids as $id ) { if ( in_array( $id, $condition['operand_val_1'] ) ) { $flag = false; break; } } break; default: $flag = true; } return $flag; } /** * Check customer condition * * @param array $condition - array with condition data. * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Customer $customer - customer object. * @return boolean */ public static function is_valid_customer_condition( $condition, $cf, $customer ) { $flag = true; $cf_ids = array_map( fn( $option ) => $option->id, $customer->{$cf->slug} ); switch ( $condition['operator'] ) { case '=': $flag = in_array( $condition['operand_val_1'], $cf_ids ); break; case 'IN': $flag = false; foreach ( $cf_ids as $id ) { if ( in_array( $id, $condition['operand_val_1'] ) ) { $flag = true; break; } } break; case 'NOT IN': foreach ( $cf_ids as $id ) { if ( in_array( $id, $condition['operand_val_1'] ) ) { $flag = false; break; } } break; default: $flag = true; } return $flag; } /** * Print ticket form field * * @param WPSC_Custom_Field $cf - Custom field object. * @param array $tff - Array of ticket form field settings for this field. * @return string */ public static function print_tff( $cf, $tff ) { $options = $cf->get_options(); $val = array(); if ( $cf->field == 'ticket' ) { $val = $cf->is_auto_fill && $cf->default_value ? $cf->default_value : array(); } else { $current_user = WPSC_Current_User::$current_user; if ( $current_user->is_customer && $current_user->customer->{$cf->slug} ) { $val = array_map( fn( $option )=>$option->id, $current_user->customer->{$cf->slug} ); } } $unique_id = uniqid( 'wpsc_' ); ob_start(); ?>
name ); ?> *
extra_info ); ?>
case '': var val = customField.find('select').first().val(); if (customField.hasClass('required') && val.length === 0) { isValid = false; alert(supportcandy.translations.req_fields_missing); } break; default_value ? implode( '|', $cf->default_value ) : ''; } /** * Check and return custom field value for new ticket to be created. * This function is used by filter for set create ticket form and called directly by my-profile for each applicable custom fields. * Ignore phpcs nonce issue as we already checked where it is called from. * * @param array $data - Array of values to to stored in ticket in an insert function. * @param array $custom_fields - Array containing all applicable custom fields indexed by unique custom field types. * @param boolean $is_my_profile - Whether it or not it is created from my-profile. This function is used by create ticket as well as my-profile. Due to customer fields handling is done same way, this flag gives apportunity to identify where it being called. * @return array */ public static function set_create_ticket_data( $data, $custom_fields, $is_my_profile ) { if ( isset( $custom_fields[ self::$slug ] ) ) { foreach ( $custom_fields[ self::$slug ] as $cf ) { $value = self::get_tff_value( $cf->slug ); if ( $cf->field == 'ticket' ) { $default_val = self::get_default_value( $cf ); $data[ $cf->slug ] = $value ? implode( '|', $value ) : $default_val; } elseif ( $cf->field == 'agentonly' ) { $data[ $cf->slug ] = self::get_default_value( $cf ); } elseif ( $cf->field == 'customer' && $data['customer'] != 0 ) { $tff = get_option( 'wpsc-tff' ); if ( ! $is_my_profile && ! isset( $tff[ $cf->slug ] ) ) { continue; } $customer = new WPSC_Customer( $data['customer'] ); $existing_val = array_map( fn( $option )=>$option->id, $customer->{$cf->slug} ); if ( array_diff( $existing_val, $value ) || array_diff( $value, $existing_val ) ) { $customer->{$cf->slug} = $value; $customer->save(); $prev_val = $existing_val ? implode( '|', $existing_val ) : ''; $new_val = $value ? implode( '|', $value ) : ''; // Set log for this change. WPSC_Log::insert( array( 'type' => 'customer', 'ref_id' => $customer->id, 'modified_by' => WPSC_Current_User::$current_user->customer->id, 'body' => wp_json_encode( array( 'slug' => $cf->slug, 'prev' => $prev_val, 'new' => $new_val, ) ), 'date_created' => ( new DateTime() )->format( 'Y-m-d H:i:s' ), ) ); } } } } return $data; } /** * Set create ticket data for rest api request * * @param array $data - create ticket data array. * @param WP_REST_Request $request - rest request object. * @param array $custom_fields - custom field objects indexed by unique custom field types. * @return array */ public static function set_rest_ticket_data( $data, $request, $custom_fields ) { $current_user = WPSC_Current_User::$current_user; $tff = get_option( 'wpsc-tff' ); if ( isset( $custom_fields[ self::$slug ] ) ) { foreach ( $custom_fields[ self::$slug ] as $cf ) { if ( ! in_array( $cf->field, array( 'ticket', 'agentonly', 'customer' ) ) || ( $cf->field == 'customer' && ! isset( $tff[ $cf->slug ] ) ) ) { continue; } $value = sanitize_text_field( $request->get_param( $cf->slug ) ); if ( $value ) { $value = implode( '|', array_filter( array_map( function ( $id ) { $option = new WPSC_Option( intval( $id ) ); return $option->id ? $option->id : false; }, explode( ',', $value ) ) ) ); } if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) { $data[ $cf->slug ] = $cf->field == 'ticket' && $value ? $value : self::get_default_value( $cf ); } else { $customer = new WPSC_Customer( $data['customer'] ); $existing_val = array_filter( array_map( fn( $option ) => $option->id ? $option->id : false, $customer->{$cf->slug} ) ); $new_val = array_filter( explode( '|', $value ) ); if ( $new_val && ( array_diff( $existing_val, $new_val ) || array_diff( $new_val, $existing_val ) ) ) { $customer->{$cf->slug} = $new_val; $customer->save(); // Set log for this change.. WPSC_Log::insert( array( 'type' => 'customer', 'ref_id' => $customer->id, 'modified_by' => $current_user->customer->id, 'body' => wp_json_encode( array( 'slug' => $cf->slug, 'prev' => implode( '|', $existing_val ), 'new' => $value, ) ), 'date_created' => ( new DateTime() )->format( 'Y-m-d H:i:s' ), ) ); } } } } return $data; } /** * Return slug string to be used in where condition of ticket model for this type of field * * @param WPSC_Custom_Field $cf - custom field object. * @return string */ public static function get_sql_slug( $cf ) { $join_char = in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ? 't.' : 'c.'; return $join_char . $cf->slug; } /** * Add ticket search compatibility for fields of this custom field type. * * @param array $sql - Array of sql peices that can be joined later. * @param array $filter - User filter. * @param array $custom_fields - Custom fields array applicable for search. * @param string $search - search string. * @param array $allowed_search_fields - Allowed search fields. * @return array */ public static function ticket_search( $sql, $filter, $custom_fields, $search, $allowed_search_fields ) { if ( isset( $custom_fields[ self::$slug ] ) ) { $search_items = false; foreach ( $custom_fields[ self::$slug ] as $cf ) { if ( in_array( $cf->slug, $allowed_search_fields ) ) { if ( ! $search_items ) { $search_items = WPSC_Option::get_tl_search_string( $search ); if ( ! $search_items ) { break; } } $join_char = in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ? 't.' : 'c.'; $sql[] = $join_char . $cf->slug . ' RLIKE \'(^|[|])(' . implode( '|', $search_items ) . ')($|[|])\''; } } } return $sql; } /** * Return val field for meta query of this type of custom field * * @param array $condition - condition data. * @return mixed */ public static function get_meta_value( $condition ) { $operator = $condition['operator']; switch ( $operator ) { case '=': case 'IN': case 'NOT IN': return $condition['operand_val_1']; } return false; } /** * Print generic input field for this type. * * @param WPSC_Custom_Field $cf - custom field object. * @param mixed $value - optional. Input field will be printed with given value. * @return void */ public static function print_cf_input( $cf, $value = array() ) { if ( ! is_array( $value ) ) { $value = array_filter( array_map( function ( $val ) { $option = new WPSC_Option( $val ); return $option->id ? $option : ''; }, explode( '|', $value ) ) ); } $options = $cf->get_options(); $unique_id = uniqid( 'wpsc_' ); ?>
name ); ?>
extra_info ); if ( $extra_info ) : ?> extra_info ); ?>
slug ] ) ? array_filter( array_map( 'intval', $_POST[ $cf->slug ] ) ) : array(); // phpcs:ignore return $value ? implode( '|', $value ) : ''; } /** * Print edit ticket custom field in individual ticket * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @return void */ public static function print_edit_ticket_cf( $cf, $ticket ) { $options = $cf->get_options(); $unique_id = uniqid( 'wpsc_' ); ?>
name ); ?>
extra_info ); if ( $extra_info ) : ?> extra_info ); ?>
{$cf->slug} ? $ticket->{$cf->slug} : array(); $prev_ids = array_filter( array_map( fn( $option ) => $option->id ? $option->id : '', $prev ) ); $new_ids = isset( $_POST[ $cf->slug ] ) ? array_filter( array_map( 'intval', $_POST[ $cf->slug ] ) ) : array(); // phpcs:ignore // Exit if there is no change. if ( ! ( array_diff( $prev_ids, $new_ids ) || array_diff( $new_ids, $prev_ids ) ) ) { return $ticket; } // Create wpsc_option objects. $new = array_filter( array_map( function ( $id ) { $option = new WPSC_Option( $id ); return $option->id ? $option : ''; }, $new_ids ) ); // Change value. $ticket->{$cf->slug} = $new; $ticket->save(); return $ticket; } /** * Modify ticket field value of this custom field type using rest api * * @param WPSC_Ticket $ticket - ticket object. * @param WPSC_Custom_Field $cf - custom field. * @param mixed $value - value to be set. * @return void */ public static function set_rest_edit_ticket_cf( $ticket, $cf, $value ) { $new = array_unique( array_filter( array_map( function ( $id ) { $option = new WPSC_Option( intval( $id ) ); return $option->id ? $option->id : false; }, explode( ',', sanitize_text_field( $value ) ) ) ) ); $prev = is_array( $ticket->{$cf->slug} ) ? $ticket->{$cf->slug} : array(); $prev = array_filter( array_map( fn( $option ) => $option->id ? $option->id : false, $prev ) ); if ( array_diff( $prev, $new ) || array_diff( $new, $prev ) ) { $ticket->{$cf->slug} = $new; } } /** * Insert log thread for this custom field type change * * @param WPSC_Custom_Field $cf - current custom field of this type. * @param WPSC_Ticket $prev - ticket object before making any changes. * @param WPSC_Ticket $new - ticket object after making changes. * @param string $current_date - date string to be stored as create time. * @param int $customer_id - current user customer id for blame. * @return void */ public static function insert_ticket_log( $cf, $prev, $new, $current_date, $customer_id ) { $prev_ids = array_filter( array_map( fn( $option ) => $option->id ? $option->id : '', $prev->{$cf->slug} ) ); $new_ids = array_filter( array_map( fn( $option )=>$option->id ? $option->id : '', $new->{$cf->slug} ) ); // Exit if there is no change. if ( ! ( array_diff( $prev_ids, $new_ids ) || array_diff( $new_ids, $prev_ids ) ) ) { return; } $prev_val = $prev_ids ? implode( '|', $prev_ids ) : ''; $new_val = $new_ids ? implode( '|', $new_ids ) : ''; $thread = WPSC_Thread::insert( array( 'ticket' => $prev->id, 'customer' => $customer_id, 'type' => 'log', 'body' => wp_json_encode( array( 'slug' => $cf->slug, 'prev' => $prev_val, 'new' => $new_val, ) ), 'date_created' => $current_date, 'date_updated' => $current_date, ) ); } /** * Return data for this custom field while creating duplicate ticket * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @return mixed */ public static function get_duplicate_ticket_data( $cf, $ticket ) { $val = $ticket->{$cf->slug}; $response = array(); foreach ( $val as $option ) { $response[] = $option->id; } return $response ? implode( '|', $response ) : ''; } /** * Print edit field for this type in edit customer info * * @param WPSC_Custom_field $cf - custom field object. * @param WPSC_Customer $customer - customer object. * @param array $tff - ticket form field data. * @return string */ public static function print_edit_customer_info( $cf, $customer, $tff ) { $options = $cf->get_options(); $val = array(); if ( $customer->id && $customer->{$cf->slug} ) { foreach ( $customer->{$cf->slug} as $option ) { $val[] = $option->id; } } $unique_id = uniqid( 'wpsc_' ); ob_start(); ?>
name ); ?>
extra_info ); ?>
get_options(); foreach ( $options as $option ) : ?>
name ); ?>
extra_info = isset( $_POST['extra_info'] ) ? sanitize_text_field( wp_unslash( $_POST['extra_info'] ) ) : ''; // phpcs:ignore } // options. $options = isset( $_POST['options'] ) ? array_filter( array_map( 'sanitize_text_field', wp_unslash($_POST['options']) ) ) : array(); // phpcs:ignore if ( ! $options ) { wp_send_json_error( new WP_Error( '001', 'Bad request!' ), 400 ); } // default value. if ( in_array( 'default_value', $field_class::$allowed_properties ) ) { $cf->default_value = isset( $_POST['default-val-option-multi'] ) ? array_filter( array_map( 'intval', $_POST['default-val-option-multi'] ) ) : array(); // phpcs:ignore } // auto fill. if ( in_array( 'is_auto_fill', $field_class::$allowed_properties ) ) { $cf->is_auto_fill = isset( $_POST['is_auto_fill'] ) ? sanitize_text_field( wp_unslash( $_POST['is_auto_fill'] ) ) : ''; // phpcs:ignore } // placeholder! if ( in_array( 'placeholder_text', $field_class::$allowed_properties ) ) { $cf->placeholder_text = isset( $_POST['placeholder_text'] ) ? sanitize_text_field( wp_unslash( $_POST['placeholder_text'] ) ) : ''; // phpcs:ignore } // personal info. if ( in_array( 'is_personal_info', $field_class::$allowed_properties ) ) { $cf->is_personal_info = isset( $_POST['is_personal_info'] ) ? intval( $_POST['is_personal_info'] ) : 0; // phpcs:ignore } // my-profile. if ( in_array( 'allow_my_profile', $field_class::$allowed_properties ) ) { $cf->allow_my_profile = isset( $_POST['allow_my_profile'] ) ? intval( $_POST['allow_my_profile'] ) : 0; // phpcs:ignore } // ticket form. if ( in_array( 'allow_ticket_form', $field_class::$allowed_properties ) ) { $cf->allow_ticket_form = isset( $_POST['allow_ticket_form'] ) ? intval( $_POST['allow_ticket_form'] ) : 0; // phpcs:ignore } // tl_width! if ( in_array( 'tl_width', $field_class::$allowed_properties ) ) { $tl_width = isset( $_POST['tl_width'] ) ? intval( $_POST['tl_width'] ) : 0; // phpcs:ignore $cf->tl_width = $tl_width ? $tl_width : 100; } // save! $cf->save(); $cf->set_options( $options, true ); } /** * Returns printable ticket value for custom field. Can be used in export tickets, replace macros etc. * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @param string $module - module name. * @return string */ public static function get_ticket_field_val( $cf, $ticket, $module = '' ) { $names = array_filter( array_map( fn( $option ) => $option->id ? $option->name : '', $ticket->{$cf->slug} ) ); $value = $names ? implode( ', ', $names ) : ''; return apply_filters( 'wpsc_ticket_field_val_multi_select', $value, $cf, $ticket, $module ); } /** * Print ticket value for given custom field on ticket list * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @return void */ public static function print_tl_ticket_field_val( $cf, $ticket ) { echo esc_attr( self::get_ticket_field_val( $cf, $ticket ) ); } /** * Print ticket value for given custom field on widget * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Ticket $ticket - ticket object. * @return void */ public static function print_widget_ticket_field_val( $cf, $ticket ) { echo esc_attr( self::get_ticket_field_val( $cf, $ticket ) ); } /** * Returns printable customer value for custom field. Can be used in export tickets, replace macros etc. * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Customer $customer - customer object. * @return string */ public static function get_customer_field_val( $cf, $customer ) { $names = array_filter( array_map( fn( $option ) => $option->id ? $option->name : '', $customer->{$cf->slug} ) ); return $names ? implode( ', ', $names ) : ''; } /** * Print customer value for given custom field on ticket list * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Customer $customer - customer object. * @return void */ public static function print_tl_customer_field_val( $cf, $customer ) { echo esc_attr( self::get_customer_field_val( $cf, $customer ) ); } /** * Print customer value for given custom field on widget * * @param WPSC_Custom_Field $cf - custom field object. * @param WPSC_Customer $customer - customer object. * @return void */ public static function print_widget_customer_field_val( $cf, $customer ) { echo esc_attr( self::get_customer_field_val( $cf, $customer ) ); } /** * Print given value for custom field * * @param WPSC_Custom_Field $cf - custom field object. * @param mixed $val - value to convert and print. * @return void */ public static function print_val( $cf, $val ) { $val = is_array( $val ) ? $val : array_filter( explode( '|', $val ) ); $options = array_filter( array_map( function ( $option ) { if ( is_object( $option ) ) { return $option; } elseif ( $option ) { $option = new WPSC_Option( $option ); return $option->id ? $option : ''; } else { return ''; } }, $val ) ); $option_names = array_map( fn( $option ) => $option->name, $options ); echo $option_names ? esc_attr( implode( ', ', $option_names ) ) : esc_attr__( 'None', 'supportcandy' ); } /** * Return printable value for history log macro * * @param WPSC_Custom_Field $cf - custom field object. * @param mixed $val - value to convert and return. * @return string */ public static function get_history_log_val( $cf, $val ) { ob_start(); self::print_val( $cf, $val ); return ob_get_clean(); } /** * Print dashboard activity function * * @param WPSC_Custom_Field $cf - custom field object. * @param array $recent_logs - recent_logs object. * @param array $body - body object. * @param int $view - check if frontend. * @return string */ public static function print_activity( $cf, $recent_logs, $body, $view ) { $url = WPSC_Functions::get_ticket_url( $recent_logs->ticket->id, $view ); $ms_values = explode( '|', $body->new ); foreach ( $ms_values as $ms_value ) { $new_ms = new WPSC_Option( $ms_value ); if ( $new_ms->id ) { $new_ms_values[] = esc_attr( $new_ms->name ); } } if ( ! empty( $new_ms_values ) ) { $ms_names = implode( ', ', $new_ms_values ); } else { $ms_names = 'None'; } return esc_attr( $recent_logs->customer->name ) . ' updated the ' . esc_attr( $cf->name ) . ' value of #' . esc_attr( $recent_logs->ticket->id ) . ' to ' . esc_attr( $ms_names ); } /** * Return given value for custom field * * @param WPSC_Custom_Field $cf - custom field object. * @param mixed $val - value to convert and print. * @return string */ public static function get_field_value( $cf, $val ) { $val = is_array( $val ) ? $val : array_filter( explode( '|', $val ) ); $options = array_filter( array_map( function ( $option ) { if ( is_object( $option ) ) { return $option; } elseif ( $option ) { $option = new WPSC_Option( $option ); return $option->id ? $option : ''; } else { return ''; } }, $val ) ); $option_names = array_map( fn( $option ) => $option->name, $options ); return $option_names ? esc_attr( implode( ', ', $option_names ) ) : esc_attr__( 'None', 'supportcandy' ); } /** * Clear value of hidden fields * * @return void */ public static function js_clear_value_hidden_fields() { ?> case '': customField.find('select').first().val(''); break;