PATH:
home
/
letacommog
/
metras
/
wp-content
/
plugins
/
wp-lastweets
/
vendor
/
htmlburger
/
carbon-fields
/
core
/
Field
<?php namespace Carbon_Fields\Field; use Carbon_Fields\Datastore\Datastore_Interface; use Carbon_Fields\Helper\Helper; use Carbon_Fields\Field\Field; use Carbon_Fields\Field\Group_Field; use Carbon_Fields\Value_Set\Value_Set; use Carbon_Fields\Exception\Incorrect_Syntax_Exception; /** * Complex field class. * Allows nested repeaters with multiple field groups to be created. */ class Complex_Field extends Field { /** * Visual layout type constants */ const LAYOUT_GRID = 'grid'; // default const LAYOUT_TABBED_HORIZONTAL = 'tabbed-horizontal'; const LAYOUT_TABBED_VERTICAL = 'tabbed-vertical'; const TYPE_PROPERTY = '_type'; /** * Default field value * * @var array */ protected $default_value = array(); /** * Complex field layout * * @var string static::LAYOUT_* constant */ protected $layout = self::LAYOUT_GRID; /** * Value tree describing the complex values and all groups with their child fields * * @var array */ protected $value_tree = array(); /** * Array of groups registered for this complex field * * @var array */ protected $groups = array(); /** * Minimum number of entries. -1 for no limit * * @var integer */ protected $values_min = -1; /** * Maximum number of entries. -1 for no limit * * @var integer */ protected $values_max = -1; /** * Default entry state - collapsed or not * * @var boolean */ protected $collapsed = false; /** * Defines whether duplicate groups are allowed or not * * @var boolean */ protected $duplicate_groups_allowed = true; /** * Entry labels * These are translated in init() * * @var array */ public $labels = array( 'singular_name' => 'Entry', 'plural_name' => 'Entries', ); /** * 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->set_value_set( new Value_Set( Value_Set::TYPE_MULTIPLE_VALUES ) ); parent::__construct( $type, $name, $label ); } /** * Initialization tasks. */ public function init() { $this->labels = array( 'singular_name' => __( $this->labels['singular_name'], 'carbon-fields' ), 'plural_name' => __( $this->labels['plural_name'], 'carbon-fields' ), ); parent::init(); } /** * Set array of hierarchy field names * * @return self $this */ public function set_hierarchy( $hierarchy ) { parent::set_hierarchy( $hierarchy ); $this->update_child_hierarchy(); return $this; } /** * Propagate hierarchy to child fields */ public function update_child_hierarchy() { $hierarchy = array_merge( $this->get_hierarchy(), array( $this->get_base_name() ) ); $fields = $this->get_fields(); foreach ( $fields as $field ) { $field->set_hierarchy( $hierarchy ); } } /** * Activate the field once the container is attached. */ public function activate() { parent::activate(); $fields = $this->get_fields(); foreach ( $fields as $field ) { $field->activate(); } } /** * Set the datastore of this field and propagate it to children * * @param Datastore_Interface $datastore * @param boolean $set_as_default * @return self $this */ public function set_datastore( Datastore_Interface $datastore, $set_as_default = false ) { if ( $set_as_default && ! $this->has_default_datastore() ) { return $this; // datastore has been overriden with a custom one - abort changing to a default one } $this->datastore = $datastore; $this->has_default_datastore = $set_as_default; $this->update_child_datastore( $this->get_datastore(), true ); return $this; } /** * Propagate the datastore down the hierarchy * * @param Datastore_Interface $datastore * @param boolean $set_as_default */ protected function update_child_datastore( Datastore_Interface $datastore, $set_as_default = false ) { foreach ( $this->groups as $group ) { $group->set_datastore( $datastore, $set_as_default ); } } /** * Retrieve all groups of fields. * * @return array $fields */ public function get_fields() { $fields = array(); foreach ( $this->groups as $group ) { $group_fields = $group->get_fields(); $fields = array_merge( $fields, $group_fields ); } return $fields; } /** * Add a set/group of fields. * * Accepted param variations: * - array<Field> $fields * - string $group_name, array<Field> $fields * - string $group_name, string $group_label, array<Field> $fields * * @return $this */ public function add_fields() { $argv = func_get_args(); $argc = count( $argv ); $fields = $argv[ $argc - 1 ]; $name = ''; $label = null; if ( $argc >= 2 ) { $name = $argv[0]; } if ( $argc >= 3 ) { $label = $argv[1]; } $name = ! empty( $name ) ? $name : Group_Field::DEFAULT_GROUP_NAME; if ( array_key_exists( $name, $this->groups ) ) { Incorrect_Syntax_Exception::raise( 'Group with name "' . $name . '" in Complex Field "' . $this->get_label() . '" already exists.' ); return $this; } $reserved_names = array( Value_Set::VALUE_PROPERTY, static::TYPE_PROPERTY ); foreach ( $fields as $field ) { if ( in_array( $field->get_base_name(), $reserved_names ) ) { Incorrect_Syntax_Exception::raise( '"' . $field->get_base_name() . '" is a reserved keyword for Complex fields and cannot be used for a field name.' ); return $this; } } $group = new Group_Field( $name, $label, $fields ); $this->groups[ $group->get_name() ] = $group; $this->update_child_hierarchy(); if ( $this->get_datastore() !== null ) { $this->update_child_datastore( $this->get_datastore(), true ); } return $this; } /** * Retrieve the groups of this field. * * @return array */ public function get_group_names() { return array_keys( $this->groups ); } /** * Retrieve a group by its name. * * @param string $group_name Group name * @return Group_Field $group_object Group object */ public function get_group_by_name( $group_name ) { $group_object = null; foreach ( $this->groups as $group ) { if ( $group->get_name() == $group_name ) { $group_object = $group; } } return $group_object; } /** * Set the group label Underscore template. * * @param string|callable $template * @return self $this */ public function set_header_template( $template ) { $template = is_callable( $template ) ? call_user_func( $template ) : $template; // Assign the template to the group that was added last $values = array_values( $this->groups ); $group = end( $values ); if ( $group ) { $group->set_label_template( $template ); $this->groups[ $group->get_name() ] = $group; } return $this; } /** * Set the field labels. * Currently supported values: * - singular_name - the singular entry label * - plural_name - the plural entries label * * @param array $labels Labels */ public function setup_labels( $labels ) { $this->labels = array_merge( $this->labels, $labels ); return $this; } /** * Return a clone of a field with hierarchy settings applied * * @param Field $field * @param Field $parent_field * @param int $group_index * @return Field */ public function get_clone_under_field_in_hierarchy( $field, $parent_field, $group_index = 0 ) { $clone = clone $field; $clone->set_hierarchy( array_merge( $parent_field->get_hierarchy(), array( $parent_field->get_base_name() ) ) ); $clone->set_hierarchy_index( array_merge( $parent_field->get_hierarchy_index(), array( $group_index ) ) ); return $clone; } protected function get_prefilled_group_fields( $group_fields, $group_values, $group_index ) { $fields = array(); foreach ( $group_fields as $field ) { $clone = $this->get_clone_under_field_in_hierarchy( $field, $this, $group_index ); if ( isset( $group_values[ $clone->get_base_name() ] ) ) { $clone->set_value( $group_values[ $clone->get_base_name() ] ); } $fields[] = $clone; } return $fields; } protected function get_prefilled_groups( $groups, $value_tree ) { $fields = array(); foreach ( $value_tree as $group_index => $value ) { $group_name = $groups[ $group_index ]; $group = $this->get_group_by_name( $group_name ); if ( ! $group ) { // Failed to find group - sombody has been messing with the database or group definitions continue; } $group_fields = $group->get_fields(); $group_values = array(); if ( isset( $value_tree[ $group_index ] ) ) { $group_values = $value_tree[ $group_index ]; } $fields[ $group_index ] = array( Value_Set::VALUE_PROPERTY => $group->get_name() ) + $this->get_prefilled_group_fields( $group_fields, $group_values, $group_index ); } return $fields; } /** * Load the field value from an input array based on its name. * * @param array $input Array of field names and values. * @return self $this */ public function set_value_from_input( $input ) { if ( ! isset( $input[ $this->get_name() ] ) ) { return $this; } $value_tree = array(); $input_groups = $input[ $this->get_name() ]; $input_group_index = 0; foreach ( $input_groups as $values ) { if ( ! isset( $values[ Value_Set::VALUE_PROPERTY ] ) || ! isset( $this->groups[ $values[ Value_Set::VALUE_PROPERTY ] ] ) ) { continue; } $group = $this->get_group_by_name( $values[ Value_Set::VALUE_PROPERTY ] ); $group_fields = $group->get_fields(); $group_field_names = array_flip( $group->get_field_names() ); $value_group = array( Value_Set::VALUE_PROPERTY => $values[ Value_Set::VALUE_PROPERTY ] ); unset( $values[ Value_Set::VALUE_PROPERTY ] ); // trim input values to those used by the field $values = array_intersect_key( $values, $group_field_names ); foreach ( $group_fields as $field ) { $tmp_field = $this->get_clone_under_field_in_hierarchy( $field, $this, $input_group_index ); $tmp_field->set_value_from_input( $values ); if ( is_a( $tmp_field, get_class() ) ) { $value_group[ $tmp_field->get_base_name() ] = $tmp_field->get_value_tree(); } else { $value_group[ $tmp_field->get_base_name() ] = $tmp_field->get_full_value(); } } $value_tree[] = $value_group; $input_group_index++; } $this->set_value( $value_tree ); return $this; } /** * Save all contained groups of fields. */ public function save() { // Only delete root field values as nested field values should be deleted in a cascading manner by the datastore $hierarchy = $this->get_hierarchy(); $delete_on_save = empty( $hierarchy ); $delete_on_save = apply_filters( 'carbon_fields_should_delete_field_value_on_save', $delete_on_save, $this ); if ( $delete_on_save ) { $this->delete(); } $save = apply_filters( 'carbon_fields_should_save_field_value', true, $this->get_value(), $this ); if ( $save ) { $this->get_datastore()->save( apply_filters( 'carbon_fields_before_complex_field_save', $this ) ); $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); foreach ( $field_groups as $group_index => $fields ) { foreach ( $fields as $field ) { if ( ! is_a( $field, __NAMESPACE__ . '\\Field' ) ) { continue; } $field->save(); } } } } /** * {@inheritDoc} */ public function get_formatted_value() { $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); $value = array(); foreach ( $field_groups as $group_index => $field_group ) { $value[ $group_index ] = array(); foreach ( $field_group as $key => $field ) { if ( is_a( $field, __NAMESPACE__ . '\\Field' ) ) { $value[ $group_index ][ $field->get_base_name() ] = $field->get_formatted_value(); } else { if ( $key === Value_Set::VALUE_PROPERTY ) { $value[ $group_index ][ static::TYPE_PROPERTY ] = $field; } else { $value[ $group_index ][ $key ] = $field; } } } } return $value; } /** * Convert an externally-keyed value array ('_type' => ...) * to an internally-keyed one ('value' => ...) * * @param mixed $value * @return mixed */ protected function external_to_internal_value( $value ) { if ( ! is_array( $value ) ) { return $value; } if ( ! isset( $value[ static::TYPE_PROPERTY ] ) ) { return $value; } $value = array_map( array( $this, 'external_to_internal_value' ), $value ); $value[ Value_Set::VALUE_PROPERTY ] = $value[ static::TYPE_PROPERTY ]; unset( $value[ static::TYPE_PROPERTY ] ); return $value; } /** * {@inheritDoc} */ public function set_value( $value ) { $value = array_map( array( $this, 'external_to_internal_value' ), $value ); $groups = array(); foreach ( $value as $values ) { $groups[] = isset( $values[ Value_Set::VALUE_PROPERTY ] ) ? $values[ Value_Set::VALUE_PROPERTY ] : Group_Field::DEFAULT_GROUP_NAME; } parent::set_value( $groups ); $this->set_value_tree( $value ); return $this; } /** * {@inheritDoc} */ public function set_default_value( $default_value ) { foreach ( $default_value as $index => $group ) { if ( ! isset( $group[ static::TYPE_PROPERTY ] ) ) { $default_value[ $index ][ static::TYPE_PROPERTY ] = Group_Field::DEFAULT_GROUP_NAME; } } $this->default_value = $default_value; return $this; } /** * Return the full value tree of all groups and their fields * * @return mixed */ public function get_value_tree() { return (array) $this->value_tree; } /** * Set the full value tree of all groups and their fields * * @see Internal Glossary in DEVELOPMENT.MD * @return self $this */ public function set_value_tree( $value_tree ) { $this->value_tree = $value_tree; return $this; } /** * Returns an array that holds the field data, suitable for JSON representation. * * @param bool $load Should the value be loaded from the database or use the value from the current instance. * @return array */ public function to_json( $load ) { $complex_data = parent::to_json( $load ); $groups_data = array(); foreach ( $this->groups as $group ) { $group_data = $group->to_json( false ); $group_data['collapsed'] = $this->get_collapsed(); $groups_data[] = $group_data; } $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); $value_data = array(); foreach ( $field_groups as $group_index => $fields ) { $group = $this->get_group_by_name( $fields[ Value_Set::VALUE_PROPERTY ] ); $data = array( 'name' => $group->get_name(), 'label' => $group->get_label(), 'label_template' => $group->get_label_template(), 'group_id' => $group->get_group_id(), 'collapsed' => $this->get_collapsed(), 'fields' => array(), ); foreach ( $fields as $field ) { if ( ! is_a( $field, __NAMESPACE__ . '\\Field' ) ) { continue; } $data['fields'][] = $field->to_json( false ); } $value_data[] = $data; } $group_types = array(); foreach ( $this->groups as $group ) { $group_types[] = array( 'name' => $group->get_name(), 'label' => $group->get_label(), ); } $complex_data = array_merge( $complex_data, array( 'duplicate_groups_allowed' => $this->get_duplicate_groups_allowed(), 'group_types' => $group_types, 'layout' => $this->layout, 'labels' => $this->labels, 'min' => $this->get_min(), 'max' => $this->get_max(), 'multiple_groups' => count( $groups_data ) > 1, 'groups' => $groups_data, 'value' => $value_data, 'collapsed' => $this->get_collapsed(), ) ); return $complex_data; } /** * Modify the layout of this field. * * @param string $layout * @return self $this */ public function set_layout( $layout ) { $available_layouts = array( static::LAYOUT_GRID, static::LAYOUT_TABBED_HORIZONTAL, static::LAYOUT_TABBED_VERTICAL, ); if ( ! in_array( $layout, $available_layouts ) ) { $error_message = 'Incorrect layout ``' . $layout . '" specified. ' . 'Available layouts: ' . implode( ', ', $available_layouts ); Incorrect_Syntax_Exception::raise( $error_message ); return $this; } $this->layout = $layout; return $this; } /** * Get the minimum number of entries. * * @return int $min */ public function get_min() { return $this->values_min; } /** * Set the minimum number of entries. * * @param int $min * @return self $this */ public function set_min( $min ) { $this->values_min = intval( $min ); return $this; } /** * Get the maximum number of entries. * * @return int $max */ public function get_max() { return $this->values_max; } /** * Set the maximum number of entries. * * @param int $max * @return self $this */ public function set_max( $max ) { $this->values_max = intval( $max ); return $this; } /** * Get collapsed state * * @return bool */ public function get_collapsed() { return $this->collapsed; } /** * Change the groups initial collapse state. * This state relates to the state of which the groups are rendered. * * @param bool $collapsed * @return self $this */ public function set_collapsed( $collapsed = true ) { $this->collapsed = $collapsed; return $this; } /** * Get whether duplicate groups are allowed. * * @return bool */ public function get_duplicate_groups_allowed() { return $this->duplicate_groups_allowed; } /** * Set whether duplicate groups are allowed. * * @param bool $allowed * @return self $this */ public function set_duplicate_groups_allowed( $allowed ) { $this->duplicate_groups_allowed = $allowed; return $this; } }
[+]
..
[-] 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]