/** * @inheritdoc * * todo document * * @param array $arguments */ public function process_call($arguments) { $am = $this->get_am(); $am->ajax_begin(array('nonce' => $am->get_action_js_name(Types_Ajax::CALLBACK_FIELD_CONTROL_ACTION))); // Read and validate input $field_action = sanitize_text_field(wpcf_getpost('field_action')); $fields = wpcf_getpost('fields'); // array of values, will be sanitized when processed $current_domain = wpcf_getpost('domain', null, Types_Field_Utils::get_domains()); if (null == $current_domain) { $am->ajax_finish(array('message' => __('Wrong field domain.', 'wpcf')), false); } if (!is_array($fields) || empty($fields)) { $am->ajax_finish(array('message' => __('No fields have been selected.', 'wpcf')), false); } // will be sanitized when/if used by the action-specific method $action_specific_data = wpcf_getpost('action_specific', array()); // Process fields one by one $errors = array(); $results = array(); foreach ($fields as $field) { $result = $this->single_field_control_action($field_action, $field, $current_domain, $action_specific_data); if (is_array($result)) { // Array of errors $errors = array_merge($errors, $result); } else { if ($result instanceof WP_Error) { // Single error $errors[] = $result; } else { if (false == $result) { // This should not happen...! $errors[] = new WP_Error(0, __('An unexpected error happened while processing the request.', 'wpcf')); } else { // Success // Save the field definition model as a result if we got a whole definition if ($result instanceof WPCF_Field_Definition) { $result = $result->to_json(); } $results[wpcf_getarr($field, 'slug')] = $result; } } } } $data = array('results' => $results); $is_success = empty($errors); if (!$is_success) { $error_messages = array(); /** @var WP_Error $error */ foreach ($errors as $error) { $error_messages[] = $error->get_error_message(); } $data['messages'] = $error_messages; } $am->ajax_finish($data, $is_success); }
/** * @return array Array of true and WP_Error, one for each field value. */ public function validate_field_data() { $field_config = Types_Field_Utils::get_toolset_forms_field_config($this->field); $this->toggle_adding_field_names_to_error_messages(false); $values = $this->read_field_values(); $results = array(); foreach ($values as $key => $value) { $results[$key] = $this->validate_single_field_value($field_config, $value); } $this->toggle_adding_field_names_to_error_messages(true); return $results; }
/** * Query field groups from a single domain. * * @param string $domain One of the valid field domains. Legacy "meta type" values will be also accepted. * @param array $query Query arguments for Types_Field_Group_Factory::query_groups(). * * @return null|Types_Field_Group[] Array of field groups or null on error. * @since m2m */ private function query_specific_domain($domain, $query) { // Make sure we have a valid domain string. $valid_domains = Types_Field_Utils::get_domains(); if (!in_array($domain, $valid_domains)) { $domain = Types_Field_Utils::legacy_meta_type_to_domain($domain); } // Pass the group query to the proper factory class. try { $group_factory = Types_Field_Group_Factory::get_factory_by_domain($domain); $groups = $group_factory->query_groups($query); } catch (Exception $e) { // We don't care, it's a failure. return null; } return $groups; }
/** * @param string $action_name One of the allowed action names: 'manage_with_types' * @param array $field Field definition model passed from JS. * @param string $domain Field domain name. * @param mixed $action_specific_data * @return bool|mixed|null|WP_Error|WP_Error[]|WPCF_Field_Definition An error, array of errors, boolean indicating * success or a result value to be passed back to JS. * @since 2.0 */ private function single_field_control_action($action_name, $field, $domain, $action_specific_data) { $field_slug = wpcf_getarr($field, 'slug'); switch ($action_name) { case 'manage_with_types': return Types_Field_Utils::start_managing_field(wpcf_getarr($field, 'metaKey'), $domain); case 'stop_managing_with_types': return Types_Field_Utils::stop_managing_field($field_slug, $domain); case 'change_group_assignment': return Types_Field_Utils::change_assignment_to_groups($field_slug, $domain, $action_specific_data); case 'delete_field': return Types_Field_Utils::delete_field($field_slug, $domain); case 'change_field_type': return Types_Field_Utils::change_field_type($field_slug, $domain, $action_specific_data); case 'change_field_cardinality': return Types_Field_Utils::change_field_cardinality($field_slug, $domain, $action_specific_data); default: return new WP_Error(42, __('Invalid action name.', 'wpcf')); } }
public function on_term_update($term_id, $tt_id) { // Get an array of fields that we need to update. We don't care about their groups here. $term = get_term_by('term_taxonomy_id', $tt_id); if (!$term instanceof WP_Term) { return; } $factory = Types_Field_Group_Term_Factory::get_instance(); $groups = $factory->get_groups_by_taxonomy($term->taxonomy); if (empty($groups)) { return; } $field_definitions = Types_Field_Utils::get_field_definitions_from_groups($groups); $update_errors = $this->update_term_fields($term_id, $field_definitions); // Display errors if we have any. if (!empty($update_errors)) { foreach ($update_errors as $update_error) { wpcf_admin_message_store($update_error->get_error_message(), 'error'); } wpcf_admin_message_store(sprintf('<strong>%s</strong>', __('There has been a problem while saving custom fields. Please fix it and try again.', 'wpcf')), 'error'); } }
/** * This method is to be used only for bringing existing fields under Types control. * * At this point it is assumed that there doesn't exist any field definition for given meta_key. * See Types_Field_Utils::start_managing_field() for details. * * Maybe the usage could be wider, but that is not yet clear from the legacy code. The behaviour is slightly * different for meta_keys with the wpcf- prefix from the ones without it. More details in the code. * * The field will be created as a text field. * * @param string $meta_key Field meta key. * * @return string|false New field slug on success, false otherwise. * @since 2.0 */ public final function create_field_definition_for_existing_fields($meta_key) { // If the meta_key has our wpcf- prefix, we will not use it in the slug. $field_slug = preg_replace('/^wpcf\\-/', '', $meta_key); $definition_array = array('slug' => $field_slug, 'meta_key' => $meta_key, 'meta_type' => Types_Field_Utils::domain_to_legacy_meta_type($this->get_domain()), 'type' => Types_Field_Type_Definition_Factory::TEXTFIELD, 'name' => $field_slug, 'description' => '', 'data' => array(), 'id' => $field_slug); // Now comes a funny part that I don't fully understand. When the field's meta_key does contain the Types // prefix ('wpcf-'), we assume that this was most probably a Types field whose definition got lost. If not, // it's a completely "foreign" field that we'll only manage from now on. // // In the first case, the legacy code says "let's take full control" and that means setting 'controlled' to 0, // while for other fields (apparently without "full control") we set 'controlled' to 1... well, ok... // // But it also says "WATCH THIS! MUST NOT BE DROPPED IN ANY CASE", so let's not drop it. // // Name of the legacy function is: wpcf_types_cf_under_control(). // // I assume this setting is somehow related to toolset-forms. $adding_field_with_prefix = substr($meta_key, 0, strlen(WPCF_Field_Definition::FIELD_META_KEY_PREFIX)) == WPCF_Field_Definition::FIELD_META_KEY_PREFIX; $definition_array['data']['controlled'] = $adding_field_with_prefix ? 0 : 1; // Sanitize the definition array by type $textfield_type = Types_Field_Type_Definition_Factory::get_instance()->load_field_type_definition(Types_Field_Type_Definition_Factory::TEXTFIELD); if (null == $textfield_type) { return false; } $definition_array = $textfield_type->sanitize_field_definition_array($definition_array); // Save the data $this->set_field_definition($field_slug, $definition_array); // Indicate success return $field_slug; }
/** * Change cardinality of given field, if it is permitted by its type. * * @param string $field_slug Field definition slug. * @param string $domain Field domain. * @param string[] $arguments Needs to contain the 'target_cardinality' key with 'single'|'repetitive' value. * @return bool|WP_Error|WPCF_Field_Definition The updated definition on succes, error/false otherwise. * @since 2.0 */ public static function change_field_cardinality($field_slug, $domain, $arguments) { $factory = Types_Field_Utils::get_definition_factory_by_domain($domain); $definition = $factory->load_field_definition($field_slug); if (null == $definition) { return new WP_Error(42, sprintf(__('Field definition for field "%s" not found in options.', 'wpcf'), sanitize_text_field($field_slug))); } else { if (!$definition->is_managed_by_types()) { return new WP_Error(42, sprintf(__('Field "%s" will not be converted because it is not managed by Types.', 'wpcf'), sanitize_text_field($field_slug))); } } $target_cardinality = wpcf_getarr($arguments, 'target_cardinality', null, array('single', 'repetitive')); if (null == $target_cardinality) { return false; } $set_as_repetitive = 'repetitive' == $target_cardinality; $result = $definition->set_is_repetitive($set_as_repetitive); if ($result) { return $definition; } else { return false; } }
/** * Hook for types_filter_query_field_definitions. * * @param mixed $ignored * @param array $query Field definition query. See Types_Field_Definition_Factory::query() for supported arguments. * Additionally, you can specify: * - 'domain': A single field domain (see Types_Field_Utils) or 'all'. Legacy domain names are also accepted. * For 'all', the method returns a multidimensional arrays with results for individual domains: * - 'refresh': A boolean to refresh the definitions, useful when getting data after saving fields * array( 'posts' => array( ... ), 'users' => array( ... ), ... ). * * @note The 'refresh' parameter is temporal and might dissapear without prior notice when the groups and fields saving gets integrated in the fields definition factory * * @return null|array Field definition arrays, sanitized as per field type, or null if an error has occurred. * @since 2.1 */ public function query_field_definitions($ignored, $query) { $domain = wpcf_getarr($query, 'domain', 'all'); if ('all' == $domain) { // Call itself for each available domain. $results_by_domain = array(); $domains = Types_Field_Utils::get_domains(); foreach ($domains as $field_domain) { $per_domain_query = $query; $per_domain_query['domain'] = $field_domain; $results_by_domain[$field_domain] = $this->query_field_definitions(null, $per_domain_query); } return $results_by_domain; } else { // Sanitize input if (!is_string($domain) || !is_array($query)) { return null; } // Get the factory by domain, and if it fails, try to convert from legacy meta_type value. try { $definition_factory = Types_Field_Utils::get_definition_factory_by_domain($domain); } catch (InvalidArgumentException $e) { $definition_factory = null; } if (null == $definition_factory) { try { $definition_factory = Types_Field_Utils::get_definition_factory_by_domain(Types_Field_Utils::legacy_meta_type_to_domain($domain)); } catch (InvalidArgumentException $e) { return null; } } // Allways query only Types fields. $query['filter'] = 'types'; if (isset($query['refresh']) && $query['refresh']) { $definition_factory->clear_definition_storage(); } /** @var WPCF_Field_Definition[] $definitions */ $definitions = $definition_factory->query_definitions($query); $definition_arrays = array(); foreach ($definitions as $definition) { $definition_arrays[] = $definition->get_definition_array(); } return $definition_arrays; } }
/** * Build an array describing existing field groups within the domain. * * @return array * @since 2.0 */ private function build_group_data() { $factory = Types_Field_Utils::get_group_factory_by_domain($this->get_current_domain()); $groups = $factory->query_groups(); $group_data = array(); foreach ($groups as $group) { $group_data[$group->get_slug()] = array('slug' => $group->get_slug(), 'displayName' => $group->get_display_name()); } return $group_data; }
/** * Update an existing field group or create new one. * * @param array $group * @param string $post_type * @return int Group ID. */ function wpcf_admin_fields_save_group($group, $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, $which_fields = 'none') { if (!isset($group['name']) || empty($group['name'])) { return false; } $post = array('post_status' => 'publish', 'post_type' => $post_type, 'post_title' => sanitize_text_field($group['name']), 'post_name' => sanitize_text_field($group['name']), 'post_content' => empty($group['description']) ? '' : $group['description']); if (empty($post['post_title'])) { wpcf_admin_message(__('Please set name', 'wpcf'), 'error'); return false; } $update = false; $slug_pre_save = false; if (isset($group['id']) && !empty($group['id'])) { $update = true; $post_to_update = get_post($group['id']); if (empty($post_to_update) || $post_to_update->post_type != $post_type) { return false; } $post['ID'] = $post_to_update->ID; $slug_pre_save = $post_to_update->post_name; $post['post_status'] = $post_to_update->post_status; } if ($update) { $group_id = wp_update_post($post); if (!$group_id) { return false; } update_post_meta($group_id, TOOLSET_EDIT_LAST, time()); } else { $group_id = wp_insert_post($post, true); if (is_wp_error($group_id)) { return false; } } if (isset($group['admin_styles'])) { wpcf_admin_fields_save_group_admin_styles($group_id, $group['admin_styles']); } if (!empty($group['filters_association'])) { update_post_meta($group_id, '_wp_types_group_filters_association', $group['filters_association']); } else { delete_post_meta($group_id, '_wp_types_group_filters_association'); } // WPML register strings if (function_exists('icl_register_string')) { try { // Legacy function gives us only the underlying post type of the field group. $group_factory = Types_Field_Utils::get_group_factory_by_post_type($post_type); $field_group = $group_factory->load_field_group(sanitize_title($group['name'])); // Skip registering if the group does not exist. if (null != $field_group) { $group_wpml = new Types_Wpml_Field_Group($field_group); $group_wpml->register($slug_pre_save); } } catch (InvalidArgumentException $e) { // Something is seriously wrong - there's no field group factory for given post type, bail. } } // admin message wpcf_admin_fields_save_message($update, $which_fields); return $group_id; }
/** * @param string $domain Valid field domain * @param array $group Field group import data as associative array. * @param string $conflict_resolution = 'overwrite'|'create_new' Defines how to handle a situation when a * field group already exists in the database. * * @return array Import results: * 'is_success' bool * 'display_message' string * 'new_group_id' int * * @since 2.1 */ public function import_field_group($domain, $group, $conflict_resolution) { $group_slug = wpcf_getarr($group, Types_Field_Group::XML_SLUG); $group_factory = Types_Field_Utils::get_group_factory_by_domain($domain); $existing_groups = $group_factory->query_groups(array('name' => $group_slug)); $group_already_exists = count($existing_groups) > 0; $new_post = array('post_status' => $group['post_status'], 'post_type' => $group_factory->get_post_type(), 'post_title' => $group['post_title'], 'post_content' => !empty($group['post_content']) ? $group['post_content'] : ''); $update_existing = $group_already_exists && 'overwrite' == $conflict_resolution; if ($update_existing) { $existing_group = $existing_groups[0]; $new_post['ID'] = $existing_group->get_id(); $new_group_id = wp_update_post($new_post); } else { $new_group_id = wp_insert_post($new_post, true); } $is_success = !is_wp_error($new_group_id) && 0 < $new_group_id; // Update group's postmeta if ($is_success && !empty($group['meta'])) { foreach ($group['meta'] as $meta_key => $meta_value) { if (Types_Field_Group_Term::POSTMETA_ASSOCIATED_TAXONOMY == $meta_key) { $meta_values = explode(',', $meta_value); delete_post_meta($new_group_id, $meta_key); foreach ($meta_values as $single_meta_value) { update_post_meta($new_group_id, $meta_key, $single_meta_value); } } else { update_post_meta($new_group_id, $meta_key, $meta_value); } } } // Create display message if ($is_success) { if ($update_existing) { $display_message = sprintf(__('Term field group "%s" updated', 'wpcf'), $group['post_title']); } else { $display_message = sprintf(__('Term field group "%s" added', 'wpcf'), $group['post_title']); } } else { if ($update_existing) { $display_message = sprintf(__('Term field group "%s" update failed', 'wpcf'), $group['post_title']); } else { $display_message = sprintf(__('Term field group "%s" insert failed', 'wpcf'), $group['post_title']); } } return array('is_success' => $is_success, 'display_message' => $display_message, 'new_group_id' => $new_group_id); }