PATH:
home
/
letacommog
/
metras
/
wp-content
/
plugins
/
wp-lastweets
/
vendor
/
htmlburger
/
carbon-fields
/
core
/
Field
<?php namespace Carbon_Fields\Field; use Carbon_Fields\Value_Set\Value_Set; use WP_Query; use WP_Term_Query; use WP_User_Query; use WP_Comment_Query; /** * Association field class. * Allows selecting and manually sorting entries from various types: * - Posts * - Terms * - Users * - Comments */ class Association_Field extends Field { /** * WP_Toolset instance for WP data loading * * @var Carbon_Fields\Toolset\WP_Toolset */ protected $wp_toolset; /** * Min number of selected items allowed. -1 for no limit * * @var integer */ protected $min = -1; /** * Max number of selected items allowed. -1 for no limit * * @var integer */ protected $max = -1; /** * Max items per page. -1 for no limit * * @var integer */ protected $items_per_page = 20; /** * Allow items to be added multiple times * * @var boolean */ protected $duplicates_allowed = false; /** * Default field value * * @var array */ protected $default_value = array(); /** * Types of entries to associate with. * @var array */ protected $types = array( array( 'type' => 'post', 'post_type' => 'post', ), ); /** * Create a field from a certain type with the specified label. * * @param string $type Field type * @param string $name Field name * @param string $label Field label */ public function __construct( $type, $name, $label ) { $this->wp_toolset = \Carbon_Fields\Carbon_Fields::resolve( 'wp_toolset' ); $this->set_value_set( new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'type' => '', 'subtype' => '', 'id' => 0 ) ) ); parent::__construct( $type, $name, $label ); } /** * {@inheritDoc} */ public function set_value_from_input( $input ) { $value = array(); if ( isset( $input[ $this->get_name() ] ) ) { $value = stripslashes_deep( $input[ $this->get_name() ] ); if ( is_array( $value ) ) { $value = array_values( $value ); } } $this->set_value( $value ); return $this; } /** * {@inheritDoc} */ public function set_value( $value ) { $value = $this->value_string_array_to_value_set( $value ); return parent::set_value( $value ); } /** * Get value string for legacy value * * @return string */ protected function get_value_string_for_legacy_value( $legacy_value ) { $entry_type = 'post'; $entry_subtype = 'post'; // attempt to find a suitable type that is registered to this field as post type is not stored for legacy data foreach ( $this->types as $type ) { if ( $type['type'] === $entry_type ) { $entry_subtype = $type['post_type']; break; } } return $entry_type . ':' . $entry_subtype . ':' . $legacy_value; } /** * Convert a colon:separated:string into its expected components * Used for backwards compatibility to CF 1.5 * * @param string $value_string * @return array */ protected function value_string_to_property_array( $value_string ) { if ( is_numeric( $value_string ) ) { // we are dealing with legacy data that only contains a post ID $value_string = $this->get_value_string_for_legacy_value( $value_string ); } $value_pieces = explode( ':', $value_string ); $type = isset( $value_pieces[0] ) ? $value_pieces[0] : 'post'; $subtype = isset( $value_pieces[1] ) ? $value_pieces[1] : 'post'; $id = isset( $value_pieces[2] ) ? $value_pieces[2] : 0; $property_array = array( Value_Set::VALUE_PROPERTY => $value_string, 'type' => $type, 'subtype' => $subtype, 'id' => intval( $id ), ); return $property_array; } /** * Convert a colon:separated:string into its expected components * Used for backwards compatibility to CF 1.5 * * @param array $value_string_array * @return array<array> */ protected function value_string_array_to_value_set( $value_string_array ) { $value_set = array(); foreach ( $value_string_array as $raw_value_entry ) { $value_string = $raw_value_entry; if ( is_array( $raw_value_entry ) ) { if ( isset( $raw_value_entry['type'] ) ) { // array is already in suitable format $value_set[] = $raw_value_entry; continue; } $value_string = $raw_value_entry[ Value_Set::VALUE_PROPERTY ]; } $value_string = trim( $value_string ); if ( empty( $value_string ) ) { continue; } $property_array = $this->value_string_to_property_array( $value_string ); $value_set[] = $property_array; } return $value_set; } /** * Generate the item options. * * @access public * * @param array $args * @return array $options The selectable options of the association field. */ public function get_options( $args = array() ) { global $wpdb; $args = wp_parse_args( $args, array( 'page' => 1, 'term' => '', ) ); $sql_queries = array(); foreach ( $this->types as $type ) { $type_args = array_merge( $type, array( 'term' => $args['term'], ) ); $callback = "get_{$type['type']}_options_sql"; $sql_statement = $this->$callback( $type_args ); $sql_queries[] = $sql_statement; } $sql_queries = implode( " UNION ", $sql_queries ); $per_page = $this->get_items_per_page(); $offset = ($args['page'] - 1) * $per_page; $sql_queries .= " ORDER BY `title` ASC LIMIT {$per_page} OFFSET {$offset}"; $results = $wpdb->get_results( $sql_queries ); $options = array(); foreach ( $results as $result ) { $callback = "format_{$result->type}_option"; $options[] = $this->$callback( $result ); } /** * Filter the final list of options, available to a certain association field. * * @param array $options Unfiltered options items. * @param string $name Name of the association field. */ $options = apply_filters( 'carbon_fields_association_field_options', $options, $this->get_base_name() ); return array( 'total_options' => $wpdb->get_var( "SELECT COUNT(*) FROM (" . preg_replace( '~(LIMIT .*)$~', '', $sql_queries ) . ") as t" ), 'options' => $options, ); } /** * Modify the types. * * @param array $types New types * @return self $this */ public function set_types( $types ) { $this->types = $types; return $this; } /** * Get the minimum allowed number of selected entries. * * @return int */ public function get_min() { return $this->min; } /** * Set the minimum allowed number of selected entries. * * @param int $min * @return self $this */ public function set_min( $min ) { $this->min = intval( $min ); return $this; } /** * Get the maximum allowed number of selected entries. * * @return int */ public function get_max() { return $this->max; } /** * Set the maximum allowed number of selected entries. * * @param int $max * @return self $this */ public function set_max( $max ) { $this->max = intval( $max ); return $this; } /** * Set the items per page. * * @param int $items_per_page * @return self $this */ public function set_items_per_page( $items_per_page ) { $this->items_per_page = intval( $items_per_page ); return $this; } /** * Get the items per page. * * @param int $items_per_page * @return self $this */ public function get_items_per_page() { return $this->items_per_page; } /** * Get whether entry duplicates are allowed. * * @return boolean */ public function get_duplicates_allowed() { return $this->duplicates_allowed; } /** * Set whether entry duplicates are allowed. * * @param boolean $allowed * @return self $this */ public function set_duplicates_allowed( $allowed ) { $this->duplicates_allowed = $allowed; return $this; } /** * Specify whether to allow each entry to be selected multiple times. * Backwards-compatibility alias. * * @param boolean $allow * @return self $this */ public function allow_duplicates( $allow = true ) { return $this->set_duplicates_allowed( $allow ); } /** * Converts the field values into a usable associative array. * * The association data is saved in the database in the following format: * array ( * 0 => 'post:page:4', * 1 => 'term:category:2', * 2 => 'user:user:1', * ) * where the value of each array item contains: * - Type of data (post, term, user or comment) * - Subtype of data (the particular post type or taxonomy) * - ID of the item (the database ID of the item) */ protected function value_to_json() { $value_set = $this->get_value(); $value = array(); foreach ( $value_set as $entry ) { $item = array( 'type' => $entry['type'], 'subtype' => $entry['subtype'], 'id' => intval( $entry['id'] ), 'title' => $this->get_title_by_type( $entry['id'], $entry['type'], $entry['subtype'] ), 'label' => $this->get_item_label( $entry['id'], $entry['type'], $entry['subtype'] ), 'is_trashed' => ( $entry['type'] == 'post' && get_post_status( $entry['id'] ) === 'trash' ), ); $value[] = $item; } return $value; } /** * Convert the field data into JSON representation. * @param bool $load Whether to load data from the datastore. * @return mixed The JSON field data. */ public function to_json( $load ) { $field_data = parent::to_json( $load ); $field_data = array_merge( $field_data, array( 'value' => $this->value_to_json(), 'options' => $this->get_options(), 'min' => $this->get_min(), 'max' => $this->get_max(), 'duplicates_allowed' => $this->duplicates_allowed, ) ); return $field_data; } /** * Helper method to prepare the SQL needed to search for options of type 'post'. * * Creates a 'fake' WP_Query with only one result in order to catch the SQL * that it will construct in order to support all of the WP_Query arguments. * * @access public * * @param array $args * @return string */ public function get_post_options_sql( $args = array() ) { $type = $args['type']; $post_type = $args['post_type']; $search_term = $args['term']; unset( $args['type'], $args['post_type'], $args['term'] ); /** * Filter the default query when fetching posts for a particular field. * * @param array $args The parameters, passed to WP_Query::__construct(). */ $filter_name = 'carbon_fields_association_field_options_' . $this->get_base_name() . '_' . $type . '_' . $post_type; $args = apply_filters( $filter_name, array( 'post_type' => $post_type, 'posts_per_page' => 1, 'fields' => 'ids', 'suppress_filters' => false, 's' => $search_term, ) ); add_filter( 'posts_fields_request', array( $this, 'get_post_options_sql_select_clause' ) ); add_filter( 'posts_groupby_request', '__return_empty_string' ); add_filter( 'posts_orderby_request', '__return_empty_string' ); add_filter( 'post_limits_request', '__return_empty_string' ); $posts_query = new WP_Query( $args ); remove_filter( 'posts_fields_request', array( $this, 'get_post_options_sql_select_clause' ) ); remove_filter( 'posts_groupby_request', '__return_empty_string' ); remove_filter( 'posts_orderby_request', '__return_empty_string' ); remove_filter( 'post_limits_request', '__return_empty_string' ); return $posts_query->request; } /** * Modify the "SELECT" columns for the WP_Query. * * @access public * * @param string $fields * @return string */ public function get_post_options_sql_select_clause( $fields ) { global $wpdb; return $fields . " , `{$wpdb->posts}`.`post_title` AS `title`, 'post' AS `type`, `{$wpdb->posts}`.`post_type` AS `subtype` "; } /** * Helper method to prepare the SQL needed to search for options of type 'term'. * * Creates a 'fake' WP_Term_Query with only one result in order to catch the SQL * that it will construct in order to support all of the WP_Term_Query arguments. * * @access public * * @param array $args * @return string */ public function get_term_options_sql( $args = array() ) { $type = $args['type']; $taxonomy = $args['taxonomy']; $search_term = $args['term']; unset( $args['type'], $args['taxonomy'], $args['term'] ); /** * Filter the default parameters when fetching terms for a particular field. * * @param array $args The parameters, passed to WP_Term_Query::__construct(). */ $filter_name = 'carbon_fields_association_field_options_' . $this->get_base_name() . '_' . $type . '_' . $taxonomy; $args = apply_filters( $filter_name, array( 'hide_empty' => 0, 'taxonomy' => $taxonomy, 'fields' => 'count', 'number' => 1, 'search' => $search_term, 'update_term_meta_cache' => false, ) ); add_filter( 'get_terms_fields', array( $this, 'get_term_options_sql_select_clause' ) ); add_filter( 'terms_clauses', array( $this, 'get_term_options_sql_clauses' ) ); $terms_query = new WP_Term_Query( $args ); remove_filter( 'get_terms_fields', array( $this, 'get_term_options_sql_select_clause' ) ); remove_filter( 'terms_clauses', array( $this, 'get_term_options_sql_clauses' ) ); return $terms_query->request; } /** * Modify the "SELECT" columns for the WP_Term_Query. * * @access public * * @param array $fields * @return array */ public function get_term_options_sql_select_clause( $fields ) { return array( '`t`.`term_id` AS `ID`', '`t`.`name` AS `title`', '\'term\' as `type`', '`tt`.`taxonomy` AS `subtype`' ); } /** * Modify the clauses for the SQL request of the WP_Term_Query. * * @access public * * @param array $clauses * @return array */ public function get_term_options_sql_clauses( $clauses ) { unset( $clauses['orderby'], $clauses['order'], $clauses['limits'] ); return $clauses; } /** * Helper method to prepare the SQL needed to search for options of type 'user'. * * Creates a 'fake' WP_User_Query with only one result in order to catch the SQL * that it will construct in order to support all of the WP_User_Query arguments. * * @access public * * @param array $args * @return string */ public function get_user_options_sql( $args = array() ) { global $wpdb; $type = $args['type']; $search_term = $args['term']; unset( $args['type'], $args['term'], $args['subtype'] ); /** * Filter the default parameters when fetching terms for a particular field. * * @param array $args The parameters, passed to WP_User_Query::__construct(). */ $filter_name = 'carbon_fields_association_field_options_' . $this->get_base_name() . '_' . $type; $args = apply_filters( $filter_name, array( 'fields' => 'ID', 'number' => 1, 'search' => $search_term, ) ); $users_query = new WP_User_Query; $users_query->prepare_query( $args ); return "SELECT `{$wpdb->users}`.`ID`, '' AS `title`, 'user' AS `type`, 'user' AS `subtype` {$users_query->query_from} {$users_query->query_where}"; } /** * Helper method to prepare the SQL needed to search for options of type 'comment'. * * Creates a 'fake' WP_Comment_Query with only one result in order to catch the SQL * that it will construct in order to support all of the WP_Comment_Query arguments. * * @access public * * @param array $args * @return string */ public function get_comment_options_sql( $args = array() ) { $type = $args['type']; $search_term = $args['term']; unset( $args['type'], $args['term'], $args['subtype'] ); /** * Filter the default parameters when fetching comments for a particular field. * * @param array $args The parameters, passed to get_comments(). */ $filter_name = 'carbon_fields_association_field_options_' . $this->get_base_name() . '_' . $type; $args = apply_filters( $filter_name, array( 'fields' => 'ids', 'number' => 1, 'search' => $search_term, ) ); add_filter( 'comments_clauses', array( $this, 'get_comments_clauses' ) ); $comments_query = new WP_Comment_Query; $comments_query->query( $args ); remove_filter( 'comments_clauses', array( $this, 'get_comments_clauses' ) ); return $comments_query->request; } /** * Modify the "SELECT" columns and the clauses for the SQL request * performed by the WP_Comment_Query. * * @access public * * @param array $clauses * @return array */ public function get_comments_clauses( $clauses ) { global $wpdb; $clauses['fields'] = " {$wpdb->comments}.`comment_ID` AS `ID`, '' AS `title`, 'comment' AS `type`, 'comment' AS `subtype` "; unset( $clauses['orderby'], $clauses['limits'], $clauses['groupby'] ); return $clauses; } /** * Used to get the thumbnail of an item. * * Can be overriden or extended by the `carbon_fields_association_field_option_thumbnail` filter. * * @param int $id The database ID of the item. * @param string $type Item type (post, term, user, comment, or a custom one). * @param string $subtype The subtype - "page", "post", "category", etc. * @return string $title The title of the item. */ public function get_thumbnail_by_type( $id, $type, $subtype = '' ) { $thumbnail_url = ''; if ( $type === 'post' ) { $thumbnail_url = get_the_post_thumbnail_url( $id, 'thumbnail' ); } return apply_filters( 'carbon_fields_association_field_option_thumbnail', $thumbnail_url, $id, $type, $subtype ); } /** * Used to get the title of an item. * * Can be overriden or extended by the `carbon_association_title` filter. * * @param int $id The database ID of the item. * @param string $type Item type (post, term, user, comment, or a custom one). * @param string $subtype The subtype - "page", "post", "category", etc. * @return string $title The title of the item. */ public function get_title_by_type( $id, $type, $subtype = '' ) { $title = ''; $method = 'get_' . $type . '_title'; $callable = array( $this->wp_toolset, $method ); if ( is_callable( $callable ) ) { $title = call_user_func( $callable, $id, $subtype ); } if ( $type === 'comment' ) { $max = apply_filters( 'carbon_fields_association_field_comment_length', 30, $this->get_base_name() ); if ( strlen( $title ) > $max ) { $title = substr( $title, 0, $max ) . '...'; } } /** * Filter the title of the association item. * * @param string $title The unfiltered item title. * @param string $name Name of the association field. * @param int $id The database ID of the item. * @param string $type Item type (post, term, user, comment, or a custom one). * @param string $subtype Subtype - "page", "post", "category", etc. */ $title = apply_filters( 'carbon_fields_association_field_title', $title, $this->get_base_name(), $id, $type, $subtype ); if ( ! $title ) { $title = '(no title) - ID: ' . $id; } return $title; } /** * Used to get the label of an item. * * Can be overriden or extended by the `carbon_association_item_label` filter. * * @param int $id The database ID of the item. * @param string $type Item type (post, term, user, comment, or a custom one). * @param string $subtype Subtype - "page", "post", "category", etc. * @return string $label The label of the item. */ public function get_item_label( $id, $type, $subtype = '' ) { $label = $subtype ? $subtype : $type; if ( $type === 'post' ) { $post_type_object = get_post_type_object( $subtype ); $label = $post_type_object->labels->singular_name; } elseif ( $type === 'term' ) { $taxonomy_object = get_taxonomy( $subtype ); $label = $taxonomy_object->labels->singular_name; } /** * Filter the label of the association item. * * @param string $label The unfiltered item label. * @param string $name Name of the association field. * @param int $id The database ID of the item. * @param string $type Item type (post, term, user, comment, or a custom one). * @param string $subtype Subtype - "page", "post", "category", etc. */ return apply_filters( 'carbon_fields_association_field_item_label', $label, $this->get_base_name(), $id, $type, $subtype ); } /** * Retrieve the edit link of a particular object. * * @param string $type Object type. * @param int $id ID of the object. * @return string URL of the edit link. */ protected function get_object_edit_link( $type, $id ) { switch ( $type['type'] ) { case 'post': $edit_link = get_edit_post_link( $id ); break; case 'term': $edit_link = get_edit_term_link( $id, '', $type['type'] ); break; case 'comment': $edit_link = get_edit_comment_link( $id ); break; case 'user': $edit_link = get_edit_user_link( $id ); break; default: $edit_link = false; } return $edit_link; } /** * Prepares an option of type 'post' for JS usage. * * @param array $data * @return array */ public function format_post_option( $data ) { return array( 'id' => intval( $data->ID ), 'title' => $this->get_title_by_type( $data->ID, $data->type, $data->subtype ), 'thumbnail' => get_the_post_thumbnail_url( $data->ID, 'thumbnail' ), 'type' => $data->type, 'subtype' => $data->subtype, 'label' => $this->get_item_label( $data->ID, $data->type, $data->subtype ), 'is_trashed' => ( get_post_status( $data->ID ) == 'trash' ), 'edit_link' => $this->get_object_edit_link( get_object_vars( $data ), $data->ID ), ); } /** * Prepares an option of type 'term' for JS usage. * * @param array $data * @return array */ public function format_term_option( $data ) { return array( 'id' => intval( $data->ID ), 'title' => $data->title, 'thumbnail' => '', 'type' => $data->type, 'subtype' => $data->subtype, 'label' => $this->get_item_label( $data, $data->type, $data->subtype ), 'is_trashed' => false, 'edit_link' => $this->get_object_edit_link( get_object_vars( $data ), $data->ID ), ); } /** * Prepares an option of type 'comment' for JS usage. * * @param array $data * @return array */ public function format_comment_option( $data ) { return array( 'id' => intval( $data->ID ), 'title' => $this->get_title_by_type( $data->ID, 'comment' ), 'thumbnail' => '', 'type' => 'comment', 'subtype' => 'comment', 'label' => $this->get_item_label( $data->ID, 'comment' ), 'is_trashed' => false, 'edit_link' => $this->get_object_edit_link( get_object_vars( $data ), $data->ID ), ); } /** * Prepares an option of type 'user' for JS usage. * * @param array $data * @return array */ public function format_user_option( $data ) { return array( 'id' => intval( $data->ID ), 'title' => $this->get_title_by_type( $data->ID, 'user' ), 'thumbnail' => get_avatar_url( $data->ID, array( 'size' => 150 ) ), 'type' => 'user', 'subtype' => 'user', 'label' => $this->get_item_label( $data->ID, 'user' ), 'is_trashed' => false, 'edit_link' => $this->get_object_edit_link( get_object_vars( $data ), $data->ID ), ); } }
[+]
..
[-] Date_Field.php
[edit]
[-] Checkbox_Field.php
[edit]
[-] Broken_Field.php
[edit]
[-] Sidebar_Field.php
[edit]
[-] Textarea_Field.php
[edit]
[-] Radio_Image_Field.php
[edit]
[-] Text_Field.php
[edit]
[-] Multiselect_Field.php
[edit]
[-] Set_Field.php
[edit]
[-] Radio_Field.php
[edit]
[-] Group_Field.php
[edit]
[-] Header_Scripts_Field.php
[edit]
[-] Oembed_Field.php
[edit]
[-] Scripts_Field.php
[edit]
[-] Hidden_Field.php
[edit]
[-] Field.php
[edit]
[-] Date_Time_Field.php
[edit]
[-] Footer_Scripts_Field.php
[edit]
[-] Time_Field.php
[edit]
[-] Image_Field.php
[edit]
[-] Gravity_Form_Field.php
[edit]
[-] Color_Field.php
[edit]
[-] Complex_Field.php
[edit]
[-] Select_Field.php
[edit]
[-] Predefined_Options_Field.php
[edit]
[-] Rich_Text_Field.php
[edit]
[-] Separator_Field.php
[edit]
[-] File_Field.php
[edit]
[-] Association_Field.php
[edit]
[-] Media_Gallery_Field.php
[edit]
[-] Map_Field.php
[edit]
[-] Html_Field.php
[edit]