__('None', 'uicore-elements'),
];
$generic_posts = [
'author' => __('Author', 'uicore-elements'),
'date' => __('Posted Date', 'uicore-elements'),
'updated date' => __('Updated Date', 'uicore-elements'),
'comment' => __('Comments Count', 'uicore-elements'),
'reading time' => __('Reading Time', 'uicore-elements'),
'category' => __('Category', 'uicore-elements'),
'tag' => __('Tag', 'uicore-elements'),
'excerpt' => __('Excerpt', 'uicore-elements'),
];
$products = [
'product price' => __('Product Price', 'uicore-elements'),
'product rating' => __('Product Rating', 'uicore-elements'),
'product stock' => __('Product Stock', 'uicore-elements'),
'product category' => __('Product Category', 'uicore-elements'),
'product tag' => __('Product Tag', 'uicore-elements'),
'product attribute' => __('Product Attribute', 'uicore-elements'),
'product sale' => __('Product Sale', 'uicore-elements'),
];
$custom = [
'custom meta' => __('Custom Meta', 'uicore-elements'),
'custom taxonomy' => __('Custom Taxonomy', 'uicore-elements'),
'custom html' => __('Custom HTML', 'uicore-elements'),
];
$portfolio = [
'portfolio category' => __('Portfolio Category', 'uicore-elements'),
];
$options = $product_metas ?
array_merge($options, $products, $custom) : // specific to product widgets
array_merge($options, $generic_posts, $products, $portfolio, $custom); // generic posts widgets
$repeater = new \Elementor\Repeater();
$repeater->add_control(
'type',
[
'label' => __('Meta', 'uicore-elements'),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => $options
]
);
$repeater->add_control(
'type_custom',
[
'label' => __('Custom Field Name', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
'condition' => [
'type' => ['custom meta', 'custom taxonomy']
]
]
);
$repeater->add_control(
'html_custom',
[
'label' => __('Custom HTML', 'uicore-elements'),
'type' => Controls_Manager::TEXTAREA,
'condition' => [
'type' => ['custom html']
]
]
);
$repeater->add_control(
'date_format',
[
'label' => esc_html__('Date Format', 'uicore-elements'),
'type' => Controls_Manager::SELECT,
'default' => 'default',
'options' => [
'default' => esc_html__('Default', 'uicore-elements'),
'F j, Y' => gmdate('F j, Y'),
'Y-m-d' => gmdate('Y-m-d'),
'm/d/Y' => gmdate('m/d/Y'),
'd/m/Y' => gmdate('d/m/Y'),
'custom' => esc_html__('Custom', 'uicore-elements'),
],
'condition' => [
'type' => ['date', 'updated date']
]
]
);
$repeater->add_control(
'custom_format',
[
'label' => esc_html__('Custom Format', 'uicore-elements'),
'default' => get_option('date_format') . ' ' . get_option('time_format'),
'description' => sprintf('%s', esc_html__('Documentation on date and time formatting', 'uicore-elements')),
'condition' => [
'date_format' => 'custom',
'type' => ['date', 'updated date']
],
]
);
$repeater->add_control(
'stock_type',
[
'label' => esc_html__('Stock Data', 'uicore-elements'),
'type' => Controls_Manager::SELECT,
'default' => 'qty',
'options' => [
'qty' => esc_html__('Quantity', 'uicore-elements'),
'in' => esc_html__('In/Out of stock', 'uicore-elements'),
],
'condition' => [
'type' => ['product stock']
]
]
);
$repeater->add_control(
'in_stock_text',
[
'label' => esc_html__('In Stock Text', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
'default' => esc_html__('In Stock', 'uicore-elements'),
'condition' => [
'type' => ['product stock'],
'stock_type' => 'in',
]
]
);
$repeater->add_control(
'out_of_stock_text',
[
'label' => esc_html__('Out of Stock Text', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
'default' => esc_html__('Out of Stock', 'uicore-elements'),
'condition' => [
'type' => ['product stock'],
]
]
);
$repeater->add_control(
'in_stock_color',
[
'label' => __('In Stock Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .in-stock' => 'color: {{VALUE}}',
],
'condition' => [
'type' => ['product stock'],
]
]
);
$repeater->add_control(
'out_of_stock_color',
[
'label' => __('Out of Stock Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .out-of-stock' => 'color: {{VALUE}}',
],
'condition' => [
'type' => ['product stock'],
]
]
);
$repeater->add_control(
'before',
[
'label' => __('Text Before', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
'condition' => [
'type!' => 'none',
]
]
);
$repeater->add_control(
'after',
[
'label' => __('Text After', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
'condition' => [
'type!' => 'none',
]
]
);
$repeater->add_control(
'autor_display',
[
'label' => __('Display Type', 'uicore-elements'),
'type' => Controls_Manager::SELECT,
'default' => 'name',
'options' => [
'name' => __('Name', 'uicore-elements'),
'full' => __('Avatar & Name', 'uicore-elements'),
'avatar' => __('Avatar', 'uicore-elements'),
],
'condition' => [
'type' => 'author',
],
]
);
$repeater->add_control(
'icon',
[
'label' => __('Icon', 'uicore-elements'),
'type' => Controls_Manager::ICONS,
'condition' => [
'autor_display' => 'name',
'type!' => 'none',
],
]
);
return $repeater->get_controls();
}
function get_meta_style_controls($position = 'tb-meta')
{
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => $position . '_meta_typography',
'selector' => '{{WRAPPER}} .ui-e-' . $position,
'separator' => 'before',
]
);
$this->add_control(
$position . '_meta_color',
[
'label' => __('Text Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position => 'color: {{VALUE}}',
'{{WRAPPER}} .ui-e-' . $position . ' svg' => 'fill: {{VALUE}}',
],
]
);
$this->add_control(
$position . '_link_color',
[
'label' => __('Link Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item a' => 'color: {{VALUE}}',
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item svg' => 'fill: {{VALUE}}',
],
]
);
$this->add_control(
$position . '_linkh_color',
[
'label' => __('Link Hover Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item a:hover' => 'color: {{VALUE}}',
],
]
);
$this->add_control(
$position . '_meta_background',
[
'label' => __('Background Color', 'uicore-elements'),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item' => 'background-color: {{VALUE}}',
],
]
);
$this->add_control(
$position . '_meta_radius',
[
'label' => esc_html__('Border Radius', 'uicore-elements'),
'type' => Controls_Manager::DIMENSIONS,
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item' => 'border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;'
],
]
);
$this->add_group_control(
\Elementor\Group_Control_Box_Shadow::get_type(),
[
'name' => $position . '_meta_shadow',
'label' => esc_html__('Box Shadow', 'uicore-elements'),
'selector' => '{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item',
]
);
$this->add_responsive_control(
$position . '_meta_padding',
[
'label' => esc_html__('Padding', 'uicore-elements'),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => ['px', 'em', '%'],
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' .ui-e-meta-item' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
]
]
);
if ($position === 'top') {
$this->add_responsive_control(
$position . '_meta_margin',
[
'label' => esc_html__('Margin', 'uicore-elements'),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => ['px', 'em', '%'],
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};'
]
]
);
} else {
$this->add_control(
$position . '_meta_margin',
[
'label' => __('Meta Top Space', 'uicore-elements'),
'type' => Controls_Manager::SLIDER,
'size_units' => ['em'],
'separator' => 'after',
'range' => [
'px' => [
'min' => 0,
'max' => 3,
'step' => 0.1,
],
],
'default' => [
'unit' => 'em',
'size' => 1.2,
],
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position => 'margin-top: {{SIZE}}em;',
],
]
);
}
$this->add_responsive_control(
$position . '_meta_gap',
[
'label' => __('Items Gap', 'uicore-elements'),
'type' => Controls_Manager::SLIDER,
'size_units' => ['px'],
'range' => [
'px' => [
'min' => 0,
'max' => 30,
],
],
'default' => [
'unit' => 'px',
'size' => 8,
],
'selectors' => [
'{{WRAPPER}} .ui-e-' . $position . ' ' => 'gap: {{SIZE}}px;',
],
]
);
$this->add_control(
$position . '_meta_separator',
[
'label' => __('Separator', 'uicore-elements'),
'type' => Controls_Manager::TEXT,
]
);
if ($position === 'top') {
$this->add_control(
$position . '_meta_placement',
[
'label' => __('Items placement', 'uicore-elements'),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => [
'start left' => __('Top Left', 'uicore-elements'),
'start right' => __('Top Right', 'uicore-elements'),
'end left' => __('Bottom Left', 'uicore-elements'),
'end right' => __('Bottom Right', 'uicore-elements'),
],
'selectors' => [
'{{WRAPPER}} .ui-e-post-top-meta' => 'place-content: {{VALUE}};',
],
]
);
}
}
function get_meta_the_author($mode)
{
global $post;
$author_id = $post->post_author;
$author_name = get_the_author_meta('display_name', $author_id);
// name, full, avatar
if ($mode === 'avatar') {
$display = '';
} elseif ($mode === 'full') {
$display = '
' . esc_html($author_name);
} else {
$display = esc_html($author_name);
}
$link = sprintf(
/* translators: 1: Author archive url, 2: Author meta title, 3: Author display name */
'%3$s',
esc_url(get_author_posts_url($author_id)),
/* translators: %s: Author's display name. */
esc_attr(sprintf(__('View %s’s posts', 'uicore-elements'), esc_html($author_name))),
$display
);
return $link;
}
function get_woo_meta($type, $meta = null)
{
global $product;
if (empty($product)) {
return 'No product found.';
}
switch ($type) {
case 'product price':
return $product->get_price_html();
case 'product rating':
return wc_get_rating_html($product->get_average_rating());
case 'product category':
return get_the_term_list($product->get_id(), 'product_cat', '', ', ', '');
case 'product tag':
return get_the_term_list($product->get_id(), 'product_tag', '', ', ', '');
case 'product stock':
return $this->get_product_stock_for_widget_meta($product, $meta);
case 'product attribute':
return $this->print_product_attributes($product);
case 'product sale':
return $product->is_on_sale() ? esc_html__('Sale!', 'uicore-elements') : '';
default:
return 'Invalid meta type.';
}
}
/**
* Get the product stock quantity for Advanced Product widget meta. If the product is variable, return the highest stock quantity among its variations.
* TODO: this function should be part of the product TRAIT, but product trait uses this meta trait, so we'd have a circular dependency.
*
* @param WC_Product $product The WooCommerce product object.
* @param array $meta The meta settings array.
*/
function get_product_stock_for_widget_meta($product, $meta)
{
// In/out of stock return
if (isset($meta['stock_type']) && $meta['stock_type'] === 'in') {
$in_stock = false;
if ($product->is_type('variable')) {
foreach ($product->get_children() as $child_id) {
$variation = wc_get_product($child_id);
if ($variation && $variation->is_in_stock()) {
$in_stock = true;
break;
}
}
} else {
$in_stock = $product->is_in_stock();
}
return $in_stock
? '' . esc_html($meta['in_stock_text'] ?? __('In stock', 'uicore-elements')) . ''
: '' . esc_html($meta['out_of_stock_text'] ?? __('Out of stock', 'uicore-elements')) . '';
}
// Quantity return
if ($product->is_type('variable')) {
$qty = 0;
// Find the maximum stock quantity among variations
foreach ($product->get_available_variations() as $variation) {
$obj = wc_get_product($variation['variation_id']);
if ($obj->managing_stock()) {
$stock = $obj->get_stock_quantity();
if ($stock > $qty) {
$qty = $stock;
}
}
}
return $qty > 0
? '' . esc_html($qty) . ''
: '' . esc_html($meta['out_of_stock_text'] ?? __('Out of stock', 'uicore-elements')) . '';
}
if (!$product->managing_stock()) {
return '' . esc_html($meta['in_stock_text'] ?? __('In stock', 'uicore-elements')) . '';
}
return $product->get_stock_quantity() !== null
? $product->get_stock_quantity()
: '';
}
/**
* Gets and prints a list of product attributes. We use a custom function for it because
* `wc_display_product_attributes` uses a table layout wich is not suitable for our widget.
*
* @param WC_Product $product The WooCommerce product object.
* @return string|false The HTML string of product attributes or false if none are visible.
* @since 1.3.13
*/
function print_product_attributes($product)
{
$attributes = $product->get_attributes();
if (empty($attributes)) {
return false;
}
$default = true; // Flag to check if we're actually displaying any attribute
$content = '