File manager - Edit - /home/contenidosenred/public_html/OD/wp-admin/includes/219846/inc.tar
Back
meta-box-registry.php 0000644 00000003341 15105434331 0010637 0 ustar 00 <?php /** * A registry for storing all meta boxes. * * @link https://designpatternsphp.readthedocs.io/en/latest/Structural/Registry/README.html * @package Meta Box */ /** * Meta box registry class. */ class RWMB_Meta_Box_Registry { /** * Internal data storage. * * @var array */ private $data = array(); /** * Create a meta box object. * * @param array $settings Meta box settings. * @return \RW_Meta_Box */ public function make( $settings ) { $class_name = apply_filters( 'rwmb_meta_box_class_name', 'RW_Meta_Box', $settings ); $meta_box = new $class_name( $settings ); $this->add( $meta_box ); return $meta_box; } /** * Add a meta box to the registry. * * @param RW_Meta_Box $meta_box Meta box instance. */ public function add( RW_Meta_Box $meta_box ) { $this->data[ $meta_box->id ] = $meta_box; } /** * Retrieve a meta box by id. * * @param string $id Meta box id. * * @return RW_Meta_Box|bool False or meta box object. */ public function get( $id ) { return isset( $this->data[ $id ] ) ? $this->data[ $id ] : false; } /** * Get meta boxes under some conditions. * * @param array $args Custom argument to get meta boxes by. * * @return array */ public function get_by( $args ) { $meta_boxes = $this->data; foreach ( $meta_boxes as $index => $meta_box ) { foreach ( $args as $key => $value ) { $meta_box_key = 'object_type' === $key ? $meta_box->get_object_type() : $meta_box->$key; if ( $meta_box_key !== $value ) { unset( $meta_boxes[ $index ] ); continue 2; // Skip the meta box loop. } } } return $meta_boxes; } /** * Retrieve all meta boxes. * * @return array */ public function all() { return $this->data; } } fields/image-advanced.php 0000644 00000004745 15105434331 0011361 0 ustar 00 <?php /** * The advanced image upload field which uses WordPress media popup to upload and select images. * * @package Meta Box */ /** * Image advanced field class. */ class RWMB_Image_Advanced_Field extends RWMB_Media_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); RWMB_Image_Field::admin_enqueue_scripts(); wp_enqueue_script( 'rwmb-image-advanced', RWMB_JS_URL . 'image-advanced.js', array( 'rwmb-media' ), RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field['mime_type'] = 'image'; $field = wp_parse_args( $field, array( 'image_size' => 'thumbnail', ) ); $field = parent::normalize( $field ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'imageSize' => $field['image_size'], ) ); return $field; } /** * Get the field value. * * @param array $field Field parameters. * @param array $args Additional arguments. * @param null $post_id Post ID. * @return mixed */ public static function get_value( $field, $args = array(), $post_id = null ) { return RWMB_Image_Field::get_value( $field, $args, $post_id ); } /** * Get uploaded file information. * * @param int $file Attachment image ID (post ID). Required. * @param array $args Array of arguments (for size). * @param array $field Field settings. * * @return array|bool False if file not found. Array of image info on success. */ public static function file_info( $file, $args = array(), $field = array() ) { return RWMB_Image_Field::file_info( $file, $args, $field ); } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return RWMB_Image_Field::format_single_value( $field, $value, $args, $post_id ); } /** * Template for media item. */ public static function print_templates() { parent::print_templates(); require_once RWMB_INC_DIR . 'templates/image-advanced.php'; } } fields/taxonomy.php 0000644 00000023577 15105434331 0010416 0 ustar 00 <?php /** * The taxonomy field which aims to replace the built-in WordPress taxonomy UI with more options. * * @package Meta Box */ /** * Taxonomy field class which set post terms when saving. */ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field { /** * Add ajax actions callback. */ public static function add_actions() { add_action( 'wp_ajax_rwmb_get_terms', array( __CLASS__, 'ajax_get_terms' ) ); add_action( 'wp_ajax_nopriv_rwmb_get_terms', array( __CLASS__, 'ajax_get_terms' ) ); } /** * Query terms via ajax. */ public static function ajax_get_terms() { check_ajax_referer( 'query' ); $request = rwmb_request(); $field = $request->filter_post( 'field', FILTER_DEFAULT, FILTER_FORCE_ARRAY ); // Required for 'choice_label' filter. See self::filter(). $field['clone'] = false; $field['_original_id'] = $field['id']; // Search. $field['query_args']['name__like'] = $request->filter_post( 'term', FILTER_SANITIZE_STRING ); // Pagination. $limit = isset( $field['query_args']['number'] ) ? (int) $field['query_args']['number'] : 0; if ( 'query:append' === $request->filter_post( '_type', FILTER_SANITIZE_STRING ) ) { $page = $request->filter_post( 'page', FILTER_SANITIZE_NUMBER_INT ); $field['query_args']['offset'] = $limit * ( $page - 1 ); } // Query the database. $items = self::query( null, $field ); $items = array_values( $items ); $data = array( 'items' => $items ); // More items for pagination. if ( $limit && count( $items ) === $limit ) { $data['more'] = true; } wp_send_json_success( $data ); } /** * Add default value for 'taxonomy' field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { // Backwards compatibility with field args. if ( isset( $field['options']['args'] ) ) { $field['query_args'] = $field['options']['args']; } if ( isset( $field['options']['taxonomy'] ) ) { $field['taxonomy'] = $field['options']['taxonomy']; } if ( isset( $field['options']['type'] ) ) { $field['field_type'] = $field['options']['type']; } // Set default field args. $field = wp_parse_args( $field, array( 'taxonomy' => 'category', 'query_args' => array(), 'remove_default' => false, ) ); // Force taxonomy to be an array. $field['taxonomy'] = (array) $field['taxonomy']; /* * Set default placeholder: * - If multiple taxonomies: show 'Select a term'. * - If single taxonomy: show 'Select a %taxonomy_name%'. */ $placeholder = __( 'Select a term', 'meta-box' ); $taxonomy_name = self::get_taxonomy_singular_name( $field ); if ( $taxonomy_name ) { // Translators: %s is the taxonomy singular label. $placeholder = sprintf( __( 'Select a %s', 'meta-box' ), strtolower( $taxonomy_name ) ); } $field = wp_parse_args( $field, array( 'placeholder' => $placeholder, ) ); $field = parent::normalize( $field ); // Set default query args. $limit = $field['ajax'] ? 10 : 0; $field['query_args'] = wp_parse_args( $field['query_args'], array( 'taxonomy' => $field['taxonomy'], 'number' => $limit, ) ); parent::set_ajax_params( $field ); // Prevent cloning for taxonomy field, not for child fields (taxonomy_advanced). if ( 'taxonomy' === $field['type'] ) { $field['clone'] = false; } return $field; } /** * Query terms for field options. * * @param array $meta Saved meta value. * @param array $field Field settings. * @return array Field options array. */ public static function query( $meta, $field ) { $args = wp_parse_args( $field['query_args'], array( 'hide_empty' => false, 'count' => false, 'update_term_meta_cache' => false, ) ); // Query only selected items. if ( ! empty( $field['ajax'] ) && ! empty( $meta ) ) { $args['include'] = $meta; } $terms = get_terms( $args ); if ( ! is_array( $terms ) ) { return array(); } $options = array(); foreach ( $terms as $term ) { $label = $term->name ? $term->name : __( '(No title)', 'meta-box' ); $label = self::filter( 'choice_label', $label, $field, $term ); $options[ $term->term_id ] = array( 'value' => $term->term_id, 'label' => $label, 'parent' => $term->parent, ); } return $options; } /** * Get meta values to save. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return array */ public static function value( $new, $old, $post_id, $field ) { $new = (array) $new; $new[] = self::add_term( $field ); $new = array_unique( array_map( 'intval', array_filter( $new ) ) ); return $new; } /** * Save meta value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. */ public static function save( $new, $old, $post_id, $field ) { if ( empty( $field['id'] ) || ! $field['save_field'] ) { return; } foreach ( $field['taxonomy'] as $taxonomy ) { wp_set_object_terms( $post_id, $new, $taxonomy ); } } /** * Add new terms if users created some. * * @param array $field Field settings. * @return int|null Term ID if added successfully, null otherwise. */ protected static function add_term( $field ) { $term = rwmb_request()->post( $field['id'] . '_new' ); if ( ! $field['add_new'] || ! $term || 1 !== count( $field['taxonomy'] ) ) { return null; } $taxonomy = reset( $field['taxonomy'] ); $term = wp_insert_term( $term, $taxonomy ); return isset( $term['term_id'] ) ? $term['term_id'] : null; } /** * Get raw meta value. * * @param int $object_id Object ID. * @param array $field Field parameters. * @param array $args Arguments of {@see rwmb_meta()} helper. * * @return mixed */ public static function raw_meta( $object_id, $field, $args = array() ) { if ( empty( $field['id'] ) ) { return ''; } $meta = wp_get_object_terms( $object_id, $field['taxonomy'], array( 'orderby' => 'term_order', ) ); if ( is_wp_error( $meta ) ) { return ''; } $meta = wp_list_pluck( $meta, 'term_id' ); return $field['multiple'] ? $meta : reset( $meta ); } /** * Get the field value. * Return list of post term objects. * * @param array $field Field parameters. * @param array $args Additional arguments. * @param int|null $post_id Post ID. null for current post. Optional. * * @return array List of post term objects. */ public static function get_value( $field, $args = array(), $post_id = null ) { if ( ! $post_id ) { $post_id = get_the_ID(); } $value = wp_get_object_terms( $post_id, $field['taxonomy'], array( 'orderby' => 'term_order', ) ); // Get single value if necessary. if ( ! $field['clone'] && ! $field['multiple'] && is_array( $value ) ) { $value = reset( $value ); } return $value; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return sprintf( '<a href="%s" title="%s">%s</a>', // @codingStandardsIgnoreLine esc_url( get_term_link( $value ) ), esc_attr( $value->name ), esc_html( $value->name ) ); } /** * Render "Add New" form * * @param array $field Field settings. * @return string */ public static function add_new_form( $field ) { // Only add new term if field has only one taxonomy. if ( 1 !== count( $field['taxonomy'] ) ) { return ''; } $taxonomy = reset( $field['taxonomy'] ); $taxonomy_object = get_taxonomy( $taxonomy ); if ( false === $taxonomy_object ) { return ''; } $html = ' <div class="rwmb-taxonomy-add"> <button class="rwmb-taxonomy-add-button">%s</button> <div class="rwmb-taxonomy-add-form rwmb-hidden"> <input type="text" name="%s_new" size="30" placeholder="%s"> </div> </div>'; $html = sprintf( $html, esc_html( $taxonomy_object->labels->add_new_item ), esc_attr( $field['id'] ), esc_attr( $taxonomy_object->labels->new_item_name ) ); return $html; } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_style( 'rwmb-taxonomy', RWMB_CSS_URL . 'taxonomy.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-taxonomy', RWMB_JS_URL . 'taxonomy.js', array( 'jquery' ), RWMB_VER, true ); // Field is the 1st param. $args = func_get_args(); $field = $args[0]; self::remove_default_meta_box( $field ); } /** * Remove default WordPress taxonomy meta box. * * @param array $field Field settings. */ protected static function remove_default_meta_box( $field ) { if ( empty( $field['remove_default'] ) || ! is_admin() || ! function_exists( 'remove_meta_box' ) ) { return; } foreach ( $field['taxonomy'] as $taxonomy ) { $id = is_taxonomy_hierarchical( $taxonomy ) ? "{$taxonomy}div" : "tagsdiv-{$taxonomy}"; remove_meta_box( $id, null, 'side' ); } } /** * Get taxonomy singular name. * * @param array $field Field settings. * @return string */ protected static function get_taxonomy_singular_name( $field ) { if ( 1 !== count( $field['taxonomy'] ) ) { return ''; } $taxonomy = reset( $field['taxonomy'] ); $taxonomy_object = get_taxonomy( $taxonomy ); return false === $taxonomy_object ? '' : $taxonomy_object->labels->singular_name; } } fields/file-upload.php 0000644 00000002215 15105434331 0010723 0 ustar 00 <?php /** * The file upload field which allows users to drag and drop files to upload. * * @package Meta Box */ /** * The file upload field class. */ class RWMB_File_Upload_Field extends RWMB_Media_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_style( 'rwmb-upload', RWMB_CSS_URL . 'upload.css', array( 'rwmb-media' ), RWMB_VER ); wp_enqueue_script( 'rwmb-file-upload', RWMB_JS_URL . 'file-upload.js', array( 'rwmb-media' ), RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'max_file_size' => 0, ) ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'maxFileSize' => $field['max_file_size'], ) ); return $field; } /** * Template for media item. */ public static function print_templates() { parent::print_templates(); require_once RWMB_INC_DIR . 'templates/upload.php'; } } fields/object-choice.php 0000644 00000010116 15105434331 0011217 0 ustar 00 <?php /** * The object choice class which allows users to select specific objects in WordPress. * * @package Meta Box */ /** * Abstract field to select an object: post, user, taxonomy, etc. */ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field { /** * Show field HTML. * Populate field options before showing to make sure query is made only once. * * @param array $field Field parameters. * @param bool $saved Whether the meta box is saved at least once. * @param int $post_id Post ID. */ public static function show( $field, $saved, $post_id = 0 ) { // Get unique saved IDs for ajax fields. $meta = self::call( $field, 'meta', $post_id, $saved ); $meta = self::filter( 'field_meta', $meta, $field, $saved ); $meta = RWMB_Helpers_Array::flatten( (array) $meta ); $meta = array_unique( array_filter( array_map( 'absint', $meta ) ) ); sort( $meta ); $field['options'] = self::call( $field, 'query', $meta ); parent::show( $field, $saved, $post_id ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $html = call_user_func( array( self::get_type_class( $field ), 'html' ), $meta, $field ); if ( $field['add_new'] ) { $html .= self::call( 'add_new_form', $field ); } return $html; } /** * Render "Add New" form * * @param array $field Field settings. * @return string */ public static function add_new_form( $field ) { return ''; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'flatten' => true, 'query_args' => array(), 'field_type' => 'select_advanced', 'add_new' => false, 'ajax' => true, ) ); if ( 'select_advanced' !== $field['field_type'] ) { $field['ajax'] = false; } if ( 'checkbox_tree' === $field['field_type'] ) { $field['field_type'] = 'checkbox_list'; $field['flatten'] = false; } if ( 'radio_list' === $field['field_type'] ) { $field['field_type'] = 'radio'; } $field = call_user_func( array( self::get_type_class( $field ), 'normalize' ), $field ); return $field; } /** * Set ajax parameters. * * @param array $field Field settings. */ protected static function set_ajax_params( &$field ) { if ( ! $field['ajax'] ) { return; } if ( empty( $field['js_options']['ajax'] ) ) { $field['js_options']['ajax'] = array(); } $field['js_options']['ajax'] = wp_parse_args( array( 'url' => admin_url( 'admin-ajax.php' ), ), $field['js_options']['ajax'] ); $field['js_options']['ajax_data'] = array( 'field' => array( 'id' => $field['id'], 'type' => $field['type'], 'query_args' => $field['query_args'], ), '_wpnonce' => wp_create_nonce( 'query' ), ); } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = call_user_func( array( self::get_type_class( $field ), 'get_attributes' ), $field, $value ); if ( 'select_advanced' === $field['field_type'] ) { $attributes['class'] .= ' rwmb-select_advanced'; } elseif ( 'select' === $field['field_type'] ) { $attributes['class'] .= ' rwmb-select'; } return $attributes; } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { RWMB_Input_List_Field::admin_enqueue_scripts(); RWMB_Select_Field::admin_enqueue_scripts(); RWMB_Select_Tree_Field::admin_enqueue_scripts(); RWMB_Select_Advanced_Field::admin_enqueue_scripts(); } /** * Get correct rendering class for the field. * * @param array $field Field parameters. * @return string */ protected static function get_type_class( $field ) { return RWMB_Helpers_Field::get_class( array( 'type' => $field['field_type'], ) ); } } fields/textarea.php 0000644 00000003137 15105434331 0010343 0 ustar 00 <?php /** * The textarea field. * * @package Meta Box */ /** * Textarea field class. */ class RWMB_Textarea_Field extends RWMB_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $attributes = self::get_attributes( $field, $meta ); return sprintf( '<textarea %s>%s</textarea>', self::render_attributes( $attributes ), esc_textarea( $meta ) ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'autocomplete' => false, 'cols' => false, 'rows' => 3, 'maxlength' => false, 'wrap' => false, 'readonly' => false, ) ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'autocomplete' => $field['autocomplete'], 'cols' => $field['cols'], 'rows' => $field['rows'], 'maxlength' => $field['maxlength'], 'wrap' => $field['wrap'], 'readonly' => $field['readonly'], 'placeholder' => $field['placeholder'], ) ); return $attributes; } } fields/oembed.php 0000644 00000010023 15105434331 0007751 0 ustar 00 <?php /** * The oEmbed field which allows users to enter oEmbed URLs. * * @package Meta Box */ /** * OEmbed field class. */ class RWMB_OEmbed_Field extends RWMB_Input_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'not_available_string' => __( 'Embed HTML not available.', 'meta-box' ), ) ); $field['attributes'] = wp_parse_args( $field['attributes'], array( 'data-not-available' => $field['not_available_string'], ) ); return $field; } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-oembed', RWMB_CSS_URL . 'oembed.css', '', RWMB_VER ); wp_enqueue_script( 'rwmb-oembed', RWMB_JS_URL . 'oembed.js', array( 'jquery', 'underscore' ), RWMB_VER, true ); } /** * Add actions. */ public static function add_actions() { add_action( 'wp_ajax_rwmb_get_embed', array( __CLASS__, 'wp_ajax_get_embed' ) ); } /** * Ajax callback for returning oEmbed HTML. */ public static function wp_ajax_get_embed() { $request = rwmb_request(); $url = (string) $request->filter_post( 'url', FILTER_SANITIZE_URL ); $not_available = (string) $request->post( 'not_available' ); wp_send_json_success( self::get_embed( $url, $not_available ) ); } /** * Get embed html from url. * * @param string $url URL. * @param string $not_available Not available string displayed to users. * @return string */ public static function get_embed( $url, $not_available = '' ) { /** * Set arguments for getting embeded HTML. * Without arguments, default width will be taken from global $content_width, which can break UI in the admin. * * @link https://github.com/rilwis/meta-box/issues/801 * @see WP_oEmbed::fetch() * @see WP_Embed::shortcode() * @see wp_embed_defaults() */ $args = array(); if ( is_admin() ) { $args['width'] = 360; } // Try oembed first. $embed = wp_oembed_get( $url, $args ); // If no oembed provides found, try WordPress auto embed. if ( ! $embed ) { global $wp_embed; $temp = $wp_embed->return_false_on_fail; $wp_embed->return_false_on_fail = true; // Do not fallback to make a link. $embed = $wp_embed->shortcode( $args, $url ); $wp_embed->return_false_on_fail = $temp; } if ( $not_available ) { $not_available = '<div class="rwmb-oembed-not-available">' . wp_kses_post( $not_available ) . '</div>'; } $not_available = apply_filters( 'rwmb_oembed_not_available_string', $not_available ); return $embed ? $embed : $not_available; } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { return parent::html( $meta, $field ) . sprintf( '<span class="spinner"></span> <div class="rwmb-embed-media">%s</div>', $meta ? self::get_embed( $meta, $field['not_available_string'] ) : '' ); } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes['type'] = 'url'; return $attributes; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return self::get_embed( $value, $field['not_available_string'] ); } } fields/number.php 0000644 00000001713 15105434331 0010014 0 ustar 00 <?php /** * The number field which uses HTML <input type="number">. * * @package Meta Box */ /** * Number field class. */ class RWMB_Number_Field extends RWMB_Input_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'step' => 1, 'min' => 0, 'max' => false, ) ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'step' => $field['step'], 'max' => $field['max'], 'min' => $field['min'], ) ); return $attributes; } } fields/checkbox-list.php 0000644 00000000765 15105434331 0011271 0 ustar 00 <?php /** * The checkbox list field which shows a list of choices and allow users to select multiple options. * * @package Meta Box */ /** * Checkbox list field class. */ class RWMB_Checkbox_List_Field extends RWMB_Input_List_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field['multiple'] = true; $field = parent::normalize( $field ); return $field; } } fields/key-value.php 0000644 00000006550 15105434331 0010432 0 ustar 00 <?php /** * The key-value field which allows users to add pairs of keys and values. * * @package Meta Box */ /** * Key-value field class. */ class RWMB_Key_Value_Field extends RWMB_Input_Field { public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-key-value', RWMB_CSS_URL . 'key-value.css', array(), RWMB_VER ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { // Key. $key = isset( $meta[0] ) ? $meta[0] : ''; $attributes = self::get_attributes( $field, $key ); $attributes['placeholder'] = $field['placeholder']['key']; $html = sprintf( '<input %s>', self::render_attributes( $attributes ) ); // Value. $val = isset( $meta[1] ) ? $meta[1] : ''; $attributes = self::get_attributes( $field, $val ); $attributes['placeholder'] = $field['placeholder']['value']; $html .= sprintf( '<input %s>', self::render_attributes( $attributes ) ); return $html; } /** * Show begin HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function begin_html( $meta, $field ) { $desc = $field['desc'] ? "<p id='{$field['id']}_description' class='description'>{$field['desc']}</p>" : ''; if ( empty( $field['name'] ) ) { return '<div class="rwmb-input">' . $desc; } return sprintf( '<div class="rwmb-label"> <label for="%s">%s</label> </div> <div class="rwmb-input"> %s', $field['id'], $field['name'], $desc ); } /** * Do not show field description. * * @param array $field Field parameters. * * @return string */ public static function input_description( $field ) { return ''; } /** * Sanitize field value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return array */ public static function value( $new, $old, $post_id, $field ) { foreach ( $new as &$arr ) { if ( empty( $arr[0] ) && empty( $arr[1] ) ) { $arr = false; } } $new = array_filter( $new ); return $new; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field['clone'] = true; $field['multiple'] = true; $field = parent::normalize( $field ); $field['attributes']['type'] = 'text'; $field['placeholder'] = wp_parse_args( (array) $field['placeholder'], array( 'key' => __( 'Key', 'meta-box' ), 'value' => __( 'Value', 'meta-box' ), ) ); return $field; } /** * Format value for the helper functions. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_clone_value( $field, $value, $args, $post_id ) { return sprintf( '<label>%s:</label> %s', $value[0], $value[1] ); } } fields/custom-html.php 0000644 00000001176 15105434331 0011003 0 ustar 00 <?php /** * The custom HTML field which allows users to output any kind of content to the meta box. * * @package Meta Box */ /** * Custom HTML field class. */ class RWMB_Custom_Html_Field extends RWMB_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $html = ! empty( $field['std'] ) ? $field['std'] : ''; if ( ! empty( $field['callback'] ) && is_callable( $field['callback'] ) ) { $html = call_user_func_array( $field['callback'], array( $meta, $field ) ); } return $html; } } fields/button-group.php 0000644 00000003655 15105434331 0011200 0 ustar 00 <?php /** * The Button group. * * @package Meta Box */ /** * Button group class. */ class RWMB_Button_Group_Field extends RWMB_Choice_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-button-group', RWMB_CSS_URL . 'button-group.css', '', RWMB_VER ); wp_enqueue_script( 'rwmb-button-group', RWMB_JS_URL . 'button-group.js', array(), RWMB_VER, true ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $options = self::transform_options( $field['options'] ); $walker = new RWMB_Walker_Input_List( $field, $meta ); $output = sprintf( '<ul class="rwmb-button-input-list %s">', $field['inline'] ? ' rwmb-inline' : '' ); $output .= $walker->walk( $options, -1 ); $output .= '</ul>'; return $output; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'inline' => null, ) ); $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field; $field = RWMB_Input_Field::normalize( $field ); $field['flatten'] = true; $field['inline'] = ! $field['multiple'] && ! isset( $field['inline'] ) ? true : $field['inline']; return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = RWMB_Input_Field::get_attributes( $field, $value ); $attributes['id'] = false; $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio'; $attributes['value'] = $value; return $attributes; } } fields/file.php 0000644 00000041215 15105434331 0007444 0 ustar 00 <?php /** * The file upload file which allows users to upload files via the default HTML <input type="file">. * * @package Meta Box */ /** * File field class which uses HTML <input type="file"> to upload file. */ class RWMB_File_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-file', RWMB_CSS_URL . 'file.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-file', RWMB_JS_URL . 'file.js', array( 'jquery-ui-sortable' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-file', 'rwmbFile', array( // Translators: %d is the number of files in singular form. 'maxFileUploadsSingle' => __( 'You may only upload maximum %d file', 'meta-box' ), // Translators: %d is the number of files in plural form. 'maxFileUploadsPlural' => __( 'You may only upload maximum %d files', 'meta-box' ), ) ); } /** * Add custom actions. */ public static function add_actions() { add_action( 'post_edit_form_tag', array( __CLASS__, 'post_edit_form_tag' ) ); add_action( 'wp_ajax_rwmb_delete_file', array( __CLASS__, 'ajax_delete_file' ) ); } /** * Add data encoding type for file uploading */ public static function post_edit_form_tag() { echo ' enctype="multipart/form-data"'; } /** * Ajax callback for deleting files. */ public static function ajax_delete_file() { $request = rwmb_request(); $field_id = $request->filter_post( 'field_id', FILTER_SANITIZE_STRING ); $type = false !== strpos( $request->filter_post( 'field_name', FILTER_SANITIZE_STRING ), '[' ) ? 'child' : 'top'; check_ajax_referer( "rwmb-delete-file_{$field_id}" ); if ( 'child' === $type ) { $field_group = explode( '[', $request->filter_post( 'field_name', FILTER_SANITIZE_STRING ) ); $field_id = $field_group[0]; //this is top parent field_id } // Make sure the file to delete is in the custom field. $attachment = $request->post( 'attachment_id' ); $object_id = $request->filter_post( 'object_id', FILTER_SANITIZE_STRING ); $object_type = $request->filter_post( 'object_type', FILTER_SANITIZE_STRING ); $field = rwmb_get_field_settings( $field_id, array( 'object_type' => $object_type ), $object_id ); $field_value = self::raw_meta( $object_id, $field ); $field_value = $field['clone'] ? call_user_func_array( 'array_merge', $field_value ) : $field_value; if ( ( 'child' !== $type && ! in_array( $attachment, $field_value ) ) || ( 'child' === $type && ! in_array( $attachment, self::get_sub_values( $field_value, $request->filter_post( 'field_id', FILTER_SANITIZE_STRING ) ) ) ) ) { wp_send_json_error( __( 'Error: Invalid file', 'meta-box' ) ); } // Delete the file. if ( is_numeric( $attachment ) ) { $result = wp_delete_attachment( $attachment ); } else { $path = str_replace( home_url( '/' ), trailingslashit( ABSPATH ), $attachment ); $result = unlink( $path ); } if ( $result ) { wp_send_json_success(); } wp_send_json_error( __( 'Error: Cannot delete file', 'meta-box' ) ); } /** * Recursively get values for sub-fields and sub-groups. * * @param array $field_value List of parent fields value. * @param int $key_search Nub field name. * @return array */ protected static function get_sub_values( $field_value, $key_search ) { if ( array_key_exists( $key_search, $field_value ) ) { return $field_value[ $key_search ]; } foreach ( $field_value as $key => $element ) { if( !is_array( $element ) ) { continue; } if ( self::get_sub_values( $element, $key_search ) ) { return $element[ $key_search ]; } } return false; } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $meta = array_filter( (array) $meta ); $i18n_more = apply_filters( 'rwmb_file_add_string', _x( '+ Add new file', 'file upload', 'meta-box' ), $field ); $html = self::get_uploaded_files( $meta, $field ); // Show form upload. $attributes = self::get_attributes( $field, $meta ); $attributes['type'] = 'file'; $attributes['name'] = "{$field['input_name']}[]"; $attributes['class'] = 'rwmb-file-input'; /* * Use JavaScript to toggle 'required' attribute, because: * - Field might already have value (uploaded files). * - Be able to detect when uploading multiple files. */ if ( $attributes['required'] ) { $attributes['data-required'] = 1; $attributes['required'] = false; } // Upload new files. $html .= sprintf( '<div class="rwmb-file-new"><input %s>', self::render_attributes( $attributes ) ); if ( 1 !== $field['max_file_uploads'] ) { $html .= sprintf( '<a class="rwmb-file-add" href="#"><strong>%s</strong></a>', $i18n_more ); } $html .= '</div>'; $html .= sprintf( '<input type="hidden" class="rwmb-file-index" name="%s" value="%s">', $field['index_name'], $field['input_name'] ); return $html; } /** * Get HTML for uploaded files. * * @param array $files List of uploaded files. * @param array $field Field parameters. * @return string */ protected static function get_uploaded_files( $files, $field ) { $delete_nonce = wp_create_nonce( "rwmb-delete-file_{$field['id']}" ); $output = ''; foreach ( (array) $files as $k => $file ) { // Ignore deleted files (if users accidentally deleted files or uses `force_delete` without saving post). if ( get_attached_file( $file ) || $field['upload_dir'] ) { $output .= self::call( $field, 'file_html', $file, $k ); } } return sprintf( '<ul class="rwmb-files" data-field_id="%s" data-field_name="%s" data-delete_nonce="%s" data-force_delete="%s" data-max_file_uploads="%s" data-mime_type="%s">%s</ul>', $field['id'], $field['field_name'], $delete_nonce, $field['force_delete'] ? 1 : 0, $field['max_file_uploads'], $field['mime_type'], $output ); } /** * Get HTML for uploaded file. * * @param int $file Attachment (file) ID. * @param int $index File index. * @param array $field Field data. * @return string */ protected static function file_html( $file, $index, $field ) { $i18n_delete = apply_filters( 'rwmb_file_delete_string', _x( 'Delete', 'file upload', 'meta-box' ) ); $i18n_edit = apply_filters( 'rwmb_file_edit_string', _x( 'Edit', 'file upload', 'meta-box' ) ); $attributes = self::get_attributes( $field, $file ); if ( ! $file ) { return ''; } if ( $field['upload_dir'] ) { $data = self::file_info_custom_dir( $file, $field ); } else { $data = [ 'icon' => wp_get_attachment_image( $file, [48, 64], true ), 'name' => basename( get_attached_file( $file ) ), 'url' => wp_get_attachment_url( $file ), 'title' => get_the_title( $file ), 'edit_link' => '', ]; $edit_link = get_edit_post_link( $file ); if ( $edit_link ) { $data['edit_link'] = sprintf( '<a href="%s" class="rwmb-file-edit" target="_blank">%s</a>', $edit_link, $i18n_edit ); } } return sprintf( '<li class="rwmb-file"> <div class="rwmb-file-icon">%s</div> <div class="rwmb-file-info"> <a href="%s" target="_blank" class="rwmb-file-title">%s</a> <div class="rwmb-file-name">%s</div> <div class="rwmb-file-actions"> %s <a href="#" class="rwmb-file-delete" data-attachment_id="%s">%s</a> </div> </div> <input type="hidden" name="%s[%s]" value="%s"> </li>', $data['icon'], esc_url( $data['url'] ), esc_html( $data['title'] ), esc_html( $data['name'] ), $data['edit_link'], esc_attr( $file ), esc_html( $i18n_delete ), esc_attr( $attributes['name'] ), esc_attr( $index ), esc_attr( $file ) ); } /** * Get file data uploaded to custom directory. * * @param string $file URL to uploaded file. * @param array $field Field settings. * @return string */ protected static function file_info_custom_dir( $file, $field ) { $path = wp_normalize_path( trailingslashit( $field['upload_dir'] ) . basename( $file ) ); $ext = pathinfo( $path, PATHINFO_EXTENSION ); $icon_url = wp_mime_type_icon( wp_ext2type( $ext ) ); $data = array( 'icon' => '<img width="48" height="64" src="' . esc_url( $icon_url ) . '" alt="">', 'name' => basename( $path ), 'path' => $path, 'url' => $file, 'title' => preg_replace( '/\.[^.]+$/', '', basename( $path ) ), 'edit_link' => '', ); return $data; } /** * Get meta values to save. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return array|mixed */ public static function value( $new, $old, $post_id, $field ) { $input = isset( $field['index'] ) ? $field['index'] : $field['input_name']; // @codingStandardsIgnoreLine if ( empty( $input ) || empty( $_FILES[ $input ] ) ) { return $new; } $new = array_filter( (array) $new ); $count = self::transform( $input ); for ( $i = 0; $i <= $count; $i ++ ) { $attachment = self::handle_upload( "{$input}_{$i}", $post_id, $field ); if ( $attachment && ! is_wp_error( $attachment ) ) { $new[] = $attachment; } } return $new; } /** * Get meta values to save for cloneable fields. * * @param array $new The submitted meta value. * @param array $old The existing meta value. * @param int $object_id The object ID. * @param array $field The field settings. * @param array $data_source Data source. Either $_POST or custom array. Used in group to get uploaded files. * * @return mixed */ public static function clone_value( $new, $old, $object_id, $field, $data_source = null ) { if ( ! $data_source ) { // @codingStandardsIgnoreLine $data_source = $_POST; } // @codingStandardsIgnoreLine $indexes = isset( $data_source[ "_index_{$field['id']}" ] ) ? $data_source[ "_index_{$field['id']}" ] : array(); foreach ( $indexes as $key => $index ) { $field['index'] = $index; $old_value = isset( $old[ $key ] ) ? $old[ $key ] : array(); $value = isset( $new[ $key ] ) ? $new[ $key ] : array(); $value = self::value( $value, $old_value, $object_id, $field ); $new[ $key ] = self::filter( 'sanitize', $value, $field, $old_value, $object_id ); } return $new; } /** * Handle file upload. * Consider upload to Media Library or custom folder. * * @param string $file_id File ID in $_FILES when uploading. * @param int $post_id Post ID. * @param array $field Field settings. * * @return \WP_Error|int|string WP_Error if has error, attachment ID if upload in Media Library, URL to file if upload to custom folder. */ protected static function handle_upload( $file_id, $post_id, $field ) { return $field['upload_dir'] ? self::handle_upload_custom_dir( $file_id, $field ) : media_handle_upload( $file_id, $post_id ); } /** * Transform $_FILES from $_FILES['field']['key']['index'] to $_FILES['field_index']['key']. * * @param string $input_name The field input name. * * @return int The number of uploaded files. */ protected static function transform( $input_name ) { // @codingStandardsIgnoreStart foreach ( $_FILES[ $input_name ] as $key => $list ) { foreach ( $list as $index => $value ) { $file_key = "{$input_name}_{$index}"; if ( ! isset( $_FILES[ $file_key ] ) ) { $_FILES[ $file_key ] = array(); } $_FILES[ $file_key ][ $key ] = $value; } } return count( $_FILES[ $input_name ]['name'] ); // @codingStandardsIgnoreEnd } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, [ 'std' => [], 'force_delete' => false, 'max_file_uploads' => 0, 'mime_type' => '', 'upload_dir' => '', 'unique_filename_callback' => null, ] ); $field['multiple'] = true; $field['input_name'] = "_file_{$field['id']}"; $field['index_name'] = "_index_{$field['id']}"; return $field; } /** * Get the field value. Return meaningful info of the files. * * @param array $field Field parameters. * @param array $args Not used for this field. * @param int|null $post_id Post ID. null for current post. Optional. * * @return mixed Full info of uploaded files */ public static function get_value( $field, $args = array(), $post_id = null ) { $value = parent::get_value( $field, $args, $post_id ); if ( ! $field['clone'] ) { $value = self::call( 'files_info', $field, $value, $args ); } else { $return = array(); foreach ( $value as $subvalue ) { $return[] = self::call( 'files_info', $field, $subvalue, $args ); } $value = $return; } if ( isset( $args['limit'] ) ) { $value = array_slice( $value, 0, intval( $args['limit'] ) ); } return $value; } /** * Get uploaded files information. * * @param array $field Field parameters. * @param array $files Files IDs. * @param array $args Additional arguments (for image size). * @return array */ public static function files_info( $field, $files, $args ) { $return = array(); foreach ( (array) $files as $file ) { $info = self::call( $field, 'file_info', $file, $args ); if ( $info ) { $return[ $file ] = $info; } } return $return; } /** * Get uploaded file information. * * @param int $file Attachment file ID (post ID). Required. * @param array $args Array of arguments (for size). * @param array $field Field settings. * * @return array|bool False if file not found. Array of (id, name, path, url) on success. */ public static function file_info( $file, $args = array(), $field = array() ) { if ( $field['upload_dir'] ) { return self::file_info_custom_dir( $file, $field ); } $path = get_attached_file( $file ); if ( ! $path ) { return false; } return wp_parse_args( array( 'ID' => $file, 'name' => basename( $path ), 'path' => $path, 'url' => wp_get_attachment_url( $file ), 'title' => get_the_title( $file ), ), wp_get_attachment_metadata( $file ) ); } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param array $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $value['url'] ), esc_html( $value['title'] ) ); } /** * Handle upload for files in custom directory. * * @param string $file_id File ID in $_FILES when uploading. * @param array $field Field settings. * * @return string URL to uploaded file. */ public static function handle_upload_custom_dir( $file_id, $field ) { // @codingStandardsIgnoreStart if ( empty( $_FILES[ $file_id ] ) ) { return; } $file = $_FILES[ $file_id ]; // @codingStandardsIgnoreEnd // Use a closure to filter upload directory. Requires PHP >= 5.3.0. $filter_upload_dir = function( $uploads ) use ( $field ) { $uploads['path'] = $field['upload_dir']; $uploads['url'] = self::convert_path_to_url( $field['upload_dir'] ); $uploads['subdir'] = ''; $uploads['basedir'] = $field['upload_dir']; return $uploads; }; // Make sure upload dir is inside WordPress. $upload_dir = wp_normalize_path( untrailingslashit( $field['upload_dir'] ) ); $root = wp_normalize_path( untrailingslashit( ABSPATH ) ); if ( 0 !== strpos( $upload_dir, $root ) ) { return; } // Let WordPress handle upload to the custom directory. add_filter( 'upload_dir', $filter_upload_dir ); $overrides = [ 'test_form' => false, 'unique_filename_callback' => $field['unique_filename_callback'], ]; $file_info = wp_handle_upload( $file, $overrides ); remove_filter( 'upload_dir', $filter_upload_dir ); return empty( $file_info['url'] ) ? null : $file_info['url']; } /** * Convert a path to an URL. * * @param string $path Full path to a file or a directory. * @return string URL to the file or directory. */ public static function convert_path_to_url( $path ) { $path = wp_normalize_path( untrailingslashit( $path ) ); $root = wp_normalize_path( untrailingslashit( ABSPATH ) ); $relative_path = str_replace( $root, '', $path ); return home_url( $relative_path ); } } fields/checkbox.php 0000644 00000002575 15105434331 0010321 0 ustar 00 <?php /** * The checkbox field. * * @package Meta Box */ /** * Checkbox field class. */ class RWMB_Checkbox_Field extends RWMB_Input_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $attributes = self::get_attributes( $field, 1 ); $output = sprintf( '<input %s %s>', self::render_attributes( $attributes ), checked( ! empty( $meta ), 1, false ) ); if ( $field['desc'] ) { $output = "<label id='{$field['id']}_description' class='description'>$output {$field['desc']}</label>"; } return $output; } /** * Do not show field description. * * @param array $field Field parameters. * @return string */ public static function input_description( $field ) { return ''; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return $value ? __( 'Yes', 'meta-box' ) : __( 'No', 'meta-box' ); } } fields/select.php 0000644 00000005031 15105434331 0010000 0 ustar 00 <?php /** * The select field. * * @package Meta Box */ /** * Select field class. */ class RWMB_Select_Field extends RWMB_Choice_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-select', RWMB_CSS_URL . 'select.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array( 'jquery' ), RWMB_VER, true ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $options = self::transform_options( $field['options'] ); $attributes = self::call( 'get_attributes', $field, $meta ); $attributes['data-selected'] = $meta; $walker = new RWMB_Walker_Select( $field, $meta ); $output = sprintf( '<select %s>', self::render_attributes( $attributes ) ); if ( ! $field['multiple'] && $field['placeholder'] ) { $output .= '<option value="">' . esc_html( $field['placeholder'] ) . '</option>'; } $output .= $walker->walk( $options, $field['flatten'] ? -1 : 0 ); $output .= '</select>'; $output .= self::get_select_all_html( $field ); return $output; } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field; $field = wp_parse_args( $field, array( 'select_all_none' => false, ) ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'multiple' => $field['multiple'], ) ); return $attributes; } /** * Get html for select all|none for multiple select. * * @param array $field Field parameters. * @return string */ public static function get_select_all_html( $field ) { if ( $field['multiple'] && $field['select_all_none'] ) { return '<div class="rwmb-select-all-none">' . __( 'Select', 'meta-box' ) . ': <a data-type="all" href="#">' . __( 'All', 'meta-box' ) . '</a> | <a data-type="none" href="#">' . __( 'None', 'meta-box' ) . '</a></div>'; } return ''; } } fields/image-upload.php 0000644 00000001775 15105434331 0011100 0 ustar 00 <?php /** * The image upload field which allows users to drag and drop images. * * @package Meta Box */ /** * File advanced field class which users WordPress media popup to upload and select files. */ class RWMB_Image_Upload_Field extends RWMB_Image_Advanced_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); RWMB_File_Upload_Field::admin_enqueue_scripts(); wp_enqueue_script( 'rwmb-image-upload', RWMB_JS_URL . 'image-upload.js', array( 'rwmb-file-upload', 'rwmb-image-advanced' ), RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); return RWMB_File_Upload_Field::normalize( $field ); } /** * Template for media item. */ public static function print_templates() { parent::print_templates(); RWMB_File_Upload_Field::print_templates(); } } fields/select-advanced.php 0000644 00000004422 15105434331 0011546 0 ustar 00 <?php /** * The beautiful select field which uses select2 library. * * @package Meta Box */ /** * Select advanced field which uses select2 library. */ class RWMB_Select_Advanced_Field extends RWMB_Select_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_style( 'rwmb-select2', RWMB_CSS_URL . 'select2/select2.css', array(), '4.0.10' ); wp_enqueue_style( 'rwmb-select-advanced', RWMB_CSS_URL . 'select-advanced.css', array(), RWMB_VER ); wp_register_script( 'rwmb-select2', RWMB_JS_URL . 'select2/select2.min.js', array( 'jquery' ), '4.0.10', true ); // Localize. $dependencies = array( 'rwmb-select2', 'rwmb-select' ); $locale = str_replace( '_', '-', get_locale() ); $locale_short = substr( $locale, 0, 2 ); $locale = file_exists( RWMB_DIR . "js/select2/i18n/$locale.js" ) ? $locale : $locale_short; if ( file_exists( RWMB_DIR . "js/select2/i18n/$locale.js" ) ) { wp_register_script( 'rwmb-select2-i18n', RWMB_JS_URL . "select2/i18n/$locale.js", array( 'rwmb-select2' ), '4.0.10', true ); $dependencies[] = 'rwmb-select2-i18n'; } wp_enqueue_script( 'rwmb-select-advanced', RWMB_JS_URL . 'select-advanced.js', $dependencies, RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'js_options' => array(), 'placeholder' => __( 'Select an item', 'meta-box' ), ) ); $field = parent::normalize( $field ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'allowClear' => true, 'dropdownAutoWidth' => true, 'placeholder' => $field['placeholder'], 'width' => 'style', ) ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'data-options' => wp_json_encode( $field['js_options'] ), ) ); return $attributes; } } fields/slider.php 0000644 00000004064 15105434331 0010010 0 ustar 00 <?php /** * The slider field which users jQueryUI slider widget. * * @package Meta Box */ /** * Slider field class. */ class RWMB_Slider_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { $url = RWMB_CSS_URL . 'jqueryui'; wp_register_style( 'jquery-ui-core', "$url/core.css", [], '1.12.1' ); wp_register_style( 'jquery-ui-theme', "$url/theme.css", [], '1.12.1' ); wp_register_style( 'jquery-ui-slider', "$url/slider.css", ['jquery-ui-core', 'jquery-ui-theme'], '1.12.1' ); wp_enqueue_style( 'rwmb-slider', RWMB_CSS_URL . 'slider.css', ['jquery-ui-slider'], RWMB_VER ); wp_enqueue_script( 'rwmb-slider', RWMB_JS_URL . 'slider.js', ['jquery-ui-slider', 'jquery-ui-widget', 'jquery-ui-mouse', 'jquery-ui-core'], RWMB_VER, true ); } /** * Get div HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $attributes = self::call( 'get_attributes', $field, $meta ); return sprintf( '<div class="rwmb-slider-inner"> <div class="rwmb-slider-ui" id="%s" data-options="%s"></div> <span class="rwmb-slider-label">%s<span>%s</span>%s</span> <input type="hidden" value="%s" %s> </div>', $field['id'], esc_attr( wp_json_encode( $field['js_options'] ) ), $field['prefix'], $meta, $field['suffix'], $meta, self::render_attributes( $attributes ) ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'prefix' => '', 'suffix' => '', 'std' => '', 'js_options' => array(), ) ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'range' => 'min', // range = 'min' will add a dark background to sliding part, better UI. 'value' => $field['std'], ) ); return $field; } } fields/post.php 0000644 00000013151 15105434331 0007510 0 ustar 00 <?php /** * The post field which allows users to select existing posts. * * @package Meta Box */ /** * Post field class. */ class RWMB_Post_Field extends RWMB_Object_Choice_Field { /** * Add ajax actions callback. */ public static function add_actions() { add_action( 'wp_ajax_rwmb_get_posts', array( __CLASS__, 'ajax_get_posts' ) ); add_action( 'wp_ajax_nopriv_rwmb_get_posts', array( __CLASS__, 'ajax_get_posts' ) ); } /** * Query posts via ajax. */ public static function ajax_get_posts() { check_ajax_referer( 'query' ); $request = rwmb_request(); $field = $request->filter_post( 'field', FILTER_DEFAULT, FILTER_FORCE_ARRAY ); // Required for 'choice_label' filter. See self::filter(). $field['clone'] = false; $field['_original_id'] = $field['id']; // Search. $field['query_args']['s'] = $request->filter_post( 'term', FILTER_SANITIZE_STRING ); // Pagination. if ( 'query:append' === $request->filter_post( '_type', FILTER_SANITIZE_STRING ) ) { $field['query_args']['paged'] = $request->filter_post( 'page', FILTER_SANITIZE_NUMBER_INT ); } // Query the database. $items = self::query( null, $field ); $items = array_values( $items ); $data = array( 'items' => $items ); // More items for pagination. $limit = (int) $field['query_args']['posts_per_page']; if ( -1 !== $limit && count( $items ) === $limit ) { $data['more'] = true; } wp_send_json_success( $data ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'post_type' => 'post', 'parent' => false, 'query_args' => array(), ) ); $field['post_type'] = (array) $field['post_type']; /* * Set default placeholder: * - If multiple post types: show 'Select a post'. * - If single post type: show 'Select a %post_type_name%'. */ $placeholder = __( 'Select a post', 'meta-box' ); if ( 1 === count( $field['post_type'] ) ) { $post_type = reset( $field['post_type'] ); $post_type_object = get_post_type_object( $post_type ); if ( ! empty( $post_type_object ) ) { // Translators: %s is the taxonomy singular label. $placeholder = sprintf( __( 'Select a %s', 'meta-box' ), strtolower( $post_type_object->labels->singular_name ) ); } } $field = wp_parse_args( $field, array( 'placeholder' => $placeholder, ) ); // Set parent option, which will change field name to `parent_id` to save as post parent. if ( $field['parent'] ) { $field['multiple'] = false; $field['field_name'] = 'parent_id'; } $field = parent::normalize( $field ); // Set default query args. $posts_per_page = $field['ajax'] ? 10 : -1; $field['query_args'] = wp_parse_args( $field['query_args'], array( 'post_type' => $field['post_type'], 'post_status' => 'publish', 'posts_per_page' => $posts_per_page, ) ); parent::set_ajax_params( $field ); return $field; } /** * Query posts for field options. * * @param array $meta Saved meta value. * @param array $field Field settings. * @return array Field options array. */ public static function query( $meta, $field ) { $args = wp_parse_args( $field['query_args'], array( 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ) ); // Query only selected items. if ( ! empty( $field['ajax'] ) && ! empty( $meta ) ) { $args['posts_per_page'] = count( $meta ); $args['post__in'] = $meta; } // Get from cache to prevent same queries. $last_changed = wp_cache_get_last_changed( 'posts' ); $key = md5( serialize( $args ) ); $cache_key = "$key:$last_changed"; $options = wp_cache_get( $cache_key, 'meta-box-post-field' ); if ( false !== $options ) { return $options; } $query = new WP_Query( $args ); $options = array(); foreach ( $query->posts as $post ) { $label = $post->post_title ? $post->post_title : __( '(No title)', 'meta-box' ); $label = self::filter( 'choice_label', $label, $field, $post ); $options[ $post->ID ] = array( 'value' => $post->ID, 'label' => $label, 'parent' => $post->post_parent, ); } // Cache the query. wp_cache_set( $cache_key, $options, 'meta-box-post-field' ); return $options; } /** * Get meta value. * If field is cloneable, value is saved as a single entry in DB. * Otherwise value is saved as multiple entries (for backward compatibility). * * @see "save" method for better understanding * * @param int $post_id Post ID. * @param bool $saved Is the meta box saved. * @param array $field Field parameters. * * @return mixed */ public static function meta( $post_id, $saved, $field ) { return $field['parent'] ? wp_get_post_parent_id( $post_id ) : parent::meta( $post_id, $saved, $field ); } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return ! $value ? '' : sprintf( '<a href="%s" title="%s">%s</a>', esc_url( get_permalink( $value ) ), the_title_attribute( array( 'post' => $value, 'echo' => false, ) ), get_the_title( $value ) ); } } fields/taxonomy-advanced.php 0000644 00000005727 15105434331 0012156 0 ustar 00 <?php /** * Taxonomy advanced field which saves terms' IDs in the post meta in CSV format. * * @package Meta Box */ /** * The taxonomy advanced field class. */ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field { /** * Save terms in form of comma-separated IDs. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return string */ public static function value( $new, $old, $post_id, $field ) { $new = parent::value( $new, $old, $post_id, $field ); return implode( ',', $new ); } /** * Save meta value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. */ public static function save( $new, $old, $post_id, $field ) { $field['multiple'] = false; // Force to save in 1 row in the database. RWMB_Field::save( $new, $old, $post_id, $field ); } /** * Get raw meta value. * * @param int $object_id Object ID. * @param array $field Field parameters. * @param array $args Arguments of {@see rwmb_meta()} helper. * * @return mixed */ public static function raw_meta( $object_id, $field, $args = array() ) { $args['single'] = true; $meta = RWMB_Field::raw_meta( $object_id, $field, $args ); if ( empty( $meta ) ) { return $field['multiple'] ? array() : ''; } $meta = $field['clone'] ? array_map( 'wp_parse_id_list', $meta ) : wp_parse_id_list( $meta ); $meta = array_filter( $meta ); return $meta; } /** * Get the field value. * Return list of post term objects. * * @param array $field Field parameters. * @param array $args Additional arguments. * @param int|null $post_id Post ID. null for current post. Optional. * * @return array List of post term objects. */ public static function get_value( $field, $args = array(), $post_id = null ) { $value = RWMB_Field::get_value( $field, $args, $post_id ); if ( ! $field['clone'] ) { $value = self::call( 'terms_info', $field, $value, $args ); } else { $return = array(); foreach ( $value as $subvalue ) { $return[] = self::call( 'terms_info', $field, $subvalue, $args ); } $value = $return; } return $value; } /** * Get terms information. * * @param array $field Field parameters. * @param string $term_ids Term IDs, in CSV format. * @param array $args Additional arguments (for image size). * * @return array */ public static function terms_info( $field, $term_ids, $args ) { if ( empty( $term_ids ) ) { return array(); } $args = wp_parse_args( array( 'include' => $term_ids, 'hide_empty' => false, ), $args ); $info = get_terms( $field['taxonomy'], $args ); $info = is_array( $info ) ? $info : array(); return $field['multiple'] ? $info : reset( $info ); } } fields/map.php 0000644 00000015072 15105434331 0007304 0 ustar 00 <?php /** * The Google Maps field. * * @package Meta Box */ /** * Map field class. */ class RWMB_Map_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-map', RWMB_CSS_URL . 'map.css', array(), RWMB_VER ); /** * Since June 2016, Google Maps requires a valid API key. * * @link http://googlegeodevelopers.blogspot.com/2016/06/building-for-scale-updates-to-google.html * @link https://developers.google.com/maps/documentation/javascript/get-api-key */ $args = func_get_args(); $field = $args[0]; $google_maps_url = add_query_arg( array( 'key' => $field['api_key'], 'language' => $field['language'], ), 'https://maps.google.com/maps/api/js' ); /** * Allows developers load more libraries via a filter. * * @link https://developers.google.com/maps/documentation/javascript/libraries */ $google_maps_url = apply_filters( 'rwmb_google_maps_url', $google_maps_url ); wp_register_script( 'google-maps', esc_url_raw( $google_maps_url ), array(), RWMB_VER, true ); wp_enqueue_script( 'rwmb-map', RWMB_JS_URL . 'map.js', array( 'jquery-ui-autocomplete', 'google-maps', ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-map', 'RWMB_Map', array( 'no_results_string' => __( 'No results found', 'meta-box' ), ) ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $address = is_array( $field['address_field'] ) ? implode( ',', $field['address_field'] ) : $field['address_field']; $html = sprintf( '<div class="rwmb-map-field" data-address-field="%s">', esc_attr( $address ) ); $attributes = self::get_attributes( $field, $meta ); $attributes['type'] = 'hidden'; $attributes['value'] = $meta; $html .= sprintf( '<div class="rwmb-map-canvas" data-default-loc="%s" data-region="%s"></div> <input %s>', esc_attr( $field['std'] ), esc_attr( $field['region'] ), self::render_attributes( $attributes ) ); $html .= '</div>'; return $html; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'std' => '', 'address_field' => '', 'language' => '', 'region' => '', // Default API key, required by Google Maps since June 2016. // Users should overwrite this key with their own key. 'api_key' => 'AIzaSyC1mUh87SGFyf133tpZQJa-s96p0tgnraQ', ) ); return $field; } /** * Get the field value. * The difference between this function and 'meta' function is 'meta' function always returns the escaped value * of the field saved in the database, while this function returns more meaningful value of the field. * * @param array $field Field parameters. * @param array $args Not used for this field. * @param int|null $post_id Post ID. null for current post. Optional. * * @return mixed Array(latitude, longitude, zoom) */ public static function get_value( $field, $args = array(), $post_id = null ) { $value = parent::get_value( $field, $args, $post_id ); list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' ); return compact( 'latitude', 'longitude', 'zoom' ); } /** * Output the field value. * Display Google maps. * * @param array $field Field parameters. * @param array $args Additional arguments for the map. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string HTML output of the field */ public static function the_value( $field, $args = array(), $post_id = null ) { $value = parent::get_value( $field, $args, $post_id ); $args = wp_parse_args( $args, array( 'api_key' => isset( $field['api_key'] ) ? $field['api_key'] : '', ) ); return self::render_map( $value, $args ); } /** * Render a map in the frontend. * * @param array $location The [latitude, longitude[, zoom]] location. * @param array $args Additional arguments for the map. * * @return string */ public static function render_map( $location, $args = array() ) { list( $latitude, $longitude, $zoom ) = explode( ',', $location . ',,' ); if ( ! $latitude || ! $longitude ) { return ''; } $args = wp_parse_args( $args, array( 'latitude' => $latitude, 'longitude' => $longitude, 'width' => '100%', 'height' => '480px', 'marker' => true, // Display marker? 'marker_title' => '', // Marker title, when hover. 'info_window' => '', // Content of info window (when click on marker). HTML allowed. 'js_options' => array(), 'zoom' => $zoom, // Default API key, required by Google Maps since June 2016. // Users should overwrite this key with their own key. 'api_key' => 'AIzaSyC1mUh87SGFyf133tpZQJa-s96p0tgnraQ', ) ); $google_maps_url = add_query_arg( 'key', $args['api_key'], 'https://maps.google.com/maps/api/js' ); /* * Allows developers load more libraries via a filter. * @link https://developers.google.com/maps/documentation/javascript/libraries */ $google_maps_url = apply_filters( 'rwmb_google_maps_url', $google_maps_url ); wp_register_script( 'google-maps', esc_url_raw( $google_maps_url ), array(), RWMB_VER, true ); wp_enqueue_script( 'rwmb-map-frontend', RWMB_JS_URL . 'map-frontend.js', array( 'google-maps', 'jquery' ), RWMB_VER, true ); /* * Google Maps options. * Option name is the same as specified in Google Maps documentation. * This array will be convert to Javascript Object and pass as map options. * @link https://developers.google.com/maps/documentation/javascript/reference */ $args['js_options'] = wp_parse_args( $args['js_options'], array( // Default to 'zoom' level set in admin, but can be overwritten. 'zoom' => $args['zoom'], // Map type, see https://developers.google.com/maps/documentation/javascript/reference#MapTypeId. 'mapTypeId' => 'ROADMAP', // Open Info Window 'openInfoWindow' => false, ) ); $output = sprintf( '<div class="rwmb-map-canvas" data-map_options="%s" style="width:%s;height:%s"></div>', esc_attr( wp_json_encode( $args ) ), esc_attr( $args['width'] ), esc_attr( $args['height'] ) ); return $output; } } fields/image.php 0000644 00000011147 15105434331 0007610 0 ustar 00 <?php /** * The image field which uploads images via HTML <input type="file">. * * @package Meta Box */ /** * Image field class which uses <input type="file"> to upload. */ class RWMB_Image_Field extends RWMB_File_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_media(); wp_enqueue_style( 'rwmb-image', RWMB_CSS_URL . 'image.css', array(), RWMB_VER ); } /** * Get HTML for uploaded file. * * @param int $file Attachment (file) ID. * @param int $index File index. * @param array $field Field data. * * @return string */ protected static function file_html( $file, $index, $field ) { $attributes = self::get_attributes( $field, $file ); $edit_link = get_edit_post_link( $file ); if ( $edit_link ) { $edit_link = sprintf( '<a href="%s" class="rwmb-image-edit" target="_blank"><span class="dashicons dashicons-edit"></span></a>', $edit_link ); } return sprintf( '<li class="rwmb-image-item"> <div class="rwmb-file-icon">%s</div> <div class="rwmb-image-overlay"></div> <div class="rwmb-image-actions"> %s <a href="#" class="rwmb-image-delete rwmb-file-delete" data-attachment_id="%s"><span class="dashicons dashicons-no-alt"></span></a> </div> <input type="hidden" name="%s[%s]" value="%s"> </li>', wp_get_attachment_image( $file, $field['image_size'] ), $edit_link, esc_attr( $file ), esc_attr( $attributes['name'] ), esc_attr( $index ), esc_attr( $file ) ); } /** * Normalize field settings. * * @param array $field Field settings. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'image_size' => 'thumbnail', ) ); $field['attributes'] = wp_parse_args( $field['attributes'], array( 'accept' => 'image/*', ) ); return $field; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param array $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $output = sprintf( '<img src="%s" alt="%s">', esc_url( $value['url'] ), esc_attr( $value['alt'] ) ); // Link thumbnail to full size image? if ( ! empty( $args['link'] ) ) { $output = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( $value['full_url'] ), esc_attr( $value['title'] ), $output ); } return $output; } /** * Get uploaded file information. * * @param int $file Attachment image ID (post ID). Required. * @param array $args Array of arguments (for size). * @param array $field Field settings. * * @return array|bool False if file not found. Array of image info on success. */ public static function file_info( $file, $args = array(), $field = array() ) { $path = get_attached_file( $file ); if ( ! $path ) { return false; } $args = wp_parse_args( $args, array( 'size' => 'thumbnail', ) ); $image = wp_get_attachment_image_src( $file, $args['size'] ); $attachment = get_post( $file ); $info = array( 'ID' => $file, 'name' => basename( $path ), 'path' => $path, 'url' => $image[0], 'full_url' => wp_get_attachment_url( $file ), 'title' => $attachment->post_title, 'caption' => $attachment->post_excerpt, 'description' => $attachment->post_content, 'alt' => get_post_meta( $file, '_wp_attachment_image_alt', true ), ); if ( function_exists( 'wp_get_attachment_image_srcset' ) ) { $info['srcset'] = wp_get_attachment_image_srcset( $file, $args['size'] ); } $info = wp_parse_args( $info, self::get_image_meta_data( $file ) ); // Do not overwrite width and height by returned value of image meta. $info['width'] = $image[1]; $info['height'] = $image[2]; return $info; } /** * Get image meta data. * * @param int $attachment_id Attachment ID. * @return array */ protected static function get_image_meta_data( $attachment_id ) { $metadata = wp_get_attachment_metadata( $attachment_id ); if ( empty( $metadata['sizes'] ) ) { return $metadata; } $dir_url = dirname( wp_get_attachment_url( $attachment_id ) ); foreach ( $metadata['sizes'] as &$size ) { $size['url'] = "{$dir_url}/{$size['file']}"; } return $metadata; } } fields/multiple-values.php 0000644 00000002564 15105434331 0011661 0 ustar 00 <?php /** * This class implements common methods used in fields which have multiple values * like checkbox list, autocomplete, etc. * * The difference when handling actions for these fields are the way they get/set * meta value. Briefly: * - If field is cloneable, value is saved as a single entry in the database * - Otherwise value is saved as multiple entries * * @package Meta Box */ /** * Multiple values field class. */ abstract class RWMB_Multiple_Values_Field extends RWMB_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field['multiple'] = true; $field['field_name'] = $field['id']; if ( ! $field['clone'] ) { $field['field_name'] .= '[]'; } return $field; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return $field['options'][ $value ]; } } fields/autocomplete.php 0000644 00000005375 15105434331 0011235 0 ustar 00 <?php /** * The autocomplete field. * * @package Meta Box */ /** * Autocomplete field class. */ class RWMB_Autocomplete_Field extends RWMB_Multiple_Values_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-autocomplete', RWMB_CSS_URL . 'autocomplete.css', '', RWMB_VER ); wp_enqueue_script( 'rwmb-autocomplete', RWMB_JS_URL . 'autocomplete.js', array( 'jquery-ui-autocomplete' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-autocomplete', 'RWMB_Autocomplete', array( 'delete' => __( 'Delete', 'meta-box' ), ) ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { if ( ! is_array( $meta ) ) { $meta = array( $meta ); } $field = apply_filters( 'rwmb_autocomplete_field', $field, $meta ); $options = $field['options']; if ( is_array( $field['options'] ) ) { $options = array(); foreach ( $field['options'] as $value => $label ) { $options[] = array( 'value' => $value, 'label' => $label, ); } $options = wp_json_encode( $options ); } // Input field that triggers autocomplete. // This field doesn't store field values, so it doesn't have "name" attribute. // The value(s) of the field is store in hidden input(s). See below. $html = sprintf( '<input type="text" class="rwmb-autocomplete-search"> <input type="hidden" name="%s" class="rwmb-autocomplete" data-options="%s" disabled>', esc_attr( $field['field_name'] ), esc_attr( $options ) ); $html .= '<div class="rwmb-autocomplete-results">'; // Each value is displayed with label and 'Delete' option. // The hidden input has to have ".rwmb-*" class to make clone work. $tpl = ' <div class="rwmb-autocomplete-result"> <div class="label">%s</div> <div class="actions">%s</div> <input type="hidden" class="rwmb-autocomplete-value" name="%s" value="%s"> </div> '; if ( is_array( $field['options'] ) ) { foreach ( $field['options'] as $value => $label ) { if ( ! in_array( $value, $meta ) ) { continue; } $html .= sprintf( $tpl, esc_html( $label ), esc_html__( 'Delete', 'meta-box' ), esc_attr( $field['field_name'] ), esc_attr( $value ) ); } } else { $meta = array_filter( $meta ); foreach ( $meta as $value ) { $label = apply_filters( 'rwmb_autocomplete_result_label', $value, $field ); $html .= sprintf( $tpl, esc_html( $label ), esc_html__( 'Delete', 'meta-box' ), esc_attr( $field['field_name'] ), esc_attr( $value ) ); } } $html .= '</div>'; // .rwmb-autocomplete-results. return $html; } } fields/choice.php 0000644 00000003535 15105434331 0007762 0 ustar 00 <?php /** * The abstract choice field. * * @package Meta Box */ /** * Abstract class for any kind of choice field. */ abstract class RWMB_Choice_Field extends RWMB_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { return ''; } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'flatten' => true, 'options' => array(), ) ); return $field; } /** * Transform field options into the verbose format. * * @param array $options Field options. * * @return array */ public static function transform_options( $options ) { $transformed = array(); $options = (array) $options; foreach ( $options as $value => $label ) { $option = is_array( $label ) ? $label : array( 'label' => (string) $label, 'value' => (string) $value, ); if ( isset( $option['label'] ) && isset( $option['value'] ) ) { $transformed[ $option['value'] ] = (object) $option; } } return $transformed; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $options = self::transform_options( $field['options'] ); return isset( $options[ $value ] ) ? $options[ $value ]->label : ''; } } fields/password.php 0000644 00000001065 15105434331 0010366 0 ustar 00 <?php /** * The secured password field. * * @package Meta Box */ /** * Password field class. */ class RWMB_Password_Field extends RWMB_Input_Field { /** * Store secured password in the database. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * @return string */ public static function value( $new, $old, $post_id, $field ) { $new = $new !== $old ? wp_hash_password( $new ) : $new; return $new; } } fields/single-image.php 0000644 00000003446 15105434331 0011072 0 ustar 00 <?php /** * The advanced image upload field which uses WordPress media popup to upload and select images. * * @package Meta Box */ /** * Image advanced field class. */ class RWMB_Single_Image_Field extends RWMB_Image_Advanced_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field['max_file_uploads'] = 1; $field['max_status'] = false; $field = parent::normalize( $field ); $field['attributes'] = wp_parse_args( $field['attributes'], array( 'class' => '', 'data-single-image' => 1, ) ); $field['attributes']['class'] .= ' rwmb-image_advanced'; $field['multiple'] = false; return $field; } /** * Get meta values to save. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return array|mixed */ public static function value( $new, $old, $post_id, $field ) { return $new; } /** * Get the field value. Return meaningful info of the files. * * @param array $field Field parameters. * @param array $args Not used for this field. * @param int|null $post_id Post ID. null for current post. Optional. * * @return mixed Full info of uploaded files */ public static function get_value( $field, $args = array(), $post_id = null ) { $value = RWMB_Field::get_value( $field, $args, $post_id ); if ( ! is_array( $value ) ) { return RWMB_Image_Field::file_info( $value, $args, $field ); } $return = array(); foreach ( $value as $image_id ) { $return[] = RWMB_Image_Field::file_info( $image_id, $args, $field ); } return $return; } } fields/divider.php 0000644 00000001575 15105434331 0010160 0 ustar 00 <?php /** * The divider field which displays a simple horizontal line. * * @package Meta Box */ /** * Divider field class. */ class RWMB_Divider_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-divider', RWMB_CSS_URL . 'divider.css', array(), RWMB_VER ); } /** * Show begin HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function begin_html( $meta, $field ) { $attributes = empty( $field['id'] ) ? '' : " id='{$field['id']}'"; return "<hr$attributes>"; } /** * Show end HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function end_html( $meta, $field ) { return ''; } } fields/switch.php 0000644 00000004526 15105434331 0010032 0 ustar 00 <?php /** * The Switch field. * * @package Meta Box */ /** * Switch field class. */ class RWMB_Switch_Field extends RWMB_Input_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-switch', RWMB_CSS_URL . 'switch.css', '', RWMB_VER ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $attributes = self::get_attributes( $field, 1 ); $output = sprintf( '<label class="rwmb-switch-label rwmb-switch-label--' . esc_attr( $field['style'] ) . '"> <input %s %s> <div class="rwmb-switch-status"> <span class="rwmb-switch-slider"></span> <span class="rwmb-switch-on">' . $field['on_label'] . '</span> <span class="rwmb-switch-off">' . $field['off_label'] . '</span> </div> </label> ', self::render_attributes( $attributes ), checked( ! empty( $meta ), 1, false ) ); return $output; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'style' => 'rounded', 'on_label' => '', 'off_label' => '', ) ); return $field; } /** * Get the attributes for a field. * * @param array $field The field parameters. * @param mixed $value The attribute value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes['type'] = 'checkbox'; return $attributes; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $on = $field['on_label'] ?: __( 'On', 'meta-box' ); $off = $field['off_label'] ?: __( 'Off', 'meta-box' ); return $value ? $on : $off; } } fields/range.php 0000644 00000003033 15105434331 0007615 0 ustar 00 <?php /** * The HTML5 range field. * * @package Meta Box */ /** * HTML5 range field class. */ class RWMB_Range_Field extends RWMB_Number_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { return sprintf( '<div class="rwmb-range-inner"> %s <span class="rwmb-range-output">%s</span> </div>', parent::html( $meta, $field ), $meta ); } /** * Enqueue styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-range', RWMB_CSS_URL . 'range.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-range', RWMB_JS_URL . 'range.js', array(), RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'max' => 10, ) ); $field = parent::normalize( $field ); return $field; } /** * Ensure number in range. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return int */ public static function value( $new, $old, $post_id, $field ) { $new = intval( $new ); $min = intval( $field['min'] ); $max = intval( $field['max'] ); if ( $new < $min ) { return $min; } if ( $new > $max ) { return $max; } return $new; } } fields/heading.php 0000644 00000001677 15105434331 0010134 0 ustar 00 <?php /** * The heading field which displays a simple heading text. * * @package Meta Box */ /** * Heading field class. */ class RWMB_Heading_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-heading', RWMB_CSS_URL . 'heading.css', array(), RWMB_VER ); } /** * Show begin HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function begin_html( $meta, $field ) { $attributes = empty( $field['id'] ) ? '' : " id='{$field['id']}'"; return sprintf( '<h4%s>%s</h4>', $attributes, $field['name'] ); } /** * Show end HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function end_html( $meta, $field ) { return self::input_description( $field ); } } fields/text-list.php 0000644 00000006607 15105434331 0010470 0 ustar 00 <?php /** * The text list field which allows users to enter multiple texts. * * @package Meta Box */ /** * Text list field class. */ class RWMB_Text_List_Field extends RWMB_Multiple_Values_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-text-list', RWMB_CSS_URL . 'text-list.css', '', RWMB_VER ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { if ( empty( $field['options'] ) ) { return ''; } $html = array(); $input = '<label><span class="rwmb-text-list-label">%s</span> <input %s></label>'; $attributes = self::get_attributes( $field, $meta ); $attributes['type'] = 'text'; $count = 0; foreach ( $field['options'] as $placeholder => $label ) { $attributes['value'] = isset( $meta[ $count ] ) ? esc_attr( $meta[ $count ] ) : ''; $attributes['placeholder'] = $placeholder; $html[] = sprintf( $input, $label, self::render_attributes( $attributes ) ); $count ++; } return implode( ' ', $html ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); if ( ! $field['clone'] ) { $field['class'] .= ' rwmb-text_list-non-cloneable'; } return $field; } /** * Set value of meta before saving into database. * Do not save if all inputs has no value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return mixed */ public static function value( $new, $old, $post_id, $field ) { $filtered = array_filter( $new ); return count( $filtered ) ? $new : array(); } /** * Format value for the helper functions. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_value( $field, $value, $args, $post_id ) { $output = '<table><thead><tr>'; foreach ( $field['options'] as $label ) { $output .= "<th>$label</th>"; } $output .= '</tr></thead><tbody>'; if ( ! $field['clone'] ) { $output .= self::format_single_value( $field, $value, $args, $post_id ); } else { foreach ( $value as $subvalue ) { $output .= self::format_single_value( $field, $subvalue, $args, $post_id ); } } $output .= '</tbody></table>'; return $output; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param array $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $output = '<tr>'; foreach ( $value as $subvalue ) { $output .= "<td>$subvalue</td>"; } $output .= '</tr>'; return $output; } } fields/radio.php 0000644 00000000625 15105434331 0007623 0 ustar 00 <?php /** * The radio field. * * @package Meta Box */ /** * Radio field class. */ class RWMB_Radio_Field extends RWMB_Input_List_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field['multiple'] = false; $field = parent::normalize( $field ); return $field; } } fields/color.php 0000644 00000005060 15105434331 0007641 0 ustar 00 <?php /** * The color field which uses WordPress color picker to select a color. * * @package Meta Box */ /** * Color field class. */ class RWMB_Color_Field extends RWMB_Input_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-color', RWMB_CSS_URL . 'color.css', array( 'wp-color-picker' ), RWMB_VER ); $dependencies = array( 'wp-color-picker' ); $args = func_get_args(); $field = reset( $args ); if ( ! empty( $field['alpha_channel'] ) ) { wp_enqueue_script( 'wp-color-picker-alpha', RWMB_JS_URL . 'wp-color-picker-alpha/wp-color-picker-alpha.min.js', array( 'wp-color-picker' ), RWMB_VER, true ); $dependencies = array( 'wp-color-picker-alpha' ); } wp_enqueue_script( 'rwmb-color', RWMB_JS_URL . 'color.js', $dependencies, RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'alpha_channel' => false, 'js_options' => array(), ) ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'defaultColor' => false, 'hide' => true, 'palettes' => true, ) ); $field = parent::normalize( $field ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'data-options' => wp_json_encode( $field['js_options'] ), ) ); $attributes['type'] = 'text'; if ( $field['alpha_channel'] ) { $attributes['data-alpha-enabled'] = 'true'; $attributes['data-alpha-color-type'] = 'hex'; } return $attributes; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return sprintf( "<span style='display:inline-block;width:20px;height:20px;border-radius:50%%;background:%s;'></span>", $value ); } } fields/media.php 0000644 00000016010 15105434331 0007577 0 ustar 00 <?php /** * Media field class which users WordPress media popup to upload and select files. * * @package Meta Box */ /** * The media field class. */ class RWMB_Media_Field extends RWMB_File_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_media(); if ( ! is_admin() ) { wp_register_script( 'media-grid', includes_url( 'js/media-grid.min.js' ), array( 'media-editor' ), '4.9.7', true ); } wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone', 'media-grid' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-media', 'i18nRwmbMedia', array( 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ), 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ), 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ), 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ), 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ), 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ), 'noTitle' => _x( 'No Title', 'media', 'meta-box' ), 'loadingUrl' => admin_url( 'images/spinner.gif' ), 'extensions' => self::get_mime_extensions(), 'select' => apply_filters( 'rwmb_media_select_string', _x( 'Select Files', 'media', 'meta-box' ) ), 'or' => apply_filters( 'rwmb_media_or_string', _x( 'or', 'media', 'meta-box' ) ), 'uploadInstructions' => apply_filters( 'rwmb_media_upload_instructions_string', _x( 'Drop files here to upload', 'media', 'meta-box' ) ), ) ); } /** * Add actions. */ public static function add_actions() { $args = func_get_args(); $field = reset( $args ); add_action( 'print_media_templates', array( RWMB_Helpers_Field::get_class( $field ), 'print_templates' ) ); } /** * Get meta value. * * @param int $post_id Post ID. * @param bool $saved Whether the meta box is saved at least once. * @param array $field Field parameters. * * @return mixed */ public static function meta( $post_id, $saved, $field ) { $meta = parent::meta( $post_id, $saved, $field ); /* * Update meta cache for all attachments, preparing for getting data for rendering in JS. * This reduces the number of queries for updating all attachments' meta. * @see get_attributes() */ $ids = (array) $meta; if ( $field['clone'] ) { foreach ( $ids as &$value ) { $value = (array) $value; } $ids = call_user_func_array( 'array_merge', $ids ); } update_meta_cache( 'post', $ids ); return $meta; } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $attributes = self::call( 'get_attributes', $field, $meta ); $html = sprintf( '<input %s data-options="%s">', self::render_attributes( $attributes ), esc_attr( wp_json_encode( $field['js_options'] ) ) ); return $html; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'std' => array(), 'mime_type' => '', 'max_file_uploads' => 0, 'force_delete' => false, 'max_status' => true, 'js_options' => array(), 'add_to' => 'end', ) ); $field['js_options'] = wp_parse_args( $field['js_options'], array( 'mimeType' => $field['mime_type'], 'maxFiles' => $field['max_file_uploads'], 'forceDelete' => $field['force_delete'] ? true : false, 'maxStatus' => $field['max_status'], 'addTo' => $field['add_to'], ) ); $field['multiple'] = true; return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $value = (array) $value; $attributes = parent::get_attributes( $field, $value ); $attributes['type'] = 'hidden'; $attributes['name'] = $field['clone'] ? str_replace( '[]', '', $attributes['name'] ) : $attributes['name']; $attributes['id'] = false; $attributes['value'] = implode( ',', $value ); $attributes['class'] .= ' rwmb-media'; // Add attachment details. $attachments = array(); foreach ( $value as $media ) { $media = wp_prepare_attachment_for_js( $media ); // Some themes/plugins add HTML, shortcodes to "compat" attrbute which break JSON validity. if ( isset( $media['compat'] ) ) { unset( $media['compat'] ); } if ( ! empty( $media ) ) { $attachments[] = $media; } } $attachments = array_values( $attachments ); $attributes['data-attachments'] = json_encode( $attachments ); return $attributes; } /** * Get supported mime extensions. * * @return array */ protected static function get_mime_extensions() { $mime_types = wp_get_mime_types(); $extensions = array(); foreach ( $mime_types as $ext => $mime ) { $ext = explode( '|', $ext ); $extensions[ $mime ] = $ext; $mime_parts = explode( '/', $mime ); if ( empty( $extensions[ $mime_parts[0] ] ) ) { $extensions[ $mime_parts[0] ] = array(); } $extensions[ $mime_parts[0] ] = array_merge( $extensions[ $mime_parts[0] ], $ext ); $extensions[ $mime_parts[0] . '/*' ] = $extensions[ $mime_parts[0] ]; } return $extensions; } /** * Get meta values to save. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return array|mixed */ public static function value( $new, $old, $post_id, $field ) { $new = RWMB_Helpers_Array::from_csv( $new ); return array_filter( array_unique( array_map( 'absint', $new ) ) ); } /** * Save meta value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. */ public static function save( $new, $old, $post_id, $field ) { if ( empty( $field['id'] ) || ! $field['save_field'] ) { return; } $storage = $field['storage']; $storage->delete( $post_id, $field['id'] ); parent::save( $new, array(), $post_id, $field ); } /** * Template for media item. */ public static function print_templates() { require_once RWMB_INC_DIR . 'templates/media.php'; } } fields/wysiwyg.php 0000644 00000004314 15105434331 0010246 0 ustar 00 <?php /** * The WYSIWYG (editor) field. * * @package Meta Box */ /** * WYSIWYG (editor) field class. */ class RWMB_Wysiwyg_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_editor(); wp_enqueue_style( 'rwmb-wysiwyg', RWMB_CSS_URL . 'wysiwyg.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-wysiwyg', RWMB_JS_URL . 'wysiwyg.js', ['jquery', 'rwmb'], RWMB_VER, true ); } /** * Change field value on save. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * @return string */ public static function value( $new, $old, $post_id, $field ) { return $field['raw'] ? $new : wpautop( $new ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { // Using output buffering because wp_editor() echos directly. ob_start(); $attributes = self::get_attributes( $field ); $options = $field['options']; $options['textarea_name'] = $field['field_name']; if ( ! empty( $attributes['required'] ) ) { $options['editor_class'] .= ' rwmb-wysiwyg-required'; } wp_editor( $meta, $attributes['id'], $options ); echo '<script class="rwmb-wysiwyg-id" type="text/html" data-id="', esc_attr( $attributes['id'] ), '" data-options="', esc_attr( wp_json_encode( $options ) ), '"></script>'; return ob_get_clean(); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'raw' => false, 'options' => array(), ) ); $field['options'] = wp_parse_args( $field['options'], array( 'editor_class' => 'rwmb-wysiwyg', 'dfw' => true, // Use default WordPress full screen UI. ) ); // Keep the filter to be compatible with previous versions. $field['options'] = apply_filters( 'rwmb_wysiwyg_settings', $field['options'] ); return $field; } } fields/sidebar.php 0000644 00000002775 15105434331 0010146 0 ustar 00 <?php /** * The sidebar select field. * * @package Meta Box */ /** * Sidebar field class. */ class RWMB_Sidebar_Field extends RWMB_Object_Choice_Field { /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'placeholder' => __( 'Select a sidebar', 'meta-box' ), ) ); $field = parent::normalize( $field ); return $field; } /** * Get sidebars for field options. * * @param array $field Field settings. * @return array Field options array. */ public static function query( $field ) { global $wp_registered_sidebars; $options = array(); foreach ( $wp_registered_sidebars as $sidebar ) { $options[ $sidebar['id'] ] = array( 'value' => $sidebar['id'], 'label' => $sidebar['name'], ); } return $options; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { if ( ! is_active_sidebar( $value ) ) { return ''; } ob_start(); dynamic_sidebar( $value ); return ob_get_clean(); } } fields/button.php 0000644 00000002502 15105434331 0010034 0 ustar 00 <?php /** * The button field. Simply displays a HTML button which might be used for JavaScript actions. * * @package Meta Box */ /** * Button field class. */ class RWMB_Button_Field extends RWMB_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field The field parameters. * @return string */ public static function html( $meta, $field ) { $attributes = self::get_attributes( $field ); return sprintf( '<button %s>%s</button>', self::render_attributes( $attributes ), $field['std'] ); } /** * Normalize parameters for field. * * @param array $field The field parameters. * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'std' => __( 'Click me', 'meta-box' ), ) ); $field = parent::normalize( $field ); return $field; } /** * Get the attributes for a field. * * @param array $field The field parameters. * @param mixed $value The attribute value. * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'type' => $field['type'], ) ); $attributes['class'] .= ' button hide-if-no-js'; return $attributes; } } fields/datetime.php 0000644 00000022532 15105434331 0010322 0 ustar 00 <?php /** * The date and time picker field which allows users to select both date and time via jQueryUI datetime picker. * * @package Meta Box */ /** * Datetime field class. */ class RWMB_Datetime_Field extends RWMB_Input_Field { /** * Translate date format from jQuery UI date picker to PHP date(). * It's used to store timestamp value of the field. * Missing: '!' => '', 'oo' => '', '@' => '', "''" => "'". * * @var array */ protected static $date_formats = array( 'd' => 'j', 'dd' => 'd', 'oo' => 'z', 'D' => 'D', 'DD' => 'l', 'm' => 'n', 'mm' => 'm', 'M' => 'M', 'MM' => 'F', 'y' => 'y', 'yy' => 'Y', 'o' => 'z', ); /** * Translate time format from jQuery UI time picker to PHP date(). * It's used to store timestamp value of the field. * Missing: 't' => '', T' => '', 'm' => '', 's' => ''. * * @var array */ protected static $time_formats = array( 'H' => 'G', 'HH' => 'H', 'h' => 'g', 'hh' => 'h', 'mm' => 'i', 'ss' => 's', 'l' => 'u', 'tt' => 'a', 'TT' => 'A', ); public static function register_assets() { // jQueryUI base theme: https://github.com/jquery/jquery-ui/tree/1.12.1/themes/base $url = RWMB_CSS_URL . 'jqueryui'; wp_register_style( 'jquery-ui-core', "$url/core.css", [], '1.12.1' ); wp_register_style( 'jquery-ui-theme', "$url/theme.css", [], '1.12.1' ); wp_register_style( 'jquery-ui-datepicker', "$url/datepicker.css", ['jquery-ui-core', 'jquery-ui-theme'], '1.12.1' ); wp_register_style( 'jquery-ui-slider', "$url/slider.css", ['jquery-ui-core', 'jquery-ui-theme'], '1.12.1' ); // jQueryUI timepicker addon: https://github.com/trentrichardson/jQuery-Timepicker-Addon wp_register_style( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.css", ['rwmb-date', 'jquery-ui-slider'], '1.6.3' ); wp_register_style( 'rwmb-date', RWMB_CSS_URL . 'date.css', ['jquery-ui-datepicker'], RWMB_VER ); // Scripts. $url = RWMB_JS_URL . 'jqueryui'; wp_register_script( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.js", ['jquery-ui-datepicker', 'jquery-ui-slider'], '1.6.3', true ); wp_register_script( 'jquery-ui-timepicker-slider', "$url/jquery-ui-sliderAccess.js", ['jquery-ui-datepicker', 'jquery-ui-slider'], '0.3', true ); wp_register_script( 'jquery-ui-timepicker-i18n', "$url/jquery-ui-timepicker-addon-i18n.min.js", ['jquery-ui-timepicker'], '1.6.3', true ); wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', ['jquery-ui-datepicker', 'jquery-ui-timepicker-i18n', 'underscore', 'jquery-ui-button', 'jquery-ui-timepicker-slider'], RWMB_VER, true ); wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', ['jquery-ui-datepicker', 'underscore'], RWMB_VER, true ); wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', ['jquery-ui-timepicker-i18n', 'jquery-ui-button', 'jquery-ui-timepicker-slider'], RWMB_VER, true ); $handles = ['datetime', 'time']; $locale = str_replace( '_', '-', get_locale() ); $locale_short = substr( $locale, 0, 2 ); $data = array( 'locale' => $locale, 'localeShort' => $locale_short, ); foreach ( $handles as $handle ) { RWMB_Helpers_Field::localize_script_once( "rwmb-$handle", 'RWMB_' . ucfirst( $handle ), $data ); } } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { self::register_assets(); wp_enqueue_style( 'jquery-ui-timepicker' ); wp_enqueue_script( 'rwmb-datetime' ); } /** * Get field HTML. * * @param mixed $meta The field meta value. * @param array $field The field parameters. * * @return string */ public static function html( $meta, $field ) { $output = ''; if ( $field['timestamp'] ) { $name = $field['field_name']; $field = wp_parse_args( array( 'field_name' => $name . '[formatted]', ), $field ); $output .= sprintf( '<input type="hidden" name="%s" class="rwmb-datetime-timestamp" value="%s">', esc_attr( $name . '[timestamp]' ), isset( $meta['timestamp'] ) ? intval( $meta['timestamp'] ) : '' ); $meta = isset( $meta['formatted'] ) ? $meta['formatted'] : ''; } $output .= parent::html( $meta, $field ); if ( $field['inline'] ) { $output .= '<div class="rwmb-datetime-inline"></div>'; } return $output; } /** * Calculates the timestamp from the datetime string and returns it if $field['timestamp'] is set or the datetime string if not. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return string|int */ public static function value( $new, $old, $post_id, $field ) { if ( $field['timestamp'] ) { if ( is_array( $new ) ) { return $new['timestamp']; } elseif ( ! is_numeric( $new ) ) { return strtotime( $new ); } return $new; } if ( $field['save_format'] ) { $date = DateTime::createFromFormat( $field['php_format'], $new ); $new = false === $date ? $new : $date->format( $field['save_format'] ); } return $new; } /** * Get meta value. * * @param int $post_id The post ID. * @param bool $saved Whether the meta box is saved at least once. * @param array $field The field parameters. * * @return mixed */ public static function meta( $post_id, $saved, $field ) { $meta = parent::meta( $post_id, $saved, $field ); if ( $field['timestamp'] ) { return RWMB_Helpers_Array::map( $meta, __CLASS__ . '::from_timestamp', $field ); } if ( $field['save_format'] && $meta ) { return RWMB_Helpers_Array::map( $meta, __CLASS__ . '::from_save_format', $field ); } return $meta; } /** * Format meta value if set 'timestamp'. * * @param string $meta The meta value. * @param array $field Field parameters. * @return array */ public static function from_timestamp( $meta, $field ) { return array( 'timestamp' => $meta ? $meta : null, 'formatted' => $meta ? gmdate( $field['php_format'], intval( $meta ) ) : '', ); } /** * Transform meta value from save format to the JS format. * * @param string $meta The meta value. * @param array $field Field parameters. * @return array */ public static function from_save_format( $meta, $field ) { $date = DateTime::createFromFormat( $field['save_format'], $meta ); return false === $date ? $meta : $date->format( $field['php_format'] ); } /** * Normalize parameters for field. * * @param array $field The field parameters. * @return array */ public static function normalize( $field ) { $field = wp_parse_args( $field, array( 'timestamp' => false, 'inline' => false, 'js_options' => array(), 'save_format' => '', 'autocomplete' => 'off', ) ); // Deprecate 'format', but keep it for backward compatible. // Use 'js_options' instead. $field['js_options'] = wp_parse_args( $field['js_options'], array( 'timeFormat' => 'HH:mm', 'separator' => ' ', 'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'], 'showButtonPanel' => true, 'changeYear' => true, 'yearRange' => '-100:+100', 'changeMonth' => true, 'showButtonPanel' => true, 'oneLine' => true, 'controlType' => 'select', // select or slider 'addSliderAccess' => true, 'sliderAccessArgs' => [ 'touchonly' => true, // To show sliderAccess only on touch devices ], ) ); if ( $field['inline'] ) { $field['js_options'] = wp_parse_args( $field['js_options'], array( 'altFieldTimeOnly' => false, ) ); } $field['php_format'] = static::get_php_format( $field['js_options'] ); $field = parent::normalize( $field ); return $field; } /** * Get the attributes for a field. * * @param array $field The field parameters. * @param mixed $value The meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'data-options' => wp_json_encode( $field['js_options'] ), ) ); $attributes['type'] = 'text'; return $attributes; } /** * Returns a date() compatible format string from the JavaScript format. * * @link http://www.php.net/manual/en/function.date.php * @param array $js_options JavaScript options. * * @return string */ protected static function get_php_format( $js_options ) { return strtr( $js_options['dateFormat'], self::$date_formats ) . $js_options['separator'] . strtr( $js_options['timeFormat'], self::$time_formats ); } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { if ( $field['timestamp'] ) { $value = self::from_timestamp( $value, $field ); } else { $value = array( 'timestamp' => strtotime( $value ), 'formatted' => $value, ); } return empty( $args['format'] ) ? $value['formatted'] : gmdate( $args['format'], $value['timestamp'] ); } } fields/input-list.php 0000644 00000005202 15105434331 0010631 0 ustar 00 <?php /** * The input list field which displays choices in a list of inputs. * * @package Meta Box */ /** * Input list field class. */ class RWMB_Input_List_Field extends RWMB_Choice_Field { /** * Enqueue scripts and styles */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-input-list', RWMB_CSS_URL . 'input-list.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-input-list', RWMB_JS_URL . 'input-list.js', array(), RWMB_VER, true ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $options = self::transform_options( $field['options'] ); $walker = new RWMB_Walker_Input_List( $field, $meta ); $output = self::get_select_all_html( $field ); $output .= sprintf( '<ul class="rwmb-input-list%s%s">', $field['collapse'] ? ' rwmb-collapse' : '', $field['inline'] ? ' rwmb-inline' : '' ); $output .= $walker->walk( $options, $field['flatten'] ? -1 : 0 ); $output .= '</ul>'; return $output; } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field; $field = RWMB_Input_Field::normalize( $field ); $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'collapse' => true, 'inline' => null, 'select_all_none' => false, ) ); $field['flatten'] = $field['multiple'] ? $field['flatten'] : true; $field['inline'] = ! $field['multiple'] && ! isset( $field['inline'] ) ? true : $field['inline']; return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = RWMB_Input_Field::get_attributes( $field, $value ); $attributes['id'] = false; $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio'; $attributes['value'] = $value; return $attributes; } /** * Get html for select all|none for multiple checkbox. * * @param array $field Field parameters. * @return string */ public static function get_select_all_html( $field ) { if ( $field['multiple'] && $field['select_all_none'] ) { return sprintf( '<p class="rwmb-toggle-all-wrapper"><button class="rwmb-input-list-select-all-none button" data-name="%s">%s</button></p>', $field['id'], __( 'Toggle All', 'meta-box' ) ); } return ''; } } fields/osm.php 0000644 00000012076 15105434331 0007326 0 ustar 00 <?php /** * The Open Street Map field. * * @package Meta Box * @since 4.15.0 */ /** * Open Street Map field class. */ class RWMB_OSM_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { // Because map is a hosted service, it's ok to use hosted Leaflet scripts. wp_enqueue_style( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.css', array(), '1.5.1' ); wp_enqueue_script( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.js', array(), '1.5.1', true ); wp_enqueue_style( 'rwmb-osm', RWMB_CSS_URL . 'osm.css', array( 'leaflet' ), RWMB_VER ); wp_enqueue_script( 'rwmb-osm', RWMB_JS_URL . 'osm.js', array( 'jquery', 'jquery-ui-autocomplete', 'leaflet' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-osm', 'RWMB_Osm', array( 'no_results_string' => __( 'No results found', 'meta-box' ), ) ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $address = is_array( $field['address_field'] ) ? implode( ',', $field['address_field'] ) : $field['address_field']; $html = sprintf( '<div class="rwmb-osm-field" data-address-field="%s">', esc_attr( $address ) ); $attributes = self::get_attributes( $field, $meta ); $attributes['type'] = 'hidden'; $attributes['value'] = $meta; $html .= sprintf( '<div class="rwmb-osm-canvas" data-default-loc="%s" data-region="%s" data-language="%s"></div> <input %s>', esc_attr( $field['std'] ), esc_attr( $field['region'] ), esc_attr( $field['language'] ), self::render_attributes( $attributes ) ); $html .= '</div>'; return $html; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'std' => '', 'address_field' => '', 'language' => '', 'region' => '', ) ); return $field; } /** * Get the field value. * The difference between this function and 'meta' function is 'meta' function always returns the escaped value * of the field saved in the database, while this function returns more meaningful value of the field. * * @param array $field Field parameters. * @param array $args Not used for this field. * @param int|null $post_id Post ID. null for current post. Optional. * * @return mixed Array(latitude, longitude, zoom) */ public static function get_value( $field, $args = array(), $post_id = null ) { $value = parent::get_value( $field, $args, $post_id ); list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' ); return compact( 'latitude', 'longitude', 'zoom' ); } /** * Output the field value. * Display Open Street Map using Leaflet * * @param array $field Field parameters. * @param array $args Additional arguments for the map. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string HTML output of the field */ public static function the_value( $field, $args = array(), $post_id = null ) { $value = parent::get_value( $field, $args, $post_id ); return self::render_map( $value, $args ); } /** * Render a map in the frontend. * * @param array $location The [latitude, longitude[, zoom]] location. * @param array $args Additional arguments for the map. * * @return string */ public static function render_map( $location, $args = array() ) { list( $latitude, $longitude, $zoom ) = explode( ',', $location . ',,' ); if ( ! $latitude || ! $longitude ) { return ''; } $args = wp_parse_args( $args, array( 'latitude' => $latitude, 'longitude' => $longitude, 'width' => '100%', 'height' => '480px', 'marker' => true, // Display marker? 'marker_title' => '', // Marker title, when hover. 'info_window' => '', // Content of info window (when click on marker). HTML allowed. 'js_options' => array(), 'zoom' => $zoom, ) ); wp_enqueue_style( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.css', array(), '1.5.1' ); wp_enqueue_script( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.js', array(), '1.5.1', true ); wp_enqueue_script( 'rwmb-osm-frontend', RWMB_JS_URL . 'osm-frontend.js', array( 'jquery', 'leaflet' ), RWMB_VER, true ); /* * More Open Street Map options * @link https://leafletjs.com/reference-1.5.0.html#map-option */ $args['js_options'] = wp_parse_args( $args['js_options'], array( // Default to 'zoom' level set in admin, but can be overwritten. 'zoom' => $args['zoom'], ) ); $output = sprintf( '<div class="rwmb-osm-canvas" data-osm_options="%s" style="width:%s;height:%s"></div>', esc_attr( wp_json_encode( $args ) ), esc_attr( $args['width'] ), esc_attr( $args['height'] ) ); return $output; } } fields/user.php 0000644 00000011114 15105434331 0007476 0 ustar 00 <?php /** * The user select field. * * @package Meta Box */ /** * User field class. */ class RWMB_User_Field extends RWMB_Object_Choice_Field { /** * Add actions. */ public static function add_actions() { add_action( 'wp_ajax_rwmb_get_users', array( __CLASS__, 'ajax_get_users' ) ); add_action( 'wp_ajax_nopriv_rwmb_get_users', array( __CLASS__, 'ajax_get_users' ) ); add_action( 'clean_user_cache', array( __CLASS__, 'update_cache' ) ); } /** * Query users via ajax. */ public static function ajax_get_users() { check_ajax_referer( 'query' ); $request = rwmb_request(); $field = $request->filter_post( 'field', FILTER_DEFAULT, FILTER_FORCE_ARRAY ); // Required for 'choice_label' filter. See self::filter(). $field['clone'] = false; $field['_original_id'] = $field['id']; // Search. $term = $request->filter_post( 'term', FILTER_SANITIZE_STRING ); if ( $term ) { $field['query_args']['search'] = "*{$term}*"; } // Pagination. $limit = isset( $field['query_args']['number'] ) ? (int) $field['query_args']['number'] : 0; if ( $limit && 'query:append' === $request->filter_post( '_type', FILTER_SANITIZE_STRING ) ) { $field['query_args']['paged'] = $request->filter_post( 'page', FILTER_SANITIZE_NUMBER_INT ); } // Query the database. $items = self::query( null, $field ); $items = array_values( $items ); $data = array( 'items' => $items ); // More items for pagination. if ( $limit && count( $items ) === $limit ) { $data['more'] = true; } wp_send_json_success( $data ); } /** * Update object cache to make sure query method below always get the fresh list of users. * Unlike posts and terms, WordPress doesn't set 'last_changed' for users. * So we have to do it ourselves. * * @see clean_post_cache() */ public static function update_cache() { wp_cache_set( 'last_changed', microtime(), 'users' ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { // Set default field args. $field = wp_parse_args( $field, array( 'placeholder' => __( 'Select an user', 'meta-box' ), 'query_args' => array(), 'display_field' => 'display_name', ) ); $field = parent::normalize( $field ); // Set default query args. $limit = $field['ajax'] ? 10 : 0; $field['query_args'] = wp_parse_args( $field['query_args'], array( 'number' => $limit, ) ); parent::set_ajax_params( $field ); if ( $field['ajax'] ) { $field['js_options']['ajax_data']['field']['display_field'] = $field['display_field']; } return $field; } /** * Query users for field options. * * @param array $meta Saved meta value. * @param array $field Field settings. * @return array Field options array. */ public static function query( $meta, $field ) { $display_field = $field['display_field']; $args = wp_parse_args( $field['query_args'], array( 'orderby' => $display_field, 'order' => 'asc', ) ); // Query only selected items. if ( ! empty( $field['ajax'] ) && ! empty( $meta ) ) { $args['include'] = $meta; } // Get from cache to prevent same queries. $last_changed = wp_cache_get_last_changed( 'users' ); $key = md5( serialize( $args ) ); $cache_key = "$key:$last_changed"; $options = wp_cache_get( $cache_key, 'meta-box-user-field' ); if ( false !== $options ) { return $options; } $users = get_users( $args ); $options = array(); foreach ( $users as $user ) { $label = $user->$display_field ? $user->$display_field : __( '(No title)', 'meta-box' ); $label = self::filter( 'choice_label', $label, $field, $user ); $options[ $user->ID ] = array( 'value' => $user->ID, 'label' => $label, ); } // Cache the query. wp_cache_set( $cache_key, $options, 'meta-box-user-field' ); return $options; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $display_field = $field['display_field']; $user = get_userdata( $value ); return '<a href="' . esc_url( get_author_posts_url( $value ) ) . '">' . esc_html( $user->$display_field ) . '</a>'; } } fields/input.php 0000644 00000006053 15105434331 0007665 0 ustar 00 <?php /** * The abstract input field which is used for all <input> fields. * * @package Meta Box */ /** * Abstract input field class. */ abstract class RWMB_Input_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-input', RWMB_CSS_URL . 'input.css', '', RWMB_VER ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $output = ''; if ( $field['prepend'] || $field['append'] ) { $output = '<div class="rwmb-input-group">'; } if ( $field['prepend'] ) { $output .= '<span class="rwmb-input-group-text">' . $field['prepend'] . '</span>'; } $attributes = self::call( 'get_attributes', $field, $meta ); $output .= sprintf( '<input %s>%s', self::render_attributes( $attributes ), self::datalist( $field ) ); if ( $field['append'] ) { $output .= '<span class="rwmb-input-group-text">' . $field['append']. '</span>'; } if ( $field['prepend'] || $field['append'] ) { $output .= '</div>'; } return $output; } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field = wp_parse_args( $field, array( 'autocomplete' => false, 'datalist' => false, 'readonly' => false, 'maxlength' => false, 'pattern' => false, 'prepend' => '', 'append' => '', ) ); if ( $field['datalist'] ) { $field['datalist'] = wp_parse_args( $field['datalist'], array( 'id' => $field['id'] . '_list', 'options' => array(), ) ); } return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes = wp_parse_args( $attributes, array( 'autocomplete' => $field['autocomplete'], 'list' => $field['datalist'] ? $field['datalist']['id'] : false, 'readonly' => $field['readonly'], 'maxlength' => $field['maxlength'], 'pattern' => $field['pattern'], 'value' => $value, 'placeholder' => $field['placeholder'], 'type' => $field['type'], ) ); if ( isset( $field['size'] ) ) { $attributes['size'] = $field['size']; } return $attributes; } /** * Create datalist, if any. * * @param array $field Field parameters. * @return string */ protected static function datalist( $field ) { if ( empty( $field['datalist'] ) ) { return ''; } $datalist = $field['datalist']; $html = sprintf( '<datalist id="%s">', $datalist['id'] ); foreach ( $datalist['options'] as $option ) { $html .= sprintf( '<option value="%s"></option>', $option ); } $html .= '</datalist>'; return $html; } } fields/image-select.php 0000644 00000004557 15105434331 0011074 0 ustar 00 <?php /** * The image select field which behaves similar to the radio field but uses images as options. * * @package Meta Box */ /** * The image select field class. */ class RWMB_Image_Select_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-image-select', RWMB_CSS_URL . 'image-select.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-image-select', RWMB_JS_URL . 'image-select.js', array( 'jquery' ), RWMB_VER, true ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $html = array(); $meta = (array) $meta; foreach ( $field['options'] as $value => $image ) { $attributes = self::get_attributes( $field, $value ); $html[] = sprintf( '<label class="rwmb-image-select"><img src="%s"><input %s%s></label>', $image, self::render_attributes( $attributes ), checked( in_array( $value, $meta ), true, false ) ); } return implode( ' ', $html ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field['field_name'] .= $field['multiple'] ? '[]' : ''; return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes['id'] = false; $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio'; $attributes['value'] = $value; return $attributes; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return $value ? sprintf( '<img src="%s">', esc_url( $field['options'][ $value ] ) ) : ''; } } fields/background.php 0000644 00000012745 15105434331 0010652 0 ustar 00 <?php /** * The background field. * * @package Meta Box */ /** * The Background field. */ class RWMB_Background_Field extends RWMB_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-background', RWMB_CSS_URL . 'background.css', '', RWMB_VER ); $args = func_get_args(); $field = reset( $args ); $color = RWMB_Color_Field::normalize( array( 'type' => 'color', 'id' => "{$field['id']}_color", 'field_name' => "{$field['field_name']}[color]", 'alpha_channel' => true, ) ); RWMB_Color_Field::admin_enqueue_scripts( $color ); RWMB_File_Input_Field::admin_enqueue_scripts(); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field settings. * * @return string */ public static function html( $meta, $field ) { $meta = wp_parse_args( $meta, array( 'color' => '', 'image' => '', 'repeat' => '', 'attachment' => '', 'position' => '', 'size' => '', ) ); $output = '<div class="rwmb-background-row">'; // Color. $color = RWMB_Color_Field::normalize( array( 'type' => 'color', 'id' => "{$field['id']}_color", 'field_name' => "{$field['field_name']}[color]", 'alpha_channel' => true, ) ); $output .= RWMB_Color_Field::html( $meta['color'], $color ); $output .= '</div><!-- .rwmb-background-row -->'; $output .= '<div class="rwmb-background-row">'; // Image. $image = RWMB_File_Input_Field::normalize( array( 'type' => 'file_input', 'id' => "{$field['id']}_image", 'field_name' => "{$field['field_name']}[image]", 'placeholder' => __( 'Background Image', 'meta-box' ), ) ); $output .= RWMB_File_Input_Field::html( $meta['image'], $image ); $output .= '</div><!-- .rwmb-background-row -->'; $output .= '<div class="rwmb-background-row">'; // Repeat. $repeat = RWMB_Select_Field::normalize( array( 'type' => 'select', 'id' => "{$field['id']}_repeat", 'field_name' => "{$field['field_name']}[repeat]", 'placeholder' => esc_html__( '-- Repeat --', 'meta-box' ), 'options' => array( 'no-repeat' => esc_html__( 'No Repeat', 'meta-box' ), 'repeat' => esc_html__( 'Repeat All', 'meta-box' ), 'repeat-x' => esc_html__( 'Repeat Horizontally', 'meta-box' ), 'repeat-y' => esc_html__( 'Repeat Vertically', 'meta-box' ), 'inherit' => esc_html__( 'Inherit', 'meta-box' ), ), ) ); $output .= RWMB_Select_Field::html( $meta['repeat'], $repeat ); // Position. $position = RWMB_Select_Field::normalize( array( 'type' => 'select', 'id' => "{$field['id']}_position", 'field_name' => "{$field['field_name']}[position]", 'placeholder' => esc_html__( '-- Position --', 'meta-box' ), 'options' => array( 'top left' => esc_html__( 'Top Left', 'meta-box' ), 'top center' => esc_html__( 'Top Center', 'meta-box' ), 'top right' => esc_html__( 'Top Right', 'meta-box' ), 'center left' => esc_html__( 'Center Left', 'meta-box' ), 'center center' => esc_html__( 'Center Center', 'meta-box' ), 'center right' => esc_html__( 'Center Right', 'meta-box' ), 'bottom left' => esc_html__( 'Bottom Left', 'meta-box' ), 'bottom center' => esc_html__( 'Bottom Center', 'meta-box' ), 'bottom right' => esc_html__( 'Bottom Right', 'meta-box' ), ), ) ); $output .= RWMB_Select_Field::html( $meta['position'], $position ); // Attachment. $attachment = RWMB_Select_Field::normalize( array( 'type' => 'select', 'id' => "{$field['id']}_attachment", 'field_name' => "{$field['field_name']}[attachment]", 'placeholder' => esc_html__( '-- Attachment --', 'meta-box' ), 'options' => array( 'fixed' => esc_html__( 'Fixed', 'meta-box' ), 'scroll' => esc_html__( 'Scroll', 'meta-box' ), 'inherit' => esc_html__( 'Inherit', 'meta-box' ), ), ) ); $output .= RWMB_Select_Field::html( $meta['attachment'], $attachment ); // Size. $size = RWMB_Select_Field::normalize( array( 'type' => 'select', 'id' => "{$field['id']}_size", 'field_name' => "{$field['field_name']}[size]", 'placeholder' => esc_html__( '-- Size --', 'meta-box' ), 'options' => array( 'inherit' => esc_html__( 'Inherit', 'meta-box' ), 'cover' => esc_html__( 'Cover', 'meta-box' ), 'contain' => esc_html__( 'Contain', 'meta-box' ), ), ) ); $output .= RWMB_Select_Field::html( $meta['size'], $size ); $output .= '</div><!-- .rwmb-background-row -->'; return $output; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param array $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { if ( empty( $value ) ) { return ''; } $output = ''; $value = array_filter( $value ); foreach ( $value as $key => $subvalue ) { $subvalue = 'image' === $key ? 'url(' . esc_url( $subvalue ) . ')' : $subvalue; $output .= 'background-' . $key . ': ' . $subvalue . ';'; } return $output; } } fields/select-tree.php 0000644 00000003011 15105434331 0010731 0 ustar 00 <?php /** * The select tree field. * * @package Meta Box */ /** * Select tree field class. */ class RWMB_Select_Tree_Field extends RWMB_Select_Advanced_Field { /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * @return string */ public static function html( $meta, $field ) { $options = self::transform_options( $field['options'] ); $walker = new RWMB_Walker_Select_Tree( $field, $meta ); return $options ? $walker->walk( $options ) : ''; } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_style( 'rwmb-select-tree', RWMB_CSS_URL . 'select-tree.css', array( 'rwmb-select' ), RWMB_VER ); wp_enqueue_script( 'rwmb-select-tree', RWMB_JS_URL . 'select-tree.js', array( 'rwmb-select' ), RWMB_VER, true ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field['multiple'] = true; $field['size'] = 0; $field = parent::normalize( $field ); return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes['multiple'] = false; $attributes['id'] = false; return $attributes; } } fields/fieldset-text.php 0000644 00000006426 15105434331 0011313 0 ustar 00 <?php /** * The text fieldset field, which allows users to enter content for a list of text fields. * * @package Meta Box */ /** * Fieldset text class. */ class RWMB_Fieldset_Text_Field extends RWMB_Input_Field { /** * Enqueue field scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-fieldset-text', RWMB_CSS_URL . 'fieldset-text.css', '', RWMB_VER ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $html = array(); $tpl = '<p><label>%s</label> %s</p>'; foreach ( $field['options'] as $key => $label ) { $value = isset( $meta[ $key ] ) ? $meta[ $key ] : ''; $field['attributes']['name'] = $field['field_name'] . "[{$key}]"; $html[] = sprintf( $tpl, $label, parent::html( $value, $field ) ); } $out = '<fieldset>' . ( $field['desc'] ? '<legend>' . $field['desc'] . '</legend>' : '' ) . implode( ' ', $html ) . '</fieldset>'; return $out; } /** * Do not show field description. * * @param array $field Field parameters. * * @return string */ public static function input_description( $field ) { return ''; } /** * Do not show field description. * * @param array $field Field parameters. * * @return string */ public static function label_description( $field ) { return ''; } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field['multiple'] = false; $field['attributes']['id'] = false; $field['attributes']['type'] = 'text'; return $field; } /** * Format value for the helper functions. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_value( $field, $value, $args, $post_id ) { $output = '<table><thead><tr>'; foreach ( $field['options'] as $label ) { $output .= "<th>$label</th>"; } $output .= '</tr></thead></tbody>'; if ( ! $field['clone'] ) { $output .= self::format_single_value( $field, $value, $args, $post_id ); } else { foreach ( $value as $subvalue ) { $output .= self::format_single_value( $field, $subvalue, $args, $post_id ); } } $output .= '</tbody></table>'; return $output; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param array $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { $output = '<tr>'; foreach ( $value as $subvalue ) { $output .= "<td>$subvalue</td>"; } $output .= '</tr>'; return $output; } } fields/video.php 0000644 00000010056 15105434331 0007632 0 ustar 00 <?php /** * Video field which uses WordPress media popup to upload and select video. * * @package Meta Box * @since 4.10 */ /** * The video field class. */ class RWMB_Video_Field extends RWMB_Media_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::admin_enqueue_scripts(); wp_enqueue_style( 'rwmb-video', RWMB_CSS_URL . 'video.css', array( 'rwmb-media' ), RWMB_VER ); wp_enqueue_script( 'rwmb-video', RWMB_JS_URL . 'video.js', array( 'rwmb-media' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-video', 'i18nRwmbVideo', array( 'extensions' => wp_get_video_extensions(), ) ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * * @return array */ public static function normalize( $field ) { $field['mime_type'] = 'video'; $field = parent::normalize( $field ); return $field; } /** * Get uploaded file information. * * @param int $file_id Attachment image ID (post ID). Required. * @param array $args Array of arguments (for size). * @param array $field Field settings. * * @return array|bool False if file not found. Array of image info on success. */ public static function file_info( $file_id, $args = array(), $field = array() ) { if ( ! get_attached_file( $file_id ) ) { return false; } $attachment = get_post( $file_id ); $url = wp_get_attachment_url( $attachment->ID ); $file_type = wp_check_filetype( $url, wp_get_mime_types() ); $data = array( 'ID' => $file_id, 'src' => $url, 'type' => $file_type['type'], 'title' => $attachment->post_title, 'caption' => $attachment->post_excerpt, 'description' => $attachment->post_content, ); $data['meta'] = array(); $meta = wp_get_attachment_metadata( $attachment->ID ); if ( ! empty( $meta ) ) { foreach ( wp_get_attachment_id3_keys( $attachment ) as $key => $label ) { if ( ! empty( $meta[ $key ] ) ) { $data['meta'][ $key ] = $meta[ $key ]; } } if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) { $data['dimensions'] = array( 'width' => $meta['width'], 'height' => $meta['height'], ); } else { $data['dimensions'] = array( 'width' => 640, 'height' => 360, ); } } $thumb_id = get_post_thumbnail_id( $attachment->ID ); if ( ! empty( $thumb_id ) ) { list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'full' ); $data['image'] = compact( 'src', 'width', 'height' ); list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'thumbnail' ); $data['thumb'] = compact( 'src', 'width', 'height' ); } else { $src = wp_mime_type_icon( $attachment->ID ); $width = 48; $height = 64; $data['image'] = compact( 'src', 'width', 'height' ); $data['thumb'] = compact( 'src', 'width', 'height' ); } return $data; } /** * Format value for a clone. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_clone_value( $field, $value, $args, $post_id ) { $ids = implode( ',', wp_list_pluck( $value, 'ID' ) ); // Display single video. if ( 1 === count( $value ) ) { $video = reset( $value ); return wp_video_shortcode( array( 'src' => $video['src'], 'width' => $video['dimensions']['width'], 'height' => $video['dimensions']['height'], ) ); } // Display multiple videos in a playlist. return wp_playlist_shortcode( array( 'ids' => $ids, 'type' => 'video', ) ); } /** * Template for media item. */ public static function print_templates() { parent::print_templates(); require_once RWMB_INC_DIR . 'templates/video.php'; } } fields/file-input.php 0000644 00000003231 15105434331 0010575 0 ustar 00 <?php /** * The file input field which allows users to enter a file URL or select it from the Media Library. * * @package Meta Box */ /** * File input field class which uses an input for file URL. */ class RWMB_File_Input_Field extends RWMB_Input_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { wp_enqueue_media(); wp_enqueue_style( 'rwmb-file-input', RWMB_CSS_URL . 'file-input.css', array(), RWMB_VER ); wp_enqueue_script( 'rwmb-file-input', RWMB_JS_URL . 'file-input.js', array( 'jquery' ), RWMB_VER, true ); RWMB_Helpers_Field::localize_script_once( 'rwmb-file-input', 'rwmbFileInput', array( 'frameTitle' => esc_html__( 'Select File', 'meta-box' ), ) ); } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { $attributes = self::get_attributes( $field, $meta ); return sprintf( '<div class="rwmb-file-input-inner"> <input %s> <a href="#" class="rwmb-file-input-select button">%s</a> <a href="#" class="rwmb-file-input-remove button %s">%s</a> </div>', self::render_attributes( $attributes ), esc_html__( 'Select', 'meta-box' ), $meta ? '' : 'hidden', esc_html__( 'Remove', 'meta-box' ) ); } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = parent::get_attributes( $field, $value ); $attributes['type'] = 'text'; return $attributes; } } fields/date.php 0000644 00000001337 15105434331 0007443 0 ustar 00 <?php /** * The date picker field, which uses built-in jQueryUI date picker widget. * * @package Meta Box */ /** * Date field class. */ class RWMB_Date_Field extends RWMB_Datetime_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::register_assets(); wp_enqueue_style( 'rwmb-date' ); wp_enqueue_script( 'rwmb-date' ); } /** * Returns a date() compatible format string from the JavaScript format. * * @link http://www.php.net/manual/en/function.date.php * @param array $js_options JavaScript options. * * @return string */ public static function get_php_format( $js_options ) { return strtr( $js_options['dateFormat'], self::$date_formats ); } } fields/time.php 0000644 00000001321 15105434331 0007455 0 ustar 00 <?php /** * The time picker field. * * @package Meta Box */ /** * Time field class. */ class RWMB_Time_Field extends RWMB_Datetime_Field { /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { parent::register_assets(); wp_enqueue_style( 'jquery-ui-timepicker' ); wp_enqueue_script( 'rwmb-time' ); } /** * Normalize parameters for field. * * @param array $field Field parameters. * @return array */ public static function normalize( $field ) { $field = parent::normalize( $field ); $field['js_options']['timeFormat'] = empty( $field['format'] ) ? $field['js_options']['timeFormat'] : $field['format']; return $field; } } autoloader.php 0000644 00000003521 15105434331 0007414 0 ustar 00 <?php /** * Autoload plugin classes. * * @package Meta Box */ /** * Autoload class */ class RWMB_Autoloader { /** * List of directories to load classes. * * @var array */ protected $dirs = array(); /** * Adds a base directory for a class name prefix and/or suffix. * * @param string $dir A base directory for class files. * @param string $prefix The class name prefix. * @param string $suffix The class name suffix. */ public function add( $dir, $prefix, $suffix = '' ) { $this->dirs[] = array( 'dir' => trailingslashit( $dir ), 'prefix' => $prefix, 'suffix' => $suffix, ); } /** * Register autoloader for plugin classes. */ public function register() { spl_autoload_register( array( $this, 'autoload' ) ); } /** * Autoload classes. * * @param string $class Class name. */ public function autoload( $class ) { foreach ( $this->dirs as $dir ) { if ( ( $dir['prefix'] && 0 !== strpos( $class, $dir['prefix'] ) ) || ( $dir['suffix'] && substr( $class, - strlen( $dir['suffix'] ) ) !== $dir['suffix'] ) ) { continue; } $file = substr( $class, strlen( $dir['prefix'] ) ); if ( $dir['suffix'] && strlen( $file ) > strlen( $dir['suffix'] ) ) { $file = substr( $file, 0, - strlen( $dir['suffix'] ) ); } if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) { $file = mb_strtolower( str_replace( '_', '-', $file ), mb_detect_encoding( $file ) ) . '.php'; } else { $file = strtolower( str_replace( '_', '-', $file ) ) . '.php'; } $file = $dir['dir'] . $file; $this->require_file( $file ); } } /** * If a file exists, require it from the file system. * * @param string $file The file to require. */ protected function require_file( $file ) { if ( file_exists( $file ) ) { require_once $file; } } } helpers/field.php 0000644 00000002677 15105434331 0010015 0 ustar 00 <?php /** * Field helper functions. * * @package Meta Box */ /** * Field helper class. * * @package Meta Box */ class RWMB_Helpers_Field { /** * Localize a script only once. * * @link https://github.com/rilwis/meta-box/issues/850 * * @param string $handle Script handle. * @param string $name Object name. * @param array $data Localized data. */ public static function localize_script_once( $handle, $name, $data ) { if ( ! wp_scripts()->get_data( $handle, 'data' ) ) { wp_localize_script( $handle, $name, $data ); } } public static function add_inline_script_once( $handle, $text ) { if ( ! wp_scripts()->get_data( $handle, 'after' ) ) { wp_add_inline_script( $handle, $text ); } } /** * Get field class name. * * @param array $field Field settings. * @return string */ public static function get_class( $field ) { $type = self::get_type( $field ); $class = 'RWMB_' . RWMB_Helpers_String::title_case( $type ) . '_Field'; return class_exists( $class ) ? $class : 'RWMB_Input_Field'; } /** * Get field type. * * @param array $field Field settings. * @return string */ private static function get_type( $field ) { $type = isset( $field['type'] ) ? $field['type'] : 'text'; $map = array_merge( array( $type => $type, ), array( 'file_advanced' => 'media', 'plupload_image' => 'image_upload', 'url' => 'text', ) ); return $map[ $type ]; } } helpers/value.php 0000644 00000001245 15105434331 0010034 0 ustar 00 <?php /** * Helper functions for checking values. * * @package Meta Box */ /** * Helper class for checking values. * * @package Meta Box */ class RWMB_Helpers_Value { /** * Check if a value is valid for field (not empty "WordPress way"), e.g. equals to empty string or array. * * @param mixed $value Input value. * @return bool */ public static function is_valid_for_field( $value ) { return '' !== $value && array() !== $value; } /** * Check if a value is valid for attribute. * * @param mixed $value Input value. * @return bool */ public static function is_valid_for_attribute( $value ) { return '' !== $value && false !== $value; } } helpers/array.php 0000644 00000003455 15105434331 0010043 0 ustar 00 <?php /** * Array helper functions. * * @package Meta Box */ /** * Array helper class. * * @package Meta Box */ class RWMB_Helpers_Array { /** * New array map function that accepts more params than just values. * Params: array|item, callback, other params. * * @return array */ public static function map() { $args = func_get_args(); $items = array_shift( $args ); $callback = array_shift( $args ); if ( ! is_array( $items ) ) { array_unshift( $args, $items ); return call_user_func_array( $callback, $args ); } return array_map( function( $item ) use ( $callback, $args ) { array_unshift( $args, $item ); return call_user_func_array( $callback, $args ); }, $items ); } /** * Convert a comma separated string to array. * * @param string $csv Comma separated string. * @return array */ public static function from_csv( $csv ) { return is_array( $csv ) ? $csv : array_filter( array_map( 'trim', explode( ',', $csv . ',' ) ) ); } /** * Change array key. * * @param array $array Input array. * @param string $from From key. * @param string $to To key. */ public static function change_key( &$array, $from, $to ) { if ( isset( $array[ $from ] ) ) { $array[ $to ] = $array[ $from ]; } unset( $array[ $from ] ); } /** * Flatten an array. * * @link https://stackoverflow.com/a/1320156/371240 * * @param array $array Input array. * @return array */ public static function flatten( $array ) { $return = array(); array_walk_recursive( $array, function( $a ) use ( &$return ) { $return[] = $a; } ); return $return; } /** * Ensure a variable is an array. * @param mixed $input Input value. * @return array */ public static function ensure( $input ) { return (array) $input; } } helpers/string.php 0000644 00000000677 15105434331 0010236 0 ustar 00 <?php /** * String helper functions. * * @package Meta Box */ /** * String helper class. * * @package Meta Box */ class RWMB_Helpers_String { /** * Convert text to Title_Case. * * @param string $text Input text. * @return string */ public static function title_case( $text ) { $text = str_replace( array( '-', '_' ), ' ', $text ); $text = ucwords( $text ); $text = str_replace( ' ', '_', $text ); return $text; } } interfaces/storage.php 0000644 00000000612 15105434331 0011042 0 ustar 00 <?php /** * Storage interface * * @package Meta Box */ /** * Interface RWMB_Storage_Interface */ interface RWMB_Storage_Interface { /** * Get value from storage. * * @param int $object_id Object id. * @param string $name Field name. * @param array $args Custom arguments.. * @return mixed */ public function get( $object_id, $name, $args = array() ); } field.php 0000644 00000043053 15105434331 0006344 0 ustar 00 <?php /** * The field base class. * This is the parent class of all custom fields defined by the plugin, which defines all the common methods. * Fields must inherit this class and overwrite methods with its own. * * @package Meta Box */ /** * The field base class. */ abstract class RWMB_Field { /** * Add actions. */ public static function add_actions() { } /** * Enqueue scripts and styles. */ public static function admin_enqueue_scripts() { } /** * 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 Field parameters. * @param bool $saved Whether the meta box is saved at least once. * @param int $post_id Post ID. */ public static function show( $field, $saved, $post_id = 0 ) { $meta = self::call( $field, 'meta', $post_id, $saved ); $meta = self::filter( 'field_meta', $meta, $field, $saved ); $begin = self::call( $field, 'begin_html', $meta ); $begin = self::filter( 'begin_html', $begin, $field, $meta ); // Separate code for cloneable and non-cloneable fields to make easy to maintain. if ( $field['clone'] ) { $field_html = RWMB_Clone::html( $meta, $field ); } else { // Call separated methods for displaying each type of field. $field_html = self::call( $field, 'html', $meta ); $field_html = self::filter( 'html', $field_html, $field, $meta ); } $end = self::call( $field, 'end_html', $meta ); $end = self::filter( 'end_html', $end, $field, $meta ); $html = self::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 ( ! empty( $field['required'] ) ) { $classes .= ' required'; } $outer_html = sprintf( $field['before'] . '<div class="%s">%s</div>' . $field['after'], esc_attr( trim( $classes ) ), $html ); $outer_html = self::filter( 'outer_html', $outer_html, $field, $meta ); echo $outer_html; // WPCS: XSS OK. } /** * Get field HTML. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function html( $meta, $field ) { return ''; } /** * Show begin HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function begin_html( $meta, $field ) { $field_label = ''; if ( $field['name'] ) { $field_label = sprintf( '<div class="rwmb-label"> <label for="%s">%s%s</label> %s </div>', esc_attr( $field['id'] ), $field['name'], $field['required'] || ! empty( $field['attributes']['required'] ) ? '<span class="rwmb-required">*</span>' : '', self::label_description( $field ) ); } $data_max_clone = is_numeric( $field['max_clone'] ) && $field['max_clone'] > 1 ? ' data-max-clone=' . $field['max_clone'] : ''; $input_open = sprintf( '<div class="rwmb-input"%s>', $data_max_clone ); return $field_label . $input_open; } /** * Show end HTML markup for fields. * * @param mixed $meta Meta value. * @param array $field Field parameters. * * @return string */ public static function end_html( $meta, $field ) { return RWMB_Clone::add_clone_button( $field ) . self::call( 'input_description', $field ) . '</div>'; } /** * Display field label description. * * @param array $field Field parameters. * @return string */ protected static function label_description( $field ) { $id = $field['id'] ? ' id="' . esc_attr( $field['id'] ) . '-label-description"' : ''; return $field['label_description'] ? "<p{$id} class='description'>{$field['label_description']}</p>" : ''; } /** * Display field description. * * @param array $field Field parameters. * @return string */ protected static function input_description( $field ) { $id = $field['id'] ? ' id="' . esc_attr( $field['id'] ) . '-description"' : ''; return $field['desc'] ? "<p{$id} class='description'>{$field['desc']}</p>" : ''; } /** * Get raw meta value. * * @param int $object_id Object ID. * @param array $field Field parameters. * @param array $args Arguments of {@see rwmb_meta()} helper. * * @return mixed */ public static function raw_meta( $object_id, $field, $args = array() ) { if ( empty( $field['id'] ) ) { return ''; } if ( isset( $field['storage'] ) ) { $storage = $field['storage']; } elseif ( isset( $args['object_type'] ) ) { $storage = rwmb_get_storage( $args['object_type'] ); } else { $storage = rwmb_get_storage( 'post' ); } if ( ! isset( $args['single'] ) ) { $args['single'] = $field['clone'] || ! $field['multiple']; } if ( $field['clone'] && $field['clone_as_multiple'] ) { $args['single'] = false; } $value = $storage->get( $object_id, $field['id'], $args ); $value = self::filter( 'raw_meta', $value, $field, $object_id, $args ); return $value; } /** * Get meta value. * * @param int $post_id Post ID. * @param bool $saved Whether the meta box is saved at least once. * @param array $field Field parameters. * * @return mixed */ public static function meta( $post_id, $saved, $field ) { /** * For special fields like 'divider', 'heading' which don't have ID, just return empty string * to prevent notice error when displaying fields. */ if ( empty( $field['id'] ) ) { return ''; } // Get raw meta. $meta = self::call( $field, 'raw_meta', $post_id ); // Use $field['std'] only when the meta box hasn't been saved (i.e. the first time we run). $meta = ! $saved || ! $field['save_field'] ? $field['std'] : $meta; if ( $field['clone'] ) { $meta = RWMB_Helpers_Array::ensure( $meta ); // Ensure $meta is an array with values so that the foreach loop in self::show() runs properly. if ( empty( $meta ) ) { $meta = array( '' ); } if ( $field['multiple'] ) { $first = reset( $meta ); // If users set std for a cloneable checkbox list field in the Builder, they can only set [value1, value2]. We need to transform it to [[value1, value2]]. // In other cases, make sure each value is an array. $meta = is_array( $first ) ? array_map( 'RWMB_Helpers_Array::ensure', $meta ) : array( $meta ); } } elseif ( $field['multiple'] ) { $meta = RWMB_Helpers_Array::ensure( $meta ); } return $meta; } /** * Process the submitted value before saving into the database. * * @param mixed $value The submitted value. * @param int $object_id The object ID. * @param array $field The field settings. */ public static function process_value( $value, $object_id, $field ) { $old_value = self::call( $field, 'raw_meta', $object_id ); // Allow field class change the value. if ( $field['clone'] ) { $value = RWMB_Clone::value( $value, $old_value, $object_id, $field ); } else { $value = self::call( $field, 'value', $value, $old_value, $object_id ); $value = self::filter( 'sanitize', $value, $field, $old_value, $object_id ); } $value = self::filter( 'value', $value, $field, $old_value, $object_id ); return $value; } /** * Set value of meta before saving into database. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. * * @return mixed */ public static function value( $new, $old, $post_id, $field ) { return $new; } /** * Save meta value. * * @param mixed $new The submitted meta value. * @param mixed $old The existing meta value. * @param int $post_id The post ID. * @param array $field The field parameters. */ public static function save( $new, $old, $post_id, $field ) { if ( empty( $field['id'] ) || ! $field['save_field'] ) { return; } $name = $field['id']; $storage = $field['storage']; // Remove post meta if it's empty. if ( ! RWMB_Helpers_Value::is_valid_for_field( $new ) ) { $storage->delete( $post_id, $name ); return; } // If field is cloneable AND not force to save as multiple rows, value is saved as a single row in the database. if ( $field['clone'] && ! $field['clone_as_multiple'] ) { $storage->update( $post_id, $name, $new ); return; } // Save cloned fields as multiple values instead serialized array. if ( ( $field['clone'] && $field['clone_as_multiple'] ) || $field['multiple'] ) { $storage->delete( $post_id, $name ); $new = (array) $new; foreach ( $new as $new_value ) { $storage->add( $post_id, $name, $new_value, false ); } return; } // Default: just update post meta. $storage->update( $post_id, $name, $new ); } /** * Normalize parameters for field. * * @param array|string $field Field settings. * @return array */ public static function normalize( $field ) { // Quick define text fields with "name" attribute only. if ( is_string( $field ) ) { $field = array( 'name' => $field, 'id' => sanitize_key( $field ), ); } $field = wp_parse_args( $field, array( 'id' => '', 'name' => '', 'type' => 'text', 'label_description' => '', 'multiple' => false, 'std' => '', 'desc' => '', 'format' => '', 'before' => '', 'after' => '', 'field_name' => isset( $field['id'] ) ? $field['id'] : '', 'placeholder' => '', 'save_field' => true, 'clone' => false, 'max_clone' => 0, 'sort_clone' => false, 'add_button' => __( '+ Add more', 'meta-box' ), 'clone_default' => false, 'clone_as_multiple' => false, 'class' => '', 'disabled' => false, 'required' => false, 'autofocus' => false, 'attributes' => array(), 'sanitize_callback' => null, ) ); // Store the original ID to run correct filters for the clonable field. if ( $field['clone'] ) { $field['_original_id'] = $field['id']; } if ( $field['clone_default'] ) { $field['attributes'] = wp_parse_args( $field['attributes'], array( 'data-default' => $field['std'], 'data-clone-default' => 'true', ) ); } if ( 1 === $field['max_clone'] ) { $field['clone'] = false; } return $field; } /** * Get the attributes for a field. * * @param array $field Field parameters. * @param mixed $value Meta value. * * @return array */ public static function get_attributes( $field, $value = null ) { $attributes = wp_parse_args( $field['attributes'], array( 'disabled' => $field['disabled'], 'autofocus' => $field['autofocus'], 'required' => $field['required'], 'id' => $field['id'], 'class' => '', 'name' => $field['field_name'], ) ); $attributes['class'] = trim( implode( ' ', array_merge( array( "rwmb-{$field['type']}" ), (array) $attributes['class'] ) ) ); return $attributes; } /** * Renders an attribute array into an html attributes string. * * @param array $attributes HTML attributes. * * @return string */ public static function render_attributes( $attributes ) { $output = ''; $attributes = array_filter( $attributes, 'RWMB_Helpers_Value::is_valid_for_attribute' ); foreach ( $attributes as $key => $value ) { if ( is_array( $value ) ) { $value = wp_json_encode( $value ); } $output .= sprintf( ' %s="%s"', $key, esc_attr( $value ) ); } return $output; } /** * Get the field value. * The difference between this function and 'meta' function is 'meta' function always returns the escaped value * of the field saved in the database, while this function returns more meaningful value of the field, for ex.: * for file/image: return array of file/image information instead of file/image IDs. * * Each field can extend this function and add more data to the returned value. * See specific field classes for details. * * @param array $field Field parameters. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return mixed Field value */ public static function get_value( $field, $args = array(), $post_id = null ) { // Some fields does not have ID like heading, custom HTML, etc. if ( empty( $field['id'] ) ) { return ''; } if ( ! $post_id ) { $post_id = get_the_ID(); } // Get raw meta value in the database, no escape. $value = self::call( $field, 'raw_meta', $post_id, $args ); // Make sure meta value is an array for cloneable and multiple fields. if ( $field['clone'] || $field['multiple'] ) { $value = is_array( $value ) && $value ? $value : array(); } return $value; } /** * Output the field value. * Depends on field value and field types, each field can extend this method to output its value in its own way * See specific field classes for details. * * Note: we don't echo the field value directly. We return the output HTML of field, which will be used in * rwmb_the_field function later. * * @use self::get_value() * @see rwmb_the_value() * * @param array $field Field parameters. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string HTML output of the field */ public static function the_value( $field, $args = array(), $post_id = null ) { $value = self::call( 'get_value', $field, $args, $post_id ); if ( false === $value ) { return ''; } return self::call( 'format_value', $field, $value, $args, $post_id ); } /** * Format value for the helper functions. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_value( $field, $value, $args, $post_id ) { if ( ! $field['clone'] ) { return self::call( 'format_clone_value', $field, $value, $args, $post_id ); } $output = '<ul>'; foreach ( $value as $clone ) { $output .= '<li>' . self::call( 'format_clone_value', $field, $clone, $args, $post_id ) . '</li>'; } $output .= '</ul>'; return $output; } /** * Format value for a clone. * * @param array $field Field parameters. * @param string|array $value The field meta value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_clone_value( $field, $value, $args, $post_id ) { if ( ! $field['multiple'] ) { return self::call( 'format_single_value', $field, $value, $args, $post_id ); } $output = '<ul>'; foreach ( $value as $single ) { $output .= '<li>' . self::call( 'format_single_value', $field, $single, $args, $post_id ) . '</li>'; } $output .= '</ul>'; return $output; } /** * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. * * @param array $field Field parameters. * @param string $value The value. * @param array $args Additional arguments. Rarely used. See specific fields for details. * @param int|null $post_id Post ID. null for current post. Optional. * * @return string */ public static function format_single_value( $field, $value, $args, $post_id ) { return $value; } /** * Call a method of a field. * This should be replaced by static::$method( $args ) in PHP 5.3. * * @return mixed */ public static function call() { $args = func_get_args(); $check = reset( $args ); // Params: method name, field, other params. if ( is_string( $check ) ) { $method = array_shift( $args ); $field = reset( $args ); // Keep field as 1st param. } else { $field = array_shift( $args ); $method = array_shift( $args ); if ( 'raw_meta' === $method ) { // Add field param after object id. array_splice( $args, 1, 0, array( $field ) ); } else { $args[] = $field; // Add field as last param. } } return call_user_func_array( array( RWMB_Helpers_Field::get_class( $field ), $method ), $args ); } /** * Apply various filters based on field type, id. * Filters: * - rwmb_{$name} * - rwmb_{$field['type']}_{$name} * - rwmb_{$field['id']}_{$name} * * @return mixed */ public static function filter() { $args = func_get_args(); // 3 first params must be: filter name, value, field. Other params will be used for filters. $name = array_shift( $args ); $value = array_shift( $args ); $field = array_shift( $args ); // List of filters. $filters = array( 'rwmb_' . $name, 'rwmb_' . $field['type'] . '_' . $name, ); if ( $field['id'] ) { $field_id = $field['clone'] ? $field['_original_id'] : $field['id']; $filters[] = 'rwmb_' . $field_id . '_' . $name; } // Filter params: value, field, other params. Note: value is changed after each run. array_unshift( $args, $field ); foreach ( $filters as $filter ) { $filter_args = $args; array_unshift( $filter_args, $value ); $value = apply_filters_ref_array( $filter, $filter_args ); } return $value; } } about/js/about.js 0000644 00000001055 15105434331 0007742 0 ustar 00 ( function ( $ ) { 'use strict'; function tabs() { var $container = $( '.nav-tab-wrapper' ), $tabs = $container.find( '.nav-tab' ), $panes = $( '.gt-tab-pane' ); $container.on( 'click', '.nav-tab', function ( e ) { e.preventDefault(); $tabs.removeClass( 'nav-tab-active' ); $( this ).addClass( 'nav-tab-active' ); $panes.removeClass( 'gt-is-active' ); $panes.filter( $( this ).attr( 'href' ) ).addClass( 'gt-is-active' ); } ); } // Auto activate tabs when DOM ready. $( tabs ); } ( jQuery ) ); about/images/online-generator.png 0000644 00000031710 15105434331 0013102 0 ustar 00 �PNG IHDR � S ;Vk gAMA ���a sRGB ��� �PLTE���FTb������������/?O�����ݙ��������������t~�������P^k��bmzmx���Ѧ��|��������������KXf���5DU���������gr~AO_���Uao���<KZ������]iv��ھ��Yes��������������Q��c�����v�ɍ�Դ������������웸�穨ރ��mj��!� 2�IDATx��k{�L�G���q�DPTD�����r2iRs��ۦ�}��e'�vv" �_� Y � � �� � d @V d � + � Y ���f���雸� |����h��Ts,� ���wn�������i7I�����Ų�(/d � Y!+ � Y��7��%�6 �YV�>uGF����z]־� ː?�[]�% >#�4V�дGǂaEb�y�ֹѶ���Ve�塸��Y��/-#�1��X�1"