# uicore-elements/1.3.17/includes/utils/meta-component.php

UiCore Elements – Free widgets and templates for Elementor, version 1.3.17. 679 lines.

- Page: https://pluginprobe.com/plugins/uicore-elements/1.3.17/code/includes/utils/meta-component.php
- Raw: https://pluginprobe.com/plugins/uicore-elements/1.3.17/raw/includes/utils/meta-component.php
- Modified: 2026-09-15T12:03:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/uicore-elements/1.3.17/code/includes/utils/meta-component.php#L10-L20`.

```php
<?php

namespace UiCoreElements\Utils;

use Elementor\Controls_Manager;
use Elementor\Group_Control_Typography;
use UiCoreElements\Helper;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

trait Meta_Trait
{

    function get_meta_content_controls($product_metas = false)
    {

        // Meta options
        $options = [
            'none' => __('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('<a href="https://wordpress.org/documentation/article/customize-date-and-time-format/" target="_blank">%s</a>', 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 = '<img class="ui-e-meta-avatar" src="' . esc_url(get_avatar_url($author_id, array('size' => 100))) . '" />';
        } elseif ($mode === 'full') {
            $display = '<img class="ui-e-meta-avatar" src="' . esc_url(get_avatar_url($author_id, array('size' => 100))) . '" /> ' . 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 */
            '<a href="%1$s" title="%2$s" rel="author">%3$s</a>',
            esc_url(get_author_posts_url($author_id)),
            /* translators: %s: Author's display name. */
            esc_attr(sprintf(__('View %s&#8217;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
                ? '<span class="in-stock">' . esc_html($meta['in_stock_text'] ?? __('In stock', 'uicore-elements')) . '</span>'
                : '<span class="out-of-stock">' . esc_html($meta['out_of_stock_text'] ?? __('Out of stock', 'uicore-elements')) . '</span>';
        }

        // 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
                ? '<span class="in-stock">' . esc_html($qty) . '</span>'
                : '<span class="out-of-stock">' . esc_html($meta['out_of_stock_text'] ?? __('Out of stock', 'uicore-elements')) . '</span>';
        }

        if (!$product->managing_stock()) {
            return '<span class="in-stock">' . esc_html($meta['in_stock_text'] ?? __('In stock', 'uicore-elements')) . '</span>';
        }

        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 = '<ul class="ui-e-product-attributes">';

        foreach ($attributes as $attribute) {
            if (! $attribute->get_visible()) {
                continue;
            }

            // We only want to display default attributes here that are not using framework swatches
            $swatch = $this->get_swatch_type($attribute->get_name());
            if ($swatch && in_array($swatch, ['color', 'label', 'button', 'image'])) {
                continue;
            }

            $default = false; // Safe to output html
            $name  = wc_attribute_label($attribute->get_name());
            $value = '';

            if ($attribute->is_taxonomy()) {
                $taxonomy = $attribute->get_name();
                $terms = wc_get_product_terms(
                    $product->get_id(),
                    $taxonomy,
                    ['fields' => 'all']
                );

                $term_links = [];
                $taxonomy_obj = get_taxonomy($taxonomy);
                $has_archive = $taxonomy_obj && $taxonomy_obj->public && $taxonomy_obj->rewrite && !empty($taxonomy_obj->rewrite['slug']);

                foreach ($terms as $term) {
                    if ($has_archive && get_term_link($term)) {
                        $term_links[] = '<a href="' . esc_url(get_term_link($term)) . '">' . esc_html($term->name) . '</a>';
                    } else {
                        $term_links[] = esc_html($term->name);
                    }
                }
                $value = implode(', ', $term_links);
            } else {
                $value = implode(', ', $attribute->get_options());
            }

            if (empty($value)) {
                continue;
            }

            $content .= '<li>';
            $content .= '<strong>' . esc_html($name) . ':</strong> ';
            $content .= $value;
            $content .= '</li>';
        }

        if ($default) {
            return false;
        }

        $content .= '</ul>';
        return $content;
    }

    /**
     * Get the attribute swatch type from Uicore Framework plugin.
     *
     * @return string The swatch type.
     * @since 1.3.15
     */
    function get_swatch_type($attribute_slug)
    {
        if (!class_exists('Uicore\WooCommerce\Swatches') && !function_exists('get_attribute_swatch_type')) {
            return false;
        }

        return \Uicore\WooCommerce\Swatches::get_attribute_swatch_type($attribute_slug);
    }

    function display_meta($meta, $product_id = null)
    {

        if ($meta['type'] === 'none')
            return;

        $content = '';
        $wrapper = '<div class="ui-e-meta-item">';
        $type    = $meta['type'];
        $prefix  = $meta['before'] ? '<span>' . esc_html($meta['before']) . '</span>' : '';
        $suffix  = $meta['after'] ? '<span class="ui-e-meta-after">' . esc_html($meta['after']) . '</span>' : '';

        ob_start();
        \Elementor\Icons_Manager::render_icon($meta['icon'], ['aria-hidden' => 'true', 'class' => 'ui-e-meta-icon'], 'span');
        $icon = ob_get_clean();

        // Build content
        switch ($type) {
            case 'author':
                $content .= $this->get_meta_the_author($meta['autor_display']);  // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                break;
            case 'date':
                $content .= Helper::format_date(get_the_date('U'), $meta['date_format'], $meta['custom_format']); // 'U' param returns the date in timestamp, necessary for format_date()
                break;
            case 'updated date':
                $content .= Helper::format_date(get_the_modified_date('U'), $meta['date_format'], $meta['custom_format']); // 'U' param returns the date in timestamp, necessary for format_date()
                break;
            case 'category':
                $content .= Helper::get_taxonomy('category');
                break;
            case 'tag':
                $content .= Helper::get_taxonomy('post_tag');
                break;
            case 'portfolio category':
                $content .= Helper::get_taxonomy('portfolio_category');
                break;
            case 'comment':
                $content .= esc_html(get_comments_number());
                break;
            case 'custom meta':
                $content .= Helper::get_custom_meta($meta['type_custom'], $product_id);
                break;
            case 'custom taxonomy':
                $content .= Helper::get_taxonomy($meta['type_custom']);
                break;
            case 'custom html':
                $content .= wp_kses_post($meta['html_custom']);
                break;
            case 'reading time':
                $content .= esc_html(Helper::get_reading_time());
                break;
            case 'excerpt':
                $content .= esc_html(get_the_excerpt());
                break;
            default:
                if (strpos($type, 'product') === 0) {
                    $data = $this->get_woo_meta($type, $meta);
                    if ($data === false) return;
                    $content .= wp_kses_post($data);
                } else {
                    echo \esc_html($type);
                }
                break;
        }

        // Only output if there's content
        if (!empty($content)) {
            echo $wrapper . Helper::esc_svg($icon) . $prefix . $content . $suffix . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        }
    }
}

```
