/** * Add possible custom columns to tickets list. * * @param array $columns List of default columns * @return array Updated list of columns * @since 3.0.0 */ public function add_custom_column($columns) { $new = array(); $custom = array(); $fields = $this->get_custom_fields(); /** * Prepare all custom fields that are supposed to show up * in the admin columns. */ foreach ($fields as $field) { /* If CF is a regular taxonomy we don't handle it, WordPress does */ if ('taxonomy' == $field['args']['callback'] && true === $field['args']['taxo_std']) { continue; } if (true === $field['args']['show_column']) { $id = $field['name']; $title = wpas_get_field_title($field); $custom[$id] = $title; } } /** * Parse the old columns and add the new ones. */ foreach ($columns as $col_id => $col_label) { /* Merge all custom columns right before the date column */ if ('date' == $col_id) { $new = array_merge($new, $custom); } $new[$col_id] = $col_label; } return $new; }
/** * Save all custom fields given in $data to the database. * * @since 3.2.0 * * @param int $post_id ID of the post being saved * @param array $data Array of data that might contain custom fields values. * @param bool $allow_log Whether or not to allow logging actions. If this is set to false and the custom field is * set to true, $log has higher priority. I tis used to prevent logging on ticket creation. * * @return array Array of custom field / value saved to the database */ public function save_custom_fields($post_id, $data = array(), $allow_log = true) { /* We store all the data to log in here */ $log = array(); /* Store all fields saved to DB and the value saved */ $saved = array(); $fields = $this->get_custom_fields(); /** * wpas_save_custom_fields_before hook * * @since 3.0.0 */ do_action('wpas_save_custom_fields_before', $post_id); foreach ($fields as $field_id => $field) { /** * All name attributes are prefixed with wpas_ * so we need to add it to get the real field ID. */ $field_form_id = "wpas_{$field_id}"; /* Process core fields differently. */ if (true === $field['args']['core']) { if (isset($data[$field_form_id])) { $this->save_core_field($post_id, $field, $data[$field_form_id]); } continue; } /** * Ignore fields in "no edit" mode. * * If we're on the admin and the custom field is set as * "no edit" (by restricting the capability), then the field * won't be passed in the $_POST, which as a result would have * the field deleted. * * If the no edit mode is enabled for the current field, we simply ignore it. */ if (is_admin() && !current_user_can($field['args']['capability'])) { continue; } /** * Get the custom field object. */ $custom_field = new WPAS_Custom_Field($field_id, $field); if (isset($data[$field_form_id])) { $value = $custom_field->get_sanitized_value($data[$field_form_id]); $result = $custom_field->update_value($value, $post_id); } else { /** * This is actually important as passing an empty value * for custom fields that aren't set in the form allows * for deleting values that aren't used from the database. * An unchecked checkbox for instance will not be set * in the form even though the value has to be deleted. */ $value = ''; $result = $custom_field->update_value($value, $post_id); } if (1 === $result || 2 === $result) { $saved[$field['name']] = $value; } if (true === $field['args']['log'] && true === $allow_log) { /** * If the custom field is a taxonomy we need to convert the term ID into its name. * * By checking if $result is different from 0 we make sure that the term actually exists. * If the term didn't exist the save function would have seen it and returned 0. */ if ('taxonomy' === $field['args']['field_type'] && 0 !== $result) { $term = get_term((int) $value, $field['name']); $value = $term->name; } /** * If the "options" parameter is set for this field, we assume it is because * the field type has multiple options. In order to make is more readable, * we try to replace the field value by the value label. * * This process is based on the fact that field types options always follow * the schema option_id => option_label. */ if (isset($field['args']['options']) && is_array($field['args']['options'])) { /* Make sure arrays are still readable */ if (is_array($value)) { $new_values = array(); foreach ($value as $val) { if (array_key_exists($val, $field['args']['options'])) { array_push($new_values, $field['args']['options'][$val]); } } /* Only if all original values were replaced we update the $value var. */ if (count($new_values) === count($value)) { $value = $new_values; } $value = implode(', ', $value); } else { if (array_key_exists($value, $field['args']['options'])) { $value = $field['args']['options'][$value]; } } } $tmp = array('action' => '', 'label' => wpas_get_field_title($field), 'value' => $value, 'field_id' => $field['name']); switch ((int) $result) { case 1: $tmp['action'] = 'added'; break; case 2: $tmp['action'] = 'updated'; break; case 3: $tmp['action'] = 'deleted'; break; } /* Only add this to the log if something was done to the field value */ if (!empty($tmp['action'])) { $log[] = $tmp; } } } /** * Log the changes if any. */ if (!empty($log)) { wpas_log($post_id, $log); } /** * wpas_save_custom_fields_before hook * * @since 3.0.0 */ do_action('wpas_save_custom_fields_after', $post_id); return $saved; }
/** * Get tickets list columns. * * Retrieve the columns to display on the list of tickets * in the client area. The columns include the 3 basic ones * (status, title and date), and also the custom fields that are * set to show on front-end (and that are not core CF). * * @since 3.0.0 * @return array The list of columns with their title and callback */ function wpas_get_tickets_list_columns() { $custom_fields = WPAS()->custom_fields->get_custom_fields(); $columns = array('status' => array('title' => __('Status', 'awesome-support'), 'callback' => 'wpas_cf_display_status', 'column_attributes' => array('head' => array('sort-ignore' => true))), 'title' => array('title' => __('Title', 'awesome-support'), 'callback' => 'title'), 'date' => array('title' => __('Date', 'awesome-support'), 'callback' => 'date', 'column_attributes' => array('head' => array('type' => 'numeric', 'sort-initial' => 'descending'), 'body' => array('value' => 'wpas_get_the_time_timestamp')))); foreach ($custom_fields as $field) { /* Don't display core fields */ if (true === $field['args']['core']) { continue; } /* Don't display fields that aren't specifically designed to */ if (true === $field['args']['show_column']) { $column_title = apply_filters('wpas_custom_column_title', wpas_get_field_title($field), $field); $column_callback = 'taxonomy' === $field['args']['field_type'] && true === $field['args']['taxo_std'] ? 'taxonomy' : $field['args']['column_callback']; $columns[$field['name']] = array('title' => $column_title, 'callback' => $column_callback); if (!empty($field['args']['column_attributes']) && is_array($field['args']['column_attributes'])) { $columns[$field['name']] = $field['args']['column_attributes']; } } } return apply_filters('wpas_tickets_list_columns', $columns); }
/** * Save the custom fields. * * The following method will get all options, * check if they have a submissed value, prefix and save it to the DB. * * @param (integer) $post_id Post ID * @since 3.0.0 */ public function save($post_id = '') { /* Need the parent object */ global $wpas_cf; /** * Clear! We can go ahead now... */ $options = $wpas_cf->get_custom_fields(); /** * Save the possible messages in this array */ $messages = array(); /** * Save all notifications to send in this array for a later expedition */ $notify = array(); /** * If some of the fields are to be logged in the ticket history, we save it here */ $log = array(); /* Go through all our options */ foreach ($options as $option) { $option_name = 'wpas_' . sanitize_text_field($option['name']); $option_args = $option['args']; /* Prepare current value */ if (isset($_POST[$option_name])) { $value = function_exists($option_args['sanitize']) ? $option_args['sanitize']($_POST[$option_name]) : sanitize_text_field($_POST[$option_name]); } /* Use a custom saving function if the save_callback is defined */ if (false !== $option_args['save_callback']) { if (is_null($option_args['save_callback'])) { continue; } if (function_exists($option_args['save_callback'])) { call_user_func($option_args['save_callback'], $value, $post_id); continue; } } /* Process the agent (re)attribution differently */ if ('assignee' === $option['name']) { /* Don't od anything if the agent didn't change */ if ($_POST[$option_name] == get_post_meta($post_id, '_wpas_assignee', true)) { continue; } wpas_assign_ticket($post_id, $_POST[$option_name], $option_args['log']); continue; } /* We handle different option types differently */ if ('taxonomy' != $option_args['callback']) { /* Form the meta key */ $key = "_{$option_name}"; /* Get current option */ $current = get_post_meta($post_id, $key, true); /** * First case scenario * * The option exists in DB but there is no value * for it in the POST. This is often the case * for checkboxes. * * Action: Delete option */ if ('' != $current && !isset($_POST[$option_name])) { /* Delete the post meta */ delete_post_meta($post_id, $key, $current); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'deleted', 'label' => wpas_get_field_title($option), 'value' => $current, 'field_id' => $option['name']); } } elseif ('' != $current && isset($_POST[$option_name])) { /* If an actual value is set, we udpate the post meta */ if ('' != $value && $current != $value) { update_post_meta($post_id, $key, $value, $current); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'updated', 'label' => wpas_get_field_title($option), 'value' => $value, 'field_id' => $option['name']); } } elseif ('' == $value) { delete_post_meta($post_id, $key, $current); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'deleted', 'label' => wpas_get_field_title($option), 'value' => $current, 'field_id' => $option['name']); } } } elseif ('' == $current && isset($_POST[$option_name])) { /* Let's not add an empty value */ if ('' != $value) { add_post_meta($post_id, $key, $value, true); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'added', 'label' => wpas_get_field_title($option), 'value' => $value, 'field_id' => $option['name']); } } } else { // Do nothing } } elseif ('taxonomy' == $option_args['callback']) { /* Check if this taxonomy has to be handled as a select */ if (true === $option_args['taxo_std']) { continue; } /* Clean the taxonomy name */ $taxonomy = substr($option_name, 5); /* If no value is submitted we delete the term relationship */ if (!isset($_POST[$option_name]) || empty($_POST[$option_name])) { $terms = wp_get_post_terms($post_id, $taxonomy); if (!empty($terms)) { wp_delete_object_term_relationships($post_id, $option_name); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'deleted', 'label' => wpas_get_field_title($option), 'value' => $current, 'field_id' => $option['name']); } } continue; } /* Get all the terms for this ticket / taxo (we should have only one term) */ $terms = get_the_terms($post_id, $taxonomy); /** * As the taxonomy is handled like a select, we should have only one value. At least * that's what we want. Hence, we loop through the possible multiple terms (which * shouldn't happen) and only keep the last one. */ if (is_array($terms)) { foreach ($terms as $term) { $the_term = $term->term_id; } } else { $the_term = ''; } /* Finally we save the new terms if changed */ if ($the_term !== (int) $value) { $term = get_term_by('id', (int) $value, $taxonomy); if (false === $term) { continue; } /** * Apply the get_term filters. * * @var object */ $term = get_term($term, $taxonomy); wp_set_object_terms($post_id, (int) $value, $taxonomy, false); /* Log the action */ if (true === $option_args['log']) { $log[] = array('action' => 'updated', 'label' => wpas_get_field_title($option), 'value' => $term->name, 'field_id' => $option['name']); } } } /** * Fired right after the option is updated */ do_action("wpas_cf_updated_{$option_name}"); /** * If a message is associated to this option, we add it now */ if (isset($option_args['message'])) { $messages[] = $option_args['message']; } /** * If an e-mail notification has to be sent we store it temporarily */ if (isset($option_args['notification'])) { $notify[] = $option_args['notification']; } } /** * Log the changes */ if (!empty($log)) { wpas_log($post_id, $log); } }
$attributes[__('Taxonomy', 'wpas')] = __('No', 'wpas'); } $attributes[__('Callback', 'wpas')] = '<code>' . $field['args']['callback'] . '</code>'; foreach ($attributes as $label => $value) { array_push($values, "<strong>{$label}</strong>: {$value}"); } ?> <tr <?php if (!empty($cf_tr_class)) { echo "class='{$cf_tr_class}'"; } ?> > <td class="row-title"><?php echo wpas_get_field_title($field); ?> </td> <td><?php echo implode(', ', $values); ?> </td> </tr> <?php } } ?> </tbody> </table> <table class="widefat wpas-system-status-table" id="wpas-system-status-plugins">
/** * "Fake" taxonomy select. * * @param array $field Field options * @since 3.0.0 */ public static function taxonomy($field) { global $post; $field_id = 'wpas_' . $field['name']; $label = wpas_get_field_title($field); $current = get_the_terms($post->ID, sanitize_text_field($field['name'])); $terms = get_terms(sanitize_text_field($field['name']), array('hide_empty' => 0)); $value = ''; $ordered_terms = array(); if (is_array($current)) { foreach ($current as $term) { $value = $term->slug; } } /* In case the taxonomy does not exist */ if (is_wp_error($terms)) { return; } /** * Re-order the terms hierarchically. */ wpas_sort_terms_hierarchicaly($terms, $ordered_terms); ?> <div <?php wpas_get_field_container_class($field_id); ?> id="<?php echo $field_id; ?> _container"> <label for="<?php echo $field_id; ?> "><strong><?php echo $label; ?> </strong></label> <?php if (!is_admin() || current_user_can($field['args']['capability'])) { ?> <select name="<?php echo $field_id; ?> " id="<?php echo $field_id; ?> " <?php wpas_get_field_class($field_id); ?> > <option value=""><?php _e('Please select', 'wpas'); ?> </option> <?php foreach ($ordered_terms as $term) { wpas_hierarchical_taxonomy_dropdown_options($term, $value); } ?> </select> <?php } else { ?> <p id="<?php echo $field_id; ?> "><?php echo $value; ?> </p> <?php } if (isset($field['args']['desc']) && '' != $field['args']['desc'] && WPAS_FIELDS_DESC) { ?> <p class="<?php echo is_admin() ? 'description' : 'wpas-help-block'; ?> "><?php echo wp_kses($field['args']['desc']); ?> </p><?php } ?> </div> <?php }