/** * Get registered meta boxes via a filter. * Advantages: * - prevents duplicated global variables. * - allows users to remove/hide registered meta boxes. */ public static function get_meta_boxes() { if (null === self::$meta_boxes) { self::$meta_boxes = apply_filters('rwmb_meta_boxes', array()); self::$meta_boxes = empty(self::$meta_boxes) || !is_array(self::$meta_boxes) ? array() : self::$meta_boxes; } return self::$meta_boxes; }
/** * Hash all fields into an indexed array for search */ public static function hash_fields() { $meta_boxes = RWMB_Core::get_meta_boxes(); foreach ($meta_boxes as $meta_box) { foreach ($meta_box['fields'] as $field) { if (!empty($field['id'])) { self::$fields[$field['id']] = $field; } } } }
/** * Find field by field ID. * This function finds field in meta boxes registered by 'rwmb_meta_boxes' filter. * * @param string $field_id Field ID * @return array|false Field params (array) if success. False otherwise. */ static function find_field($field_id) { $meta_boxes = RWMB_Core::get_meta_boxes(); foreach ($meta_boxes as $meta_box) { $meta_box = RW_Meta_Box::normalize($meta_box); foreach ($meta_box['fields'] as $field) { if ($field_id == $field['id']) { return $field; } } } return false; }
/** * Hash all fields into an indexed array for search * * @param string $post_type Post type */ public static function hash_fields($post_type) { self::$fields[$post_type] = array(); $meta_boxes = RWMB_Core::get_meta_boxes(); foreach ($meta_boxes as $meta_box) { $meta_box = RW_Meta_Box::normalize($meta_box); if (!in_array($post_type, $meta_box['post_types'])) { continue; } foreach ($meta_box['fields'] as $field) { if (!empty($field['id'])) { self::$fields[$post_type][$field['id']] = $field; } } } }
/** * Translating IDs stored as field values upon WPML post/page duplication. * * @param $value * @param $target_language * @param $meta_data * @return mixed */ public function wpml_translate_values($value, $target_language, $meta_data) { $fields = RWMB_Core::get_fields(); foreach ($fields as $field) { if (in_array($field['type'], array('post', 'taxonomy_advanced')) && $field['id'] === $meta_data['key']) { // Post type needed for WPML filter differs between fields $post_type = $field['type'] === 'taxonomy_advanced' ? $field['taxonomy'] : $field['post_type']; // Translating values, whether are stored as comma separated strings or not. if (strpos($value, ',') === false) { $value = apply_filters('wpml_object_id', $value, $post_type, true, $target_language); } else { // Dealing with IDs stored as comma separated strings $translated_values = array(); $values = explode(',', $value); foreach ($values as $v) { $translated_values[] = apply_filters('wpml_object_id', $v, $post_type, true, $target_language); } $value = implode(',', $translated_values); } } } return $value; }
/** * Save data from meta box * * @param int $post_id Post ID */ function save_post($post_id) { // Check if this function is called to prevent duplicated calls like revisions, manual hook to wp_insert_post, etc. if (true === $this->saved) { return; } $this->saved = true; // Check whether form is submitted properly $nonce = (string) filter_input(INPUT_POST, "nonce_{$this->meta_box['id']}"); if (!wp_verify_nonce($nonce, "rwmb-save-{$this->meta_box['id']}")) { return; } // Autosave if (defined('DOING_AUTOSAVE') && !$this->meta_box['autosave']) { return; } // Make sure meta is added to the post, not a revision if ($the_post = wp_is_post_revision($post_id)) { $post_id = $the_post; } // Before save action do_action('rwmb_before_save_post', $post_id); do_action("rwmb_{$this->meta_box['id']}_before_save_post", $post_id); foreach ($this->fields as $field) { $name = $field['id']; $single = $field['clone'] || !$field['multiple']; $old = get_post_meta($post_id, $name, $single); $new = isset($_POST[$name]) ? $_POST[$name] : ($single ? '' : array()); // Allow field class change the value $new = call_user_func(array(self::get_class_name($field), 'value'), $new, $old, $post_id, $field); $new = RWMB_Core::filter('value', $new, $field, $old); // Call defined method to save meta value, if there's no methods, call common one call_user_func(array(self::get_class_name($field), 'save'), $new, $old, $post_id, $field); } // After save action do_action('rwmb_after_save_post', $post_id); do_action("rwmb_{$this->meta_box['id']}_after_save_post", $post_id); }
/** * Show field HTML * Filters are put inside this method, not inside methods such as "meta", "html", "begin_html", etc. * That ensures the returned value are always been applied filters * This method is not meant to be overwritten in specific fields * * @param array $field * @param bool $saved * * @return string */ static function show($field, $saved) { $post = get_post(); $post_id = isset($post->ID) ? $post->ID : 0; $field_class = RW_Meta_Box::get_class_name($field); $meta = call_user_func(array($field_class, 'meta'), $post_id, $saved, $field); $meta = RWMB_Core::filter('field_meta', $meta, $field, $saved); $begin = call_user_func(array($field_class, 'begin_html'), $meta, $field); $begin = RWMB_Core::filter('begin_html', $begin, $field, $meta); // Separate code for cloneable and non-cloneable fields to make easy to maintain // Cloneable fields if ($field['clone']) { $field_html = ''; /** * Note: $meta must contain value so that the foreach loop runs! * @see meta() */ foreach ($meta as $index => $sub_meta) { $sub_field = $field; $sub_field['field_name'] = $field['field_name'] . "[{$index}]"; if ($index > 0) { if (isset($sub_field['address_field'])) { $sub_field['address_field'] = $field['address_field'] . "_{$index}"; } $sub_field['id'] = $field['id'] . "_{$index}"; } if ($field['multiple']) { $sub_field['field_name'] .= '[]'; } // Wrap field HTML in a div with class="rwmb-clone" if needed $class = "rwmb-clone rwmb-{$field['type']}-clone"; $sort_icon = ''; if ($field['sort_clone']) { $class .= ' rwmb-sort-clone'; $sort_icon = "<a href='javascript:;' class='rwmb-clone-icon'></a>"; } $input_html = "<div class='{$class}'>" . $sort_icon; // Call separated methods for displaying each type of field $input_html .= call_user_func(array($field_class, 'html'), $sub_meta, $sub_field); $input_html = RWMB_Core::filter('html', $input_html, $sub_field, $sub_meta); // Remove clone button $input_html .= call_user_func(array($field_class, 'remove_clone_button'), $sub_field); $input_html .= '</div>'; $field_html .= $input_html; } } else { // Call separated methods for displaying each type of field $field_html = call_user_func(array($field_class, 'html'), $meta, $field); $field_html = RWMB_Core::filter('html', $field_html, $field, $meta); } $end = call_user_func(array($field_class, 'end_html'), $meta, $field); $end = RWMB_Core::filter('end_html', $end, $field, $meta); $html = RWMB_Core::filter('wrapper_html', "{$begin}{$field_html}{$end}", $field, $meta); // Display label and input in DIV and allow user-defined classes to be appended $classes = "rwmb-field rwmb-{$field['type']}-wrapper " . $field['class']; if ('hidden' === $field['type']) { $classes .= ' hidden'; } if (!empty($field['required'])) { $classes .= ' required'; } $outer_html = sprintf($field['before'] . '<div class="%s">%s</div>' . $field['after'], trim($classes), $html); $outer_html = RWMB_Core::filter('outer_html', $outer_html, $field, $meta); echo $outer_html; }