Server IP : 104.21.93.192 / Your IP : 216.73.216.73 Web Server : LiteSpeed System : Linux premium900.web-hosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 User : redwjova ( 1790) PHP Version : 8.1.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/redwjova/clevorio.com/wp-content/themes/smart-mag/lib/vendor/plugins/ |
Upload File : |
PK 03Y[���8 �8 smartmag-core/smartmag-core.php<?php /** * SmartMag Core * * Plugin Name: SmartMag Core * Description: Elements and core functionality for SmartMag Theme. * Version: 1.5.0 * Author: ThemeSphere * Author URI: https://theme-sphere.com * License: ThemeForest Split * License URI: https://themeforest.net/licenses/standard * Text Domain: smartmag * Domain Path: /languages * Requires PHP: 7.1 */ defined('WPINC') || exit; class SmartMag_Core { const VERSION = '1.5.0'; // Due to legacy reasons, it's named smartmag without dash. const THEME_SLUG = 'smartmag'; protected static $instance; /** * Path to plugin folder, trailing slashed. */ public $path; public $path_url; /** * Flag to indicat plugin successfuly ran init. This confirms no conflicts. */ public $did_init = false; /** * Whether the correct accompanying theme exists or implementations are done. * * @var boolean */ public $theme_supports = []; public function __construct() { $this->path = plugin_dir_path(__FILE__); // URL for the plugin dir $this->path_url = plugin_dir_url(__FILE__); /** * Register autoloader. Usually uses the loader from theme if present. */ if (!class_exists('\Bunyad\Lib\Loader', false)) { require_once $this->path . 'lib/loader.php'; } $path = $this->path; $namespaces = [ 'SmartMag\\' => $path . 'inc', 'Bunyad\Blocks\\' => [ 'search_reverse' => true, 'paths' => $path . 'blocks', ], 'Bunyad\Elementor\\' => $path . 'inc/elementor', 'Bunyad\Widgets\\' => $path . 'inc/widgets', 'Bunyad\Studio\\' => $path . 'inc/studio', ]; $loader = new \Bunyad\Lib\Loader($namespaces); } /** * Setup to be hooked after setup theme. */ public function init() { $this->did_init = true; $lib_path = $this->path . 'lib/'; /** * When one of our themes isn't active, use shims */ if (!class_exists('Bunyad_Core')) { require_once $this->path . 'lib/bunyad.php'; require_once $this->path . 'inc/bunyad.php'; require_once $this->path . 'lib/util.php'; require_once $this->path . 'blocks/helpers.php'; // Set path to local as theme isn't active Bunyad::$fallback_path = $lib_path; Bunyad::options()->set_config([ 'theme_prefix' => self::THEME_SLUG, 'meta_prefix' => '_bunyad' ]); } else { // If we're here, there's a ThemeSphere theme active. All ThemeSphere themes have // their own core plugins. Theme's own core plugin should be used instead. if (Bunyad::options()->get_config('theme_name') !== self::THEME_SLUG) { return; } $this->theme_supports = ['blocks' => true]; } // Outdated Bunyad from an old theme? Cannot continue. if (!property_exists('Bunyad', 'fallback_path')) { return; } // Set local fallback for some components not packaged with theme. Bunyad::$fallback_path = $lib_path; /** * Setup filters and data */ // Elementor specific if (class_exists('\Elementor\Plugin') || did_action('elementor/loaded')) { $elementor = new \Bunyad\Elementor\Module; $elementor->register_hooks(); // And the studio. new \Bunyad\Studio\Module; } // Admin related actions add_action('admin_init', [$this, 'register_metaboxes']); // User profile fields add_filter('user_contactmethods', [$this, 'add_profile_fields']); // Register assets add_action('admin_enqueue_scripts', [$this, 'admin_assets']); // Setup blocks $this->setup_blocks(); // Setup widgets - hook will be handled by Bunyad_Widgets. $this->setup_widgets(); // Performance optimizations. require_once $this->path . 'inc/optimize.php'; // Social Share and Follow. require_once $this->path . 'inc/social-share.php'; // Classic Editor features if (is_admin()) { require_once $this->path . 'inc/editor.php'; } // Init menu helper classes Bunyad::menus(); add_filter('bunyad_custom_menu_fields', [$this, 'custom_menu_fields']); // Init reviews. Bunyad::register('reviews', [ 'object' => new SmartMag\Reviews\Module ]); // Translation: To be loaded via theme. Uncomment below to do a local translate. // load_plugin_textdomain( // 'bunyad', // false, // basename($this->path) . '/languages' // ); /** * Old version migration. */ // DEBUG: update_option('smartmag_convert_from_v3', 1); if (is_admin() && get_option('smartmag_convert_from_v3')) { new SmartMag\ConvertV5\ConvertV5; } } /** * Register our custom metaboxes. Should run admin side only via admin_init. * * Note: You may use filter bunyad_meta_boxes from lib/meta-boxes.php file to modify or extend these * in a Child Theme or plugin. * * Example, to enable post options metabox on CPT my-cpt: * * add_filter('bunyad_meta_boxes', function($meta) { * array_push($meta['post-options']['page'], 'my-cpt'); * return $meta; * }); */ public function register_metaboxes() { // Set active metaboxes $meta_boxes = (array) Bunyad::options()->get_config('meta_boxes'); $meta_boxes = array_merge($meta_boxes, [ // Enabled metaboxes and prefs - id is prefixed with _bunyad_ in init() method of lib/admin/meta-boxes.php 'post-options' => [ 'id' => 'post-options', 'title' => esc_html_x('Post Options', 'Admin: Meta', 'bunyad-admin'), 'priority' => 'high', 'page' => ['post'], 'form' => $this->path . 'metaboxes/post-options.php', 'options' => $this->path . 'metaboxes/options/post.php', ], 'page-options' => [ 'id' => 'page-options', 'title' => esc_html_x('Page Options', 'Admin: Meta', 'bunyad-admin'), 'priority' => 'high', 'page' => ['page'], 'form' => $this->path . 'metaboxes/page-options.php', 'options' => $this->path . 'metaboxes/options/page.php', ], ]); Bunyad::options()->set_config('meta_boxes', $meta_boxes); Bunyad::load_file('admin/meta-base'); Bunyad::factory('admin/meta-boxes'); /** * Setup term meta custom fields. */ $meta = Bunyad::factory('admin/meta-terms', true); $meta->taxonomy = 'category'; $meta->options_file = $this->path . 'metaboxes/terms/category-options.php'; $meta->form_file = $this->path . 'metaboxes/terms/category-form.php'; $meta->init(); } /** * Register assets for admin context only. */ public function admin_assets($hook) { wp_enqueue_style( 'smartmag-admin', $this->path_url . 'css/admin/common.css', [], self::VERSION ); wp_register_script( 'bunyad-lib-options', $this->path_url . 'lib/js/admin/options.js', ['jquery'], self::VERSION ); // We need this globally as widgets may be used on widget screen, customizer, or // in a pagebuilder like Elementor. wp_enqueue_script( 'bunyad-widgets', $this->path_url . 'js/widgets.js', ['jquery', 'wp-api-request'], self::VERSION ); // Enqueue selectize only when theme is active. if (Bunyad::get('theme')) { wp_enqueue_script( 'bunyad-customize-selectbox', get_template_directory_uri() . '/inc/core/assets/js/selectize.js', ['jquery'], Bunyad::options()->get_config('theme_version') ); wp_enqueue_style( 'bunyad-customize-selectbox', get_template_directory_uri() . '/inc/core/assets/css/selectize.css', [], Bunyad::options()->get_config('theme_version') ); } } /** * Setup Widgets */ public function setup_widgets() { /** @var \Bunyad_Widgets $widgets */ $widgets = Bunyad::get('widgets'); if (!is_object($widgets)) { return; } // Configure the object. $widgets->path = $this->path; $widgets->prefix = 'SmartMag_Widgets_'; $widgets->active = [ 'about', 'tabbed-recent', 'tabber', 'social-follow', 'bbp-login', 'latest-reviews', 'flickr' ]; // Only add these for legacy. if (Bunyad::options()->legacy_mode) { $widgets->active = array_merge($widgets->active, [ 'blocks', 'ads', 'latest-posts', 'popular-posts', ]); } /** * Block Widgets. */ add_action('widgets_init', function() { // Load the class map to prevent unnecessary autoload to save resources. include_once \SmartMag_Core::instance()->path . 'inc/widgets/classmap-widgets.php'; // Block widgets to load. $blocks = [ 'Loops\Grid', 'Loops\Overlay', 'Loops\PostsSmall', 'Loops\Highlights', 'Newsletter', 'Codes' ]; foreach ($blocks as $block) { $class = 'Bunyad\Widgets\\' . $block . '_Block'; register_widget($class); } }); } /** * Setup blocks and their shortcodes. */ public function setup_blocks() { require_once $this->path . 'inc/shortcodes.php'; /** * Register all the blocks */ $blocks = [ 'ts_loop_feat_grid' => 'Loops\FeatGrid', 'ts_loop_grid' => 'Loops\Grid', 'ts_loop_large' => 'Loops\Large', 'ts_loop_overlay' => 'Loops\Overlay', 'ts_loop_posts_list' => 'Loops\PostsList', 'ts_loop_posts_small' => 'Loops\PostsSmall', 'ts_loop_news_focus' => 'Loops\NewsFocus', 'ts_loop_focus_grid' => 'Loops\FocusGrid', 'ts_loop_highlights' => 'Loops\Highlights', 'ts_block_newsletter' => 'Newsletter', 'ts_block_heading' => 'Heading', 'ts_breadcrumbs' => 'Breadcrumbs', 'ts_social_icons' => 'SocialIcons', // Blocks without shortcodes. 1 => 'Codes', ]; // Register with elementor. add_filter('bunyad_elementor_widgets', function($value) use ($blocks) { return array_merge((array) $value, $blocks); }); // Register shortcodes. foreach ($blocks as $id => $block) { if (!is_string($id)) { continue; } Bunyad::get('shortcodes')->add([ $id => [ 'render' => 'block', 'block_class' => $block ] ]); } // // Some necessary legacy shortcodes. // if (Bunyad::options()->legacy_mode) { Bunyad::get('shortcodes')->add([ 'latest_gallery' => [ 'render' => 'block', 'map_attribs' => [ 'number' => 'posts', 'format' => 'post_formats', 'tax_tag' => 'tags', 'title' => 'heading', ], 'alias' => 'ts_loop_grid', 'attribs' => [ 'post_formats' => 'gallery', // Intentionally '0' as false could default to ''. 'cat_labels' => '0', 'posts' => 5, 'title' => '', 'cat' => '', 'type' => '', 'tax_tag' => '', 'offset' => '', 'post_type' => '', 'show_content' => false, 'excerpts' => false, 'meta_items_default' => false, 'carousel' => true, 'show_post_formats' => false, 'carousel_slides' => 1, 'carousel_dots' => false, 'meta_below' => [], 'meta_above' => [], ] ] ]); } /** * Other shortcodes. */ Bunyad::get('shortcodes')->add([ 'main-color' => [ 'render' => function($atts) { return '<span class="main-color">'. esc_html($atts['text']) .'</span>'; }, 'attribs' => ['text' => ''] ], ]); } /** * Filter callback: Custom menu fields. * * Required for both back-end and front-end. * * @see Bunyad_Menus::init() */ public function custom_menu_fields($fields) { $fields = [ 'mega_menu' => [ 'label' => esc_html__('Mega Menu', 'bunyad-admin'), 'element' => [ 'type' => 'select', 'class' => 'widefat', 'options' => [ 0 => esc_html__('Disabled', 'bunyad-admin'), 'category-a' => esc_html__('Category Modern', 'bunyad-admin'), 'category' => esc_html__('Category Legacy: (Subcats, Featured & Recent)', 'bunyad-admin'), 'normal' => esc_html__('Mega Menu for Links', 'bunyad-admin') ] ], 'parent_only' => true, ] ]; return $fields; } /** * Filter callback: Add theme-specific profile fields */ public function add_profile_fields($fields) { $fields = array_merge((array) $fields, [ 'bunyad_facebook' => esc_html__('Facebook URL', 'bunyad-admin'), 'bunyad_twitter' => esc_html__('X (Twitter) URL', 'bunyad-admin'), 'bunyad_instagram' => esc_html__('Instagram URL', 'bunyad-admin'), 'bunyad_pinterest' => esc_html__('Pinterest URL', 'bunyad-admin'), 'bunyad_bloglovin' => esc_html__('BlogLovin URL', 'bunyad-admin'), 'bunyad_dribble' => esc_html__('Dribble URL', 'bunyad-admin'), 'bunyad_linkedin' => esc_html__('LinkedIn URL', 'bunyad-admin'), 'bunyad_tumblr' => esc_html__('Tumblr URL', 'bunyad-admin'), ]); return $fields; } /** * Singleton instance * * @return SmartMag_Core */ public static function instance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } } /** * Add notice and bail if there's an incompatible plugin active. * * Note: Needed for outdated libs in ContentBerg Core. Not required for others, but * good practice to keep them out for conflicting features. */ add_action('after_setup_theme', function() { $core_plugins = [ 'contentberg-core' => 'ContentBerg_Core', 'cheerup-core' => 'CheerUp_Core', 'bunyad-widgets' => 'Bunyad_Widgets', ]; $conflict = false; foreach ($core_plugins as $plugin => $class) { // Check but don't auto-load this class. if (class_exists($class, false)) { add_action('admin_notices', function() use ($plugin) { // Path to plugin/plugin.php file. $plugin_file = $plugin . '/' . $plugin . '.php'; include_once ABSPATH . 'wp-admin/includes/plugin.php'; $plugin_full_path = WP_PLUGIN_DIR . '/' . $plugin_file; if (file_exists($plugin_full_path)) { $plugin_data = get_plugin_data($plugin_full_path); } else { $plugin_data = ['Name' => $plugin]; } $message = sprintf( 'Plugin %1$s is incompatible with current theme\'s Core Plugin. Please deactivate.', '<strong>' . esc_html($plugin_data['Name']) . '</strong>' ); printf( '<div class="notice notice-error"><h3>Important:</h3><p>%1$s</p></div>', wp_kses_post($message) ); }); $conflict = true; } } if ($conflict) { return; } /** * Initialize the plugin at correct hook. */ $smartmag = SmartMag_Core::instance(); add_action('after_setup_theme', [$smartmag, 'init']); }, 1); PK 03Y@ً3 smartmag-core/blocks/ajax.php<?php namespace Bunyad\Blocks; use Bunyad; /** * Helper methods for Blocks & Listing Archives */ class Ajax { public function init() { add_action('wp_ajax_nopriv_bunyad_block', [$this, 'render_block']); add_action('wp_ajax_bunyad_block', [$this, 'render_block']); } /** * Callback: AJAX request, render block. * * @return void */ public function render_block() { if (!isset($_REQUEST['block'])) { wp_die('0'); } $block = $_REQUEST['block']; if (!isset($block['props']) || !isset($block['id'])) { wp_die('0'); } $block_class = str_replace( 'Bunyad\Blocks\\', '', Bunyad::file_to_class_name($block['id']) ); $block['props'] = (array) $block['props']; $query_type = $block['props']['query_type'] ?? ''; // Can't support main query here, for obvious reasons. if (!in_array($query_type, ['section', 'custom'])) { $block['props']['query_type'] = 'custom'; } if ($query_type === 'section' && empty($block['props']['section_query'])) { $block['props']['query_type'] = 'custom'; } // Set a max posts per page limit to prevent DOS. if (isset($block['props']['posts'])) { $block['props']['posts'] = min(intval($block['props']['posts']), 100); } $block['props'] = $this->process_booleans($block['props']); /** @var \Bunyad\Blocks\Base\LoopBlock $block */ $block = Bunyad::blocks()->load( 'Loops\\' . $block_class, $block['props'] ); $block->render(); wp_die(); } /** * Convert string true/false to boolean values. * * @param array $props * @return array */ protected function process_booleans($props) { foreach ($props as $prop => $value) { if ($value === "true" || $value === "false") { $props[$prop] = \filter_var($value, FILTER_VALIDATE_BOOLEAN); } } return $props; } } PK 03Y�F@� � smartmag-core/blocks/helpers.php<?php namespace Bunyad\Blocks; use Bunyad; /** * Helper methods for Blocks & Listing Archives */ class Helpers { /** * @var \Bunyad\Blocks\Ajax */ public $ajax; public function __construct() { $this->ajax = new Ajax; $this->ajax->init(); } /** * Load a block * * Usage: * load('Loops\Grid'); * * @param string $block Block identifier * @param array $atts Attributes for the block * * @return Base\LoopBlock|bool */ public function load($block, $atts = []) { /** * Locate and initialize the loop post. */ $class = '\\' . __NAMESPACE__ . '\\' . $block; // Fallback to base if not present, for Loops. if (!class_exists($class)) { if (!strstr($block, 'Loops')) { return false; } $class = __NAMESPACE__ . '\\' . 'Base\LoopBlock'; } /** @var Base\LoopBlock $obj */ $obj = new $class($atts); if (!$obj->id) { $obj->set_id($block); } return $obj; } /** * Load legacy loops - for archives, cats, tags etc. * * @return Base\LoopBlock */ public function load_loop($loop, $props = array()) { // Some sane defaults for general loops. $props = array_replace([ 'pagination' => true, 'pagination_type' => Bunyad::options()->pagination_type, 'space_below' => 'none', ], $props); // Set column for ids like loop-3 if (preg_match('/([a-z\-]+)\-(\d)$/i', $loop, $match)) { $loop = $match[1]; $props['columns'] = $match[2]; } // @deprecated Old key maps, just in case. $map = array( 'loop' => 'grid', 'loop-alt' => 'posts-list', // Still needed. 'classic' => 'large', ); // Classic requires large_style if ($loop === 'classic') { $props['large_style'] = 'legacy'; } $id = (array_key_exists($loop, $map) ? $map[$loop] : $loop); $id = 'Loops\\' . Bunyad::file_to_class_name($id); $block = $this->load($id, $props); return $block; } /** * Load a loop post class * * Example: Load the loop class from inc/loop-posts/grid.php if it exists * or fallback to inc/loop-posts/post.php * * @param string $id Loop post id * @param array $props Props to set for loop post * * @return LoopPosts\BasePost */ public function load_post($id, $props = array()) { /** * Locate and initialize the loop post */ $class = __NAMESPACE__ . '\LoopPosts\\' . Bunyad::file_to_class_name($id) . 'Post'; // Fallback to base if not present if (!class_exists($class)) { $class = __NAMESPACE__ . '\LoopPosts\BasePost'; } /** @var LoopPosts\BasePost $obj */ $obj = new $class($props); return $obj; } /** * Get HTML for category label with link. * * Checks global and local settings before generating the output. * * @uses Bunyad::registry()->block_atts The current block attribs in registry * @param boolean $options * @return string|void HTML with category label */ public function cat_label($options = [], $post_id = false) { $options = wp_parse_args($options, [ 'force_show' => false, 'position' => '', 'focusable' => false, ]); $position = $options['position'] ? 'p-' . $options['position'] : ''; $output = sprintf( '<span class="cat-labels cat-labels-overlay c-overlay %1$s"> %2$s </span> ', esc_attr($position), $this->get_categories(null, false, ['focusable' => $options['focusable']]) ); return apply_filters('bunyad_blocks_cat_label', $output); } /** * Categories for meta. * * @param boolean|null $all Display primary/one category or all categories. * @param boolean|int $post_id Post ID. * @param array $options * @return string Rendered HTML. */ public function get_categories($all = null, $post_id = false, $options = []) { // Object has category taxonomy? i.e., is it a post or a valid CPT? if (!is_object_in_taxonomy(get_post_type($post_id), 'category')) { return; } $options = array_replace([ // For accessibility, whether to make it focusable or not. 'focusable' => true ], $options); $categories = apply_filters('the_category_list', get_the_category($post_id), $post_id); $output = []; // Not showing all categories. if (!$all) { $category = $this->get_primary_cat(); $categories = []; if (is_object($category)) { $categories[] = $category; } } foreach ($categories as $category) { $classes = ['category']; if (Bunyad::options()->cat_labels_use_colors) { $classes[] = 'term-color-' . $category->term_id; } $output[] = sprintf( '<a href="%1$s" class="%2$s" rel="category"' . (!$options['focusable'] ? ' tabindex="-1"' : '') . '>%3$s</a>', esc_url(get_category_link($category)), esc_attr(join(' ', $classes)), esc_html($category->name) ); } return join(' ', $output); } /** * Get primary category for a post. * * @param int $post_id * @return object|WP_Error|null */ public function get_primary_cat($post_id = null) { // Object must have category taxonomy? i.e., is it a post or a valid CPT. if (!is_object_in_taxonomy(get_post_type($post_id), 'category')) { return; } // Primary category defined. if (($cat_label = Bunyad::posts()->meta('cat_label', $post_id))) { $category = get_category($cat_label); } // Fallback to using Yoast if available. if (empty($category) && Bunyad::options()->yoast_primary_cat && function_exists('yoast_get_primary_term_id')) { $id = yoast_get_primary_term_id(); $category = $id ? get_term($id) : null; } // This test is needed even if a primary cat is defined to test for its // existence (it might be deleted etc.) if (empty($category)) { $category = current(get_the_category($post_id)); } return apply_filters('bunyad_get_primary_cat', $category); } /** * Get relative width for current block, based on sidebar or data stored * in the registry. * * @return float Column width in percent number, example 66. */ public function get_relative_width() { // Set current column width weight (width/100) - used to determine image sizing $col_relative_width = 1; if (isset(Bunyad::registry()->layout['col_relative_width'])) { $col_relative_width = Bunyad::registry()->layout['col_relative_width']; } // Adjust relative width if there's a sidebar if (Bunyad::core()->get_sidebar() !== 'none') { $col_relative_width = ($col_relative_width * (8/12)); } return $col_relative_width * 100; } } // init and make available in Bunyad::get('blocks') Bunyad::register('blocks', array( 'class' => '\Bunyad\Blocks\Helpers', 'init' => true )); PK 03Y�%�� � # smartmag-core/blocks/base/block.php<?php namespace Bunyad\Blocks\Base; /** * Base Blocks Class. */ abstract class Block { /** * @var array Properties/attributes for the block. */ public $props = []; /** * @var array Original props, after filtering by setup_props(). */ protected $orig_props = []; /** * @var string Identifier of the block - may also be used for block view. */ public $id = ''; /** * @param array $props */ public function __construct($props = []) { if (!is_array($props)) { $props = []; } $props = $this->setup_props($props); // Save originally provided props, after unknowns are removed. $this->orig_props = $props; // Override default props with processed props (by setup_props()). $this->props = array_replace( $this->get_default_props(), apply_filters('bunyad_blocks_setup_props', $props, $this->id) ); $this->init(); } public function init() {} /** * Get default props for this block. * * @return array */ abstract public static function get_default_props(); /** * Render and print the output, such as HTML. */ abstract public function render(); /** * Setup / process props before overriding the defaults with provided. * * By default, removes: * * 1. Unrecognized props (not in defaults array). * 2. When the value is _default (forces to use default prop). * 3. Props with same value as default. * * To be used to extend properties for this block based on provided props, or when * some computation is needed that's not available to the method get_default_props(). * * @param array $props * @return array */ public function setup_props(array $props) { $defaults = $this->get_default_props(); foreach ($props as $key => $value) { // Remove if unrecognized prop or has _default value. if (!array_key_exists($key, $defaults) || $value === '_default') { unset($props[$key]); continue; } /** * If the default prop value is an array, the expected value is an array, so * strings should be split by comma separation. */ if (is_array($defaults[$key])) { $orig_is_array = true; // If it's an alias, check if the original is an array. if (array_key_exists('alias', $defaults[$key])) { $ref = $defaults[$key]['alias']; if (!is_array($defaults[$ref])) { $orig_is_array = false; } } // Nothing to do anymore. if (!$orig_is_array) { continue; } // Not empty string but an array is expected. if ($value && is_string($value)) { $value = array_map( 'trim', explode(',', $value) ); } // An array is expected for this key, cast it if not empty. $props[$key] = $value ? (array) $value : []; } } /** * Removes defaults for external non-programmatic calls. For internal calls, we generally * wish to use exactly what is specified in props. Otherwise, default props will be * removed and set to global props via map_global_props(). */ if (!empty($props['is_sc_call'])) { $props = $this->remove_defaults($props, $defaults); } // ThemeSphere theme active, add in the defaults. if (class_exists('\Bunyad', false) && \Bunyad::get('theme')) { $props = $this->map_global_props($props); } return $props; } /** * Remove props with same value as default. * * Can help if correct global/default value is not set. Also required so global default * options can be added via self::map_global_props(). * * @param array $props * @param array $defaults * @return array */ protected function remove_defaults(array $props, $defaults = []) { foreach ($props as $key => $value) { /** * We don't do strict matching in all cases for removal. Based on default prop type: * * - Strict comparison for null type. * - Following are considered equal: * * 0 == '' * false == '0' * false == '' * true == '1' * true == 1 * 10 == '10' * [] == '' * * - Loose comparison done for boolean, integer, float (double). * - Strict comparison with cast for string type. * - Arrays strict comparison to allow all order sort, with cast. */ $remove = false; $default = $defaults[$key]; switch (gettype($default)) { case 'boolean': case 'integer': case 'double': $remove = $default == $value; break; case 'string': if (!is_array($value)) { // Everything but arrays. Good to cast to string first. $remove = (string) $default === (string) $value; } break; case 'array': $remove = (array) $default === (array) $value; break; default: $remove = $default === $value; break; } if ($remove) { unset($props[$key]); } } return $props; } /** * Add in global props as specified. Only invoked when a ThemeSphere theme is active. * * Called via setup_props() method after removing default props. Only overrides are * preserved. * * Proper Usage: * 1. Defaults/global options should be overridden by provided props. * <code>return array_replace($global_options, $props);</code> * * @param array $props Props after processed by self::setup_props(). * @return array */ public function map_global_props($props) { return $props; } /** * Get all the props. * * @return array */ public function get_props() { return $this->props; } /** * Magic method for print / echo. */ public function __toString() { ob_start(); $this->render(); return ob_get_clean(); } }PK 03Y�kL; ; , smartmag-core/blocks/base/carousel-trait.php<?php namespace Bunyad\Blocks\Base; /** * Share methods for implementing carousel support in a loop block. */ trait CarouselTrait { /** * Gets the carousel related props. * * @return array */ public static function get_carousel_props() { return [ 'carousel' => false, 'carousel_slides' => '', 'carousel_slides_md' => '', 'carousel_slides_sm' => '', 'carousel_dots' => true, 'carousel_arrows' => 'b', 'carousel_autoplay' => false, 'carousel_play_speed' => '', ]; } /** * Setup carousel for this block, if supported. */ protected function setup_carousel() { if (!$this->props['carousel']) { return; } // Enqueue slick slider. if (wp_script_is('smartmag-slick', 'registered')) { wp_enqueue_script('smartmag-slick'); } // Pagination is not available for carousels. if ($this->props['pagination']) { $this->props['pagination'] = 0; } $this->props['slide_attrs'] = isset($this->props['slide_attrs']) ? $this->props['slide_attrs'] : []; $this->props['slide_attrs'] = array_replace($this->props['slide_attrs'], [ 'data-slider' => 'carousel', 'data-autoplay' => $this->props['carousel_autoplay'], 'data-speed' => $this->props['carousel_play_speed'], 'data-slides' => ( $this->props['carousel_slides'] ? $this->props['carousel_slides'] : $this->props['columns'] ), 'data-slides-md' => $this->props['carousel_slides_md'], 'data-slides-sm' => $this->props['carousel_slides_sm'], 'data-arrows' => $this->props['carousel_arrows'], 'data-dots' => $this->props['carousel_dots'], ]); // Add the classes. $this->props['class'] = array_merge( $this->props['class'], [ 'common-slider loop-carousel', $this->props['carousel_arrows'] ? 'arrow-hover' : '', $this->props['carousel_arrows'] ? 'slider-arrow-' . $this->props['carousel_arrows'] : '' ] ); // Add slide attrs to wrap attrs if it exists. $this->props['wrap_attrs'] = array_replace( $this->props['wrap_attrs'], $this->props['slide_attrs'] ); } }PK 03Y� -Ȇj �j ( smartmag-core/blocks/base/loop-block.php<?php namespace Bunyad\Blocks\Base; use \Bunyad; use \WP_Query; /** * Base Blocks Class for Loops type blocks - should be extended for other blocks * * Note: This is not an abstract class and may be used standalone. More of template method. */ class LoopBlock extends Block { /** * @var string Block type */ public $type = 'loop'; /** * @var boolean Is the block processed yet */ public $processed = false; /** * @var array Internal data, extended by data retrieved from Query::setup() */ public $data = [ 'unique_id' => null ]; /** * @var \WP_Query */ public $query; /** * @var string ID for the view file. Defaults to $this->id. */ public $view_id; /** * @var integer Number of posts rendered so far. */ protected $rendered_posts = 0; /** * @param array $props */ public function __construct($props = []) { parent::__construct($props); // Resolve aliases $this->props = $this->resolve_aliases($this->props); // Setup enqueues if any add_action('wp_enqueue_scripts', [$this, 'register_assets']); } /** * Get props related to query. * * @return array */ public static function get_query_props() { $query_props = [ 'posts' => 4, 'offset' => '', // Sticky posts generally only enabled for home/blog archives. 'sticky_posts' => false, // Internal for section queries, and passed 'query' objects. // Different from offset: These posts are manually skipped in the loop. 'skip_posts' => 0, // Main category 'cat' => '', // Tag slugs - separated by commas. Not in 'terms' to allow limit by tags AND cats. 'tags' => [], // Categories, or custom taxonomies' term ids, or author ids. 'terms' => [], 'exclude_terms' => [], // Limit to a specific custom taxonomy 'taxonomy' => '', // Custom taxonomy IDs to use 'tax_ids' => [], 'sort_order' => '', 'sort_by' => '', // Only for JetPack views sort. 'sort_days' => 30, 'post_formats' => [], // Multiple supported only for legacy compat. Recommended: Single value. 'post_type' => '', // Specific post IDs 'post_ids' => [], // Skip posts by ids. // Special: Also supported for main query. 'exclude_ids' => [], // Exclude posts by tags, by ids or slugs. 'exclude_tags' => [], 'pagination' => '', // Only show review posts if enabled. 'reviews_only' => false, // A custom identifier for programmatically changing things. 'query_id' => '', // Exclude current post on a single post page. 'exclude_current' => false, // Others that may be used: // 'page' => 0 ]; return $query_props; } /** * Default properties for the block. * * @param string $type Type of props to return. * @return array */ public static function get_default_props() { // Config props (not for sc) $props = [ // Expected: // null|empty: Use global $wp_query or legacy $bunyad_loop, ignores all query props // 'custom': Create create based on provided props. // 'section': Use section query. Data must be provided in section_query. 'query_type' => '', // Forces to use the specified query. 'query' => null, // WP_Query|array Section query data. 'section_query' => [], // Whether is it called via a shortcode / builder - adds .block-sc to wrap 'is_sc_call' => false, // Style Variation for the block. 'style' => '', // Dark or normal. 'scheme' => '', // Many blocks support columns setting. 'columns' => '', 'columns_main' => '', 'columns_medium' => '', 'columns_small' => '', 'heading' => '', 'heading_type' => '', 'heading_align' => 'left', 'heading_link' => '', 'heading_more' => '', 'heading_more_text' => '', 'heading_more_link' => '', 'heading_colors' => '', 'heading_tag' => 'h4', // Values: category, tag, or taxonomy - if empty, defaults to category 'filters' => false, 'filters_terms' => [], 'filters_tags' => [], // When using custom taxonomy 'filters_tax' => '', // Current filter to apply. 'filter' => '', // Loop specific props 'excerpts' => true, 'excerpt_length' => 0, 'excerpt_lines' => '', 'cat_labels' => '', 'cat_labels_pos' => '', 'read_more' => '', 'reviews' => '', 'show_post_formats' => true, 'post_formats_pos' => '', 'show_content' => true, 'content_center' => false, // When empty, automatically inferred based on columns. 'show_media' => true, 'force_image' => '', 'media_ratio' => '', 'media_ratio_custom' => '', // Only for some blocks: list, small. 'media_width' => '', 'media_style_shadow' => '', // Define a parent container to get relative width from. 'container_width' => '', 'separators' => false, 'separators_cols' => false, // Margin below block 'space_below' => '', 'column_gap' => '', 'meta_items_default' => true, 'meta_above' => [], 'meta_below' => [], // Do not change default of empty string value for loop options field to work. 'meta_sponsor_items_default' => true, 'meta_sponsor' => '', 'meta_sponsor_label' => '', 'meta_sponsor_logo' => '', 'meta_sponsor_info' => '', 'meta_sponsor_above' => [], 'meta_sponsor_below' => [], 'show_title' => true, 'title_tag' => 'h2', 'title_lines' => '', // These meta items should not get a default value as global settings are important. 'meta_align' => '', 'meta_cat_style' => 'text', 'meta_author_img' => false, // Pagination settings. 'pagination_type' => 'numbers-ajax', 'load_more_style' => '', 'pagination_links' => true, // Pagination may be enabled, but may not be always rendered, such as for multi-blocks. 'pagination_render' => true, // Number of posts to skip lazyload image for. 'skip_lazy_number' => 0, // Only when query_type is related. 'query_yarpp' => false, // Legacy Aliases (DEPRECATED) 'link' => ['alias' => 'heading_link'], 'post_format' => ['alias' => 'post_formats'], 'title' => ['alias' => 'heading'], 'cats' => ['alias' => 'terms'], ]; $props = $props + static::get_query_props(); return $props; } /** * Add in some values from global options. */ public function map_global_props($props) { $global = [ 'cat_labels' => Bunyad::options()->get('cat_labels'), 'cat_labels_pos' => Bunyad::options()->get('cat_labels_pos'), 'reviews' => Bunyad::options()->get('loops_reviews'), 'post_formats_pos' => Bunyad::options()->get('post_formats_pos'), 'load_more_style' => Bunyad::options()->get('load_more_style'), 'meta_cat_style' => Bunyad::options()->get('post_meta_cat_style'), 'media_style_shadow' => Bunyad::options()->get('loops_media_style_shadow'), 'meta_sponsor' => Bunyad::options()->get('post_meta_sponsor'), 'meta_sponsor_logo' => Bunyad::options()->get('post_meta_sponsor_logo'), 'meta_sponsor_label' => Bunyad::options()->get('post_meta_sponsor_label'), ]; // Only set this default for listings/internal calls. Blocks/SC do not use the global // setting for these. if (empty($props['is_sc_call'])) { $global += [ 'show_post_formats' => Bunyad::options()->get('post_format_icons'), ]; } // Setting it as it will be frequently used by inheritance too. $props['meta_items_default'] = !isset($props['meta_items_default']) || $props['meta_items_default']; // If not known or explicitly set to default, global meta should be used. if ($props['meta_items_default']) { $global += [ 'meta_above' => Bunyad::options()->get('post_meta_above'), 'meta_below' => Bunyad::options()->get('post_meta_below'), ]; } // Setting it as it will be frequently used by inheritance too. $props['meta_sponsor_items_default'] = !isset($props['meta_sponsor_items_default']) || $props['meta_sponsor_items_default']; // If not known or explicitly set to default, global meta should be used. if ($props['meta_sponsor_items_default']) { $global += [ 'meta_sponsor_above' => Bunyad::options()->get('post_meta_sponsor_above'), 'meta_sponsor_below' => Bunyad::options()->get('post_meta_sponsor_below'), ]; } return array_replace($global, $props); } /** * @inheritDoc */ public function init() { // Setup internal props. These are not set from external call. $this->props += [ 'image' => '', 'image_props' => [], 'class_grid' => ['grid'], // Not all support it yet. 'class' => [], // Loop wrapper div attributes. Some loops use it, not all. 'wrap_attrs' => [], ]; } /** * @inheritDoc */ public function setup_props(array $props) { $props = parent::setup_props($props); if (isset($props['columns_main'])) { $props['columns'] = $props['columns_main']; } // Clean up section_query props by only using valid. if (isset($props['section_query'])) { $props['section_query_type'] = isset($props['section_query']['query_type']) ? $props['section_query']['query_type'] : ''; $props['section_query'] = array_intersect_key( $props['section_query'], $this->get_query_props() ); } else if (isset($props['query_type']) && $props['query_type'] === 'section') { // section_query doesn't exist, so remove it. $props['query_type'] = 'custom'; } return $props; } /** * Set the block identifier * * @return $this */ public function set_id($id) { $this->id = $id; return $this; } /** * Set a single property - sets on $this->props[] array * * @return $this */ public function set($key, $value) { $this->props[$key] = $value; return $this; } /** * Get all props. * * @see $this::get_default_props() * @return array */ public function get_props($original = false) { if ($original) { return $this->orig_props; } return $this->props; } /** * Setup aliases for provided props. */ public function resolve_aliases($props) { $default = $this->get_default_props(); foreach ($default as $key => $prop) { // Is not an alias? Skip if (!is_array($prop) OR !array_key_exists('alias', $prop)) { continue; } // Alias used here if (array_key_exists($key, $props)) { // A stray config prop, remove it if (!empty($props[$key]['alias'])) { unset($props[$key]); continue; } // Example: 'terms' set from $props['cats'] $props[ $prop['alias'] ] = $props[$key]; } } return $props; } /** * Any assets to register for this block. */ public function register_assets() {} /** * Process and setup query. * * @uses \Bunyad\Blocks\Base\Query */ public function process() { $this->create_unique_id(); // Currently applying a filter. Query type can only be custom. if ($this->props['filter']) { $this->props = array_replace($this->props, [ 'query' => '', 'query_type' => 'custom' ]); } /** * Determine current page based on main query or provided paged param in AJAX. * Only done if pagination is enabled. */ if ($this->props['pagination']) { $page = (get_query_var('paged') ? get_query_var('paged') : get_query_var('page')); if (empty($page) && isset($_REQUEST['paged'])) { $this->props['page'] = intval($_REQUEST['paged']); } else { $this->props['page'] = intval($page); } } /** * Query type: Global or a custom defined. */ // Section query may be using main query, instead of a custom one. if ($this->props['query_type'] === 'section' && $this->props['section_query_type'] === 'main-custom') { $this->props['query_type'] = 'main-custom'; $this->props = array_replace( $this->props, (array) $this->props['section_query'] ); } // This query type re-executes main query, with support for some extra query props. if ($this->props['query_type'] === 'main-custom') { // Remove unsupported. $this->props = array_diff_key( $this->props, array_flip([ 'cat', 'terms', 'taxonomy', 'tax_ids', 'post_type', 'exclude_terms', 'exclude_ids', 'exclude_current', 'exclude_tags', ]) ); $this->props['query'] = $GLOBALS['wp_query']; } // Global query for 'main' or if no query_type is defined. if ( $this->props['query_type'] === 'main' || (!$this->props['query_type'] && !$this->props['query']) ) { $this->props['query'] = !empty($GLOBALS['bunyad_loop']) ? $GLOBALS['bunyad_loop'] : $GLOBALS['wp_query']; } /** * Use a pre-defined query. May also be the main query (defined above). * * Note: This is different from an undefined 'query', which fallbacks to global (core archives). * * @todo refactor to MainQuery. */ if ($this->props['query'] instanceof WP_Query) { // Clone to prevent modification on original query object. // As it may be re-used again, modifications such as post_count below would // affect the object passed by ref. $this->query = clone $this->props['query']; /** @var WP_Query $query */ $query = $this->query; $new_args = []; /** * For Main custom query, we'll add or replace query_vars based on provided props * and re-execute the current main wp_query. */ if ($this->props['query_type'] === 'main-custom') { $query_process = new Query(array_replace( $this->props, [ // Enable sticky posts unless disabled in original query. 'sticky_posts' => empty($query->query_vars['ignore_sticky_posts']) ? true : false ] )); $new_args = $query_process->setup_query_data(); $this->data = array_replace($this->data, $query_process->get_data()); } /** * Fallback to WordPress main/global query. Mainly for native archives. */ else if ($this->props['query']->is_main_query()) { // Exclude IDs can also be used on main query, ex. skip archive featured posts. if ($this->props['exclude_ids']) { $vars = &$query->query_vars; $new_args['post__not_in'] = array_merge( isset($vars['post__not_in']) ? (array) $vars['post__not_in'] : [], $this->props['exclude_ids'] ); } } /** * Used for a mixed internal block, mega menu etc. Or for blocks that call * another block and use same query, like news focus and highlights. * * - Change post_count to limit to post number specified. */ else { $do_skip_posts = $this->props['skip_posts']; // Adjust posts if number of posts specified. if ($this->props['posts']) { if ($query->post_count > $this->props['posts']) { $query->post_count = $this->props['posts']; } else if ($query->post_count < $this->props['posts']) { $new_args['post_per_page'] = $this->props['posts']; } } } // Pagination fix for all queries. if (!$this->props['pagination'] && $query->get('paged') > 1) { $new_args['paged'] = 1; } /** * Re-execute the global query with added vars, if needed. This is done for: * - 'main-custom': Always. * - Global Main query: If exclude_ids provided. * - Others: If more posts are required than in the original query, pagination fix etc. */ if (count($new_args)) { /** * We use the same filter in Query::setup(), so to remain consistent do the same when the * pre-provided query has to be re-executed. * * Note: We don't always run this filter as that would cause issues with no duplicate posts * feature. */ $new_args = apply_filters( 'bunyad_block_query_args', array_replace($query->query_vars, $new_args), $this ); $query->query($new_args); } // Just sets the internal pointer to skip over some posts. Used internally. if (!empty($do_skip_posts)) { $query->current_post = $this->props['skip_posts'] - 1; } $this->query = $query; // Setup data required to match Query::setup(). if (!$this->data) { $this->data = array_replace($this->data, [ 'heading' => $this->props['heading'], 'term_link' => '', 'term' => '', 'display_filters' => [], ]); } } else { // Skip current post. if ($this->props['exclude_current'] && is_single()) { $this->props['exclude_ids'] = array_merge( isset($this->props['exclude_ids']) ? (array) $this->props['exclude_ids'] : [], [get_the_ID()] ); } // All the other type of queries. switch ($this->props['query_type']) { case 'custom': // Setup the block query $query = new Query($this->props, $this); $this->data = array_merge($this->data, $query->setup()); $this->query = $this->data['query']; unset($this->data['query']); break; case 'section': $query = $this->props['section_query']; if (!is_object($query)) { $query_props = array_replace( $this->props, (array) $this->props['section_query'] ); // Add posts limit. $query_props = array_replace($query_props, [ 'posts' => $this->props['posts'], ]); $query = new Query($query_props); } $this->data = array_merge($this->data, $query->setup()); $this->query = $this->data['query']; break; case 'related': // Related posts query. if (Bunyad::posts()) { $this->query = Bunyad::posts()->get_related( $this->props['posts'], null, [ 'custom' => true, 'yarpp' => $this->props['query_yarpp'], ] ); $this->data = array_merge($this->data, [ 'heading' => $this->props['heading'] ]); } break; } } // Flag to mark processed $this->processed = true; } /** * Render the partial view for this loop. * * @uses \Bunyad_Core::partial() */ public function render($options = array()) { $options = wp_parse_args($options, array( 'block_markup' => true )); /** * Run an action before rendering the loop block. * * @param self $this */ do_action('bunyad_blocks_loop_render', $this); $this->_pre_render(); $this->setup_media_ratio(); $this->infer_image_sizes(); /** * Filter block image before. * * @param string $image Current image. * @param string $id Block id. */ $this->props['image'] = apply_filters('bunyad_blocks_loop_image', $this->props['image'], $this->id); if (!$this->processed) { $this->process(); } // Odd case. if (!$this->query) { return; } // Render with or without block markup ($options['block_markup'] ? $this->render_block_markup() : $this->render_view()); // Restore post data as views will override it. wp_reset_postdata(); /** * Run an action after rendering the loop block. * * @param self $this */ do_action('bunyad_blocks_loop_render_after', $this); } /** * Checks to perform and settings to do prior to render */ public function _pre_render() {} /** * Render the view file for this block - usually a loop */ public function render_view() { $view_id = $this->view_id ? $this->view_id : $this->id; Bunyad::core()->partial( 'blocks/loops/' . $view_id . '/html/' . $view_id, [ 'block' => $this, 'query' => $this->query ] ); } /** * Get block attributes for rendering the block markup. * * @return array */ public function get_block_wrap_attribs() { $classes = [ 'block-wrap', 'block-' . $this->id, $this->props['is_sc_call'] ? 'block-sc' : '', // Preset column gaps. $this->props['column_gap'] ? 'cols-gap-' . $this->props['column_gap'] : '', // Dark scheme class if active. $this->props['scheme'] === 'dark' ? 's-dark' : '', // Margins below class. $this->props['space_below'] ? 'mb-' . $this->props['space_below'] : '', // Media shadows. Note: It's best done in wrapper instead of loop div for style consistency. $this->props['media_style_shadow'] && $this->props['media_style_shadow'] !== 'none' ? 'has-media-shadows' : '', ]; $attribs = [ 'class' => $classes, 'data-id' => $this->data['unique_id'] ]; /** * Add block query data for dynamic pagination or blocks with filters. */ $ajax_pagination = in_array( $this->props['pagination_type'], ['load-more', 'numbers-ajax', 'infinite'] ); if ($this->props['filters'] || ($this->props['pagination'] && $ajax_pagination)) { $block_data = [ 'id' => $this->id, 'props' => $this->orig_props, ]; unset($block_data['props']['section_query_type']); // Archive, or other main query will require extra data from the original query // for AJAX pagination. if (!in_array($this->props['query_type'], ['custom', 'section'])) { $term_data = $this->query->get_queried_object(); if (is_object($term_data)) { $block_data['props'] += [ 'post_type' => $this->query->get('post_type'), 'posts' => $this->query->get('posts_per_page'), 'sticky_posts' => !$this->query->get('ignore_sticky_posts'), 'taxonomy' => !empty($term_data->taxonomy) ? $term_data->taxonomy : '', 'terms' => !empty($term_data->term_id) ? $term_data->term_id : '', ]; } } $attribs['data-block'] = json_encode($block_data); } return $attribs; } /** * Output common block markup and render the specific view file. * * Note: Do not call directly, use render() instead. * * @uses self::render_view() */ public function render_block_markup() { ?> <section <?php Bunyad::markup()->attribs( $this->id .'-block', $this->get_block_wrap_attribs() ); ?>> <?php $this->the_heading(); ?> <div class="block-content"> <?php $this->render_view(); ?> </div> </section> <?php } /** * Created unique ID for the block */ protected function create_unique_id() { Bunyad::registry()->block_count++; $this->data['unique_id'] = Bunyad::registry()->block_count; } /** * Output block heading markup */ public function the_heading() { // Custom heading HTML set progrmmatically (not via prop), use this instead. if (!empty($this->data['heading_custom'])) { echo $this->data['heading_custom']; // phpcs:ignore WordPress.Security.EscapeOutput Only settable internally programmatically. return; } // This check is also performed in Heading block. Done here to save resources. if (empty($this->data['heading']) || $this->props['heading_type'] === 'none') { return; } Bunyad::blocks()->load( 'Heading', [ 'heading' => $this->data['heading'], 'align' => $this->props['heading_align'], 'type' => $this->props['heading_type'], 'link' => $this->props['heading_link'] ? $this->props['heading_link'] : $this->data['term_link'], 'term' => $this->data['term'], 'filters' => $this->data['display_filters'], 'more' => $this->props['heading_more'], 'more_text' => $this->props['heading_more_text'], 'more_link' => $this->props['heading_more_link'] ? $this->props['heading_more_link'] : $this->data['term_link'], 'accent_colors' => $this->props['heading_colors'], 'html_tag' => $this->props['heading_tag'], ] ) ->render(); } /** * Load a loop post class * * Example: Load the loop class from inc/loop-posts/grid.php if it exists * or fallback to inc/loop-posts/base.php * * @uses \Bunyad\Blocks\Helpers::load_post() * * @param string $id Loop post id * @param array $props Props to set for loop post * * @return \Bunyad\Blocks\LoopPosts\BasePost */ public function loop_post($id, $props = array()) { $this->rendered_posts++; $props = array_replace($this->get_props(), $props); $props['loop_number'] = $this->rendered_posts; // Load post $post = Bunyad::blocks()->load_post($id, $props); $post->block = $this; return $post; } /** * Get relative width for current block, based on parent column width in * relation to the whole page. * * @return float Column width in percent number, example 66 */ public function get_relative_width() { // Container defined in props, force it if (!empty($this->props['container_width'])) { return floatval($this->props['container_width']); } return Bunyad::blocks()->get_relative_width(); } /** * Set columns size based on provided columns. * * @param array $args Configs for columns of devices. * @return void */ protected function setup_columns($args = []) { if (empty($this->props['columns'])) { $this->props['columns'] = 1; } // Add the grid columns class. $this->props['class_grid'][] = 'grid-' . $this->props['columns']; $col_types = [ 'md' => 'medium', 'sm' => 'small', 'xs' => 'xsmall' ]; /** * Add responsive column classes based on props of type columns_medium etc. * OR, override via args provided. */ foreach ($col_types as $key => $columns) { $cols = null; if (!empty($this->props[ 'columns_' . $columns ])) { $cols = $this->props[ 'columns_' . $columns ]; } else if (!empty($args[ $columns ])) { $cols = $args[ $columns ]; } if ($cols) { array_push( $this->props['class_grid'], "{$key}:grid-{$cols}" ); } } // 1/3 * 12 to get col-4 $column = (1 / absint($this->props['columns']) * 12); $this->props['col_class'] = 'col-' . str_replace('.', '-', $column); } /** * Setup media ratio if provided. */ public function setup_media_ratio() { if (empty($this->props['media_ratio'])) { return; } $ratio = $this->props['media_ratio']; if ($ratio === 'custom' && !empty($this->props['media_ratio_custom'])) { $ratio = $this->props['media_ratio_custom']; } $this->props['media_ratio'] = $ratio; } /** * Decide the image to use for this block */ public function infer_image_sizes() { // If an image is forced, don't bother setting it if (!empty($this->props['image'])) { return; } $this->props['image'] = 'bunyad-thumb'; } /** * Render pagination for current block * * @uses \Bunyad_Core::partial() * @param array $props */ public function the_pagination($props = []) { if (!$this->props['pagination'] || !$this->props['pagination_render']) { return; } $props = array_merge( [ 'query' => $this->query, 'page' => $this->props['page'], 'pagination' => $this->props['pagination'], 'pagination_type' => $this->props['pagination_type'], 'load_more_style' => $this->props['load_more_style'], 'pagination_links' => $this->props['pagination_links'] ], $props ); // AJAX pagination is not possible in author and search archives, yet. if (is_author() || is_search()) { $props['pagination_type'] = 'numbers'; } Bunyad::core()->partial('partials/pagination', $props); } }PK 03Y6|֫� �� * smartmag-core/blocks/base/loop-options.php<?php namespace Bunyad\Blocks\Base; use \Bunyad; /** * Block options for page builders, widgets and so on. */ class LoopOptions extends Options { /** * @var integer|array Number of supported columns. */ protected $supported_columns = 6; /** * @var array Internal terms cache. */ private $terms_cache; // Max number of categories to be shown. public $limit_cats = 500; /** * Setup options * * @return $this */ public function init() { $this->get_common_data(); $this->options = $this->get_shared_options(); return $this; } /** * Most common options usually shared by loop blocks */ public function get_shared_options() { $options = []; /** * General Options */ $options['sec-general'] = [ 'posts' => [ 'label' => esc_html__('Number of Posts', 'bunyad-admin'), 'type' => 'number', 'condition' => ['query_type!' => 'main'], ], 'pagination' => [ 'label' => esc_html__('Pagination', 'bunyad-admin'), 'type' => 'switcher', 'default' => 0, 'return_value' => '1', 'condition' => ['query_type!' => 'related'], ], 'pagination_type' => [ 'label' => esc_html__('Pagination Type', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'numbers-ajax' => esc_html__('Page Numbers AJAX', 'bunyad-admin'), 'load-more' => esc_html__('Load More Button', 'bunyad-admin'), 'numbers' => esc_html__('Page Numbers', 'bunyad-admin'), 'infinite' => esc_html__('Infinite Scroll (For Last Block Only)', 'bunyad-admin'), ], 'default' => 'numbers-ajax', 'condition' => ['pagination' => '1'], ], 'pagination_links' => [ 'label' => esc_html__('SEO: Pagination Links', 'bunyad-admin'), 'desc' => 'Might be desirable to disable load more pagination links for homepage blocks to prevent indexing.', 'type' => 'switcher', 'default' => '1', 'return_value' => '1', 'condition' => ['pagination_type' => ['load-more', 'infinite']], ], 'scheme' => [ 'label' => esc_html__('Color Scheme', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Default', 'bunyad-admin'), 'dark' => esc_html__('Contrast (For Dark Background)', 'bunyad-admin'), ], 'default' => '', ], 'title_tag' => [ 'label' => esc_html__('SEO: Titles Tag', 'bunyad-admin'), 'type' => 'select', 'options' => $this->common['heading_tags'], ], ]; /** * Layout options. */ $options['sec-layout'] = []; if ($this->supported_columns) { $options['sec-layout'] = [ 'columns' => [ 'label' => esc_html__('Columns', 'bunyad-admin'), 'type' => 'select', 'devices' => true, 'description' => esc_html__('Note: Make sure the container column/section is large enough for best look.', 'bunyad-admin'), 'options' => [$this, '_option_columns'], ], ]; } $options['sec-layout'] += [ 'space_below' => [ 'label' => esc_html__('Add Space Below', 'bunyad-admin'), 'type' => 'select', 'description' => esc_html__('Space to add below the block. Note: Columns in Elementor also add additional space below via "Widgets Space" setting.', 'bunyad-admin'), 'options' => [ '' => esc_html__('Default', 'bunyad-admin'), 'none' => esc_html__('None', 'bunyad-admin'), 'sm' => esc_html__('Small', 'bunyad-admin'), 'md' => esc_html__('Medium', 'bunyad-admin'), // 'lg' => esc_html__('Large', 'bunyad-admin'), ], 'default' => '', // 'label_block' => true ], 'cat_labels' => [ 'label' => esc_html__('Category Label Overlay', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Auto/Global', 'bunyad-admin'), '1' => esc_html__('Enabled', 'bunyad-admin'), '0' => esc_html__('Disabled', 'bunyad-admin'), ], 'default' => '1', ], 'cat_labels_pos' => [ 'label' => esc_html__('Overlay Position', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Auto/Global', 'bunyad-admin') ] + $this->common['cat_labels_pos_options'], 'default' => '', 'separator' => 'after', 'condition' => ['cat_labels' => '1'], ], 'title_lines' => [ 'label' => esc_html__('Limit Title to Lines', 'bunyad-admin'), 'type' => 'select', 'options' => function() { return [ '' => esc_html__('Default / Global', 'bunyad-admin'), '0' => 'No Limit', ] + array_combine(range(1, 5), range(1, 5)); } ], 'excerpts' => [ 'label' => esc_html__('Show Excerpts', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', ], 'excerpt_lines' => [ 'label' => esc_html__('Excerpt Limit Lines', 'bunyad-admin'), 'type' => 'select', 'options' => function() { return [ '' => esc_html__('Default / Global', 'bunyad-admin'), '0' => 'No Limit', ] + array_combine(range(1, 5), range(1, 5)); }, 'condition' => ['excerpts' => '1'], ], 'excerpt_length' => [ 'label' => esc_html__('Excerpt Words', 'bunyad-admin'), 'type' => 'number', 'condition' => ['excerpts' => '1'], // We have to force excerpt length here as blocks default to empty. // Empty default is needed in block config to allow global prefill. 'default' => 15, 'default_forced' => true, ], 'content_center' => [ 'label' => esc_html__('Content Centered', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '0', ], 'show_media' => [ 'label' => esc_html__('Show Media/Image', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'separator' => 'before' ], 'media_ratio' => [ 'label' => esc_html__('Image Ratio', 'bunyad-admin'), 'type' => 'select', 'options' => $this->common['ratio_options'], 'default' => '', 'condition' => ['show_media' => '1'], ], // media_ratio_custom will be the main value. // media_ratio_custom_mobile, media_ratio_custom_tablet etc. will be for devices. 'media_ratio_custom' => [ 'label' => esc_html__('Image Ratio', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 0.25, 'max' => 4.5, 'step' => .1], 'devices' => true, 'default' => '', 'selectors' => [ '{{WRAPPER}} .media-ratio' => 'padding-bottom: calc(100% / {{SIZE}});' ], 'condition' => ['show_media' => '1', 'media_ratio' => 'custom'], ], 'read_more' => [ 'label' => esc_html__('Read More', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Auto/Global', 'bunyad-admin'), ] + $this->common['read_more_options'], 'default' => '', ], 'reviews' => [ 'label' => esc_html__('Reviews', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Auto/Global', 'bunyad-admin') ] + $this->common['reviews_options'], 'default' => '', ], 'show_post_formats' => [ 'label' => esc_html__('Post Formats Icons', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', ], 'post_formats_pos' => [ 'label' => esc_html__('Formats Default Position', 'bunyad-admin'), 'type' => 'select', 'options' => $this->common['post_format_pos_options'], 'condition' => ['show_post_formats' => '1'] ], // -- Post Meta 'h-post-meta' => [ 'label' => esc_html__('Post Meta', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before' ], 'meta_items_default' => [ 'label' => esc_html__('Default/Global Meta Items', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'separator' => 'before' ], 'meta_above' => [ 'label' => esc_html__('Items Above', 'bunyad-admin'), 'type' => 'bunyad-selectize', 'options' => $this->common['meta_options'], 'multiple' => true, 'label_block' => true, 'condition' => ['meta_items_default!' => '1'], ], 'meta_below' => [ 'label' => esc_html__('Items Below', 'bunyad-admin'), 'type' => 'bunyad-selectize', 'options' => $this->common['meta_options'], 'multiple' => true, 'label_block' => true, 'condition' => ['meta_items_default!' => '1'], ], 'meta_cat_style' => [ 'label' => esc_html__('Category Style', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'text' => esc_html__('Plain Text', 'bunyad-admin'), 'labels' => esc_html__('Label', 'bunyad-admin'), ], 'default' => 'text', ], 'meta_author_img' => [ 'label' => esc_html__('Author Image', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => 0, // 'separator' => 'after' ], 'show_title' => [ 'label' => esc_html__('Show Post Title', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', ], // -- Post Meta 'h-post-meta-sp' => [ 'label' => esc_html__('Post Meta: Sponsor', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before' ], 'meta_sponsor' => [ 'label' => esc_html__('Show Sponsors', 'bunyad-admin'), 'type' => 'select', 'default' => '', 'options' => [ '' => esc_html__('Default/Global', 'bunyad-admin'), '1' => esc_html__('Enable & Customize', 'bunyad-admin'), '0' => esc_html__('Disabled', 'bunyad-admin'), ], 'separator' => 'before' ], 'meta_sponsor_items_default' => [ 'label' => esc_html__('Default/Global Sponsor Meta', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'condition' => ['meta_sponsor' => '1'], ], 'meta_sponsor_above' => [ 'label' => esc_html__('Items Above', 'bunyad-admin'), 'type' => 'bunyad-selectize', 'options' => $this->common['meta_options_sp'], 'multiple' => true, 'label_block' => true, 'condition' => ['meta_sponsor_items_default!' => '1', 'meta_sponsor' => '1'], ], 'meta_sponsor_below' => [ 'label' => esc_html__('Items Below', 'bunyad-admin'), 'type' => 'bunyad-selectize', 'options' => $this->common['meta_options_sp'], 'multiple' => true, 'label_block' => true, 'condition' => ['meta_sponsor_items_default!' => '1', 'meta_sponsor' => '1'], ], 'meta_sponsor_logo' => [ 'label' => esc_html__('Sponsor Logo', 'bunyad-admin'), 'type' => 'select', 'default' => '', 'options' => [ '' => esc_html__('Default/Global', 'bunyad-admin'), '1' => esc_html__('Enabled', 'bunyad-admin'), '0' => esc_html__('Disabled', 'bunyad-admin'), ], 'condition' => ['meta_sponsor' => '1'], ], 'meta_sponsor_label' => [ 'label' => esc_html__('Sponsor Custom Label', 'bunyad-admin'), 'desc' => 'By default, will use labels set in Customizer > Global Posts settings.', 'type' => 'text', 'default' => '', 'condition' => ['meta_sponsor' => '1'], ], // -- 'h-advanced-1' => [ 'label' => esc_html__('Advanced', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before' ], 'container_width' => [ 'label' => esc_html__('Container Width', 'bunyad-admin'), 'type' => 'select', 'description' => esc_html__('The block will select image sizing based on specified container width.', 'bunyad-admin'), 'options' => [ '33' => esc_html__('Small: 1 Column or In Sidebar', 'bunyad-admin'), '50' => esc_html__('Medium: 50% of Width', 'bunyad-admin'), '66' => esc_html__('Large: 66% of Width', 'bunyad-admin'), '100' => esc_html__('Full Width', 'bunyad-admin'), ], 'label_block' => true, 'separator' => 'before' ], 'skip_lazy_number' => [ 'label' => esc_html__('Skip Lazyload on Images', 'bunyad-admin'), 'type' => 'number', 'description' => esc_html__('Number of posts to skip lazyload on for LCP performance.', 'bunyad-admin'), // 'separator' => 'after', // 'condition' => ['show_media' => '1'], // Not supported for feat-grid ], // 'force_image' => [ // 'label' => esc_html__('Forced Image Size', 'bunyad-admin'), // 'type' => 'select', // 'description' => esc_html__('Best kept default! Forces a specific physical image to use. Does not effect width or height.', 'bunyad-admin'), // 'options' => [$this, '_option_images'], // 'label_block' => true, // // 'separator' => 'before' // ], ]; /** * Posts Source / Filters */ $options['sec-filter'] = [ 'query_type' => [ 'label' => esc_html__('Query Type', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'custom' => esc_html__('Custom', 'bunyad-admin'), 'section' => esc_html__('Section Query (Parent Section)', 'bunyad-admin'), 'main-custom' => esc_html__('Main Query / Archive', 'bunyad-admin'), 'main' => esc_html__('Global Query (for Devs)', 'bunyad-admin'), 'related' => esc_html__('Related Posts (for Single Post)', 'bunyad-admin'), ], 'default' => 'custom', 'default_forced' => true, ], 'query_yarpp' => [ 'label' => esc_html__('Use YARPP Plugin?', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '0', 'condition' => ['query_type' => 'related'], ], '_n_section_query' => [ 'type' => 'html', 'raw' => esc_html__('Edit the nearest/direct parent section and configure under the Section Query.', 'bunyad-admin'), 'condition' => ['query_type' => 'section'], 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info', ], 'sort_by' => [ 'label' => esc_html__('Sort By', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Published Date', 'bunyad-admin'), 'modified' => esc_html__('Modified Date', 'bunyad-admin'), 'random' => esc_html__('Random', 'bunyad-admin'), 'comments' => esc_html__('Comments Count', 'bunyad-admin'), 'alphabetical' => esc_html__('Alphabetical', 'bunyad-admin'), 'rating' => esc_html__('Rating', 'bunyad-admin'), ] + ( // Not using global setting for now. class_exists('\Jetpack') && \Jetpack::is_module_active('stats') ? ['jetpack_views' => esc_html__('JetPack Plugin Views Count', 'bunyad-admin')] : [] ) + ( class_exists('\Sphere\PostViews\Plugin') ? [ 'views' => esc_html__('Post Views: All Time', 'bunyad-admin'), 'views-7days' => esc_html__('Post Views: 30 Days', 'bunyad-admin'), 'views-days' => esc_html__('Post Views: Custom Days', 'bunyad-admin') ] : [] ), 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'sort_days' => [ 'label' => esc_html__('Sort Days', 'bunyad-admin'), 'description' => esc_html__('Number of days to use for the views sort. Max limit is 90 days for Jetpack.', 'bunyad-admin'), 'type' => 'number', 'default' => 30, 'condition' => [ 'sort_by' => ['jetpack_views', 'views-days'], 'query_type' => 'custom' ] ], 'sort_order' => [ 'label' => esc_html__('Sort Order', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'desc' => esc_html__('Descending / Latest First', 'bunyad-admin'), 'asc' => esc_html__('Ascending / Oldest First', 'bunyad-admin'), ], 'default' => 'desc', 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'terms' => [ 'label' => esc_html__('From Categories', 'bunyad-admin'), 'type' => 'select2', 'options' => [$this, '_option_categories'], 'description' => 'Limit posts to selected categories.', 'multiple' => true, 'label_block' => true, 'separator' => 'before', 'condition' => ['query_type' => 'custom'], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'categories'); } ], 'cat' => [ 'label' => esc_html__('Main Category', 'bunyad-admin'), 'type' => 'select2', 'description' => esc_html__('OPTIONAL: Will also be used for heading link, text and color if set.', 'bunyad-admin'), 'options' => function() { return [ '' => esc_html__('None', 'bunyad-admin'), '__current' => esc_html__('Archive: Current Category', 'bunyad-admin') ] + $this->_option_categories(); }, 'condition' => ['query_type' => 'custom'], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'categories'); } ], 'exclude_terms' => [ 'label' => esc_html__('Exclude Categories', 'bunyad-admin'), 'type' => 'select2', 'options' => [$this, '_option_categories'], 'description' => 'Prevents posts from these categories.', 'multiple' => true, 'label_block' => true, // 'separator' => 'before', 'condition' => ['query_type' => 'custom'], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'categories'); } ], 'offset' => [ 'label' => esc_html__('Skip Posts / Offset', 'bunyad-admin'), 'description' => esc_html__('Skip first X posts.', 'bunyad-admin'), 'type' => 'number', 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'reviews_only' => [ 'label' => esc_html__('Review Posts Only', 'bunyad-admin'), 'description' => '', 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'tags' => [ 'label' => esc_html__('From Tags', 'bunyad-admin'), 'type' => 'select2', // 'options' => [$this, '_option_tags'], 'options' => [], 'description' => esc_html__('Will limit posts to selected tags.', 'bunyad-admin'), 'multiple' => true, 'label_block' => true, 'separator' => 'before', 'condition' => ['query_type' => ['custom', 'main-custom']], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'tags'); } ], // 'author' => [ // ] 'post_ids' => [ 'label' => esc_html__('Specific Post IDs', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Post IDs separated by commas, ex: 25, 34', 'bunyad-admin'), 'multiple' => true, 'label_block' => true, 'condition' => ['query_type' => 'custom'], ], 'post_formats' => [ 'label' => esc_html__('Specific Post Formats', 'bunyad-admin'), 'type' => 'select2', 'description' => esc_html__('Show posts of specific post formats only. Defaults to standard posts.', 'bunyad-admin'), 'options' => [ 'video' => esc_html__('Video', 'bunyad-admin'), 'audio' => esc_html__('Audio', 'bunyad-admin'), 'gallery' => esc_html__('Gallery', 'bunyad-admin'), ], 'multiple' => true, 'label_block' => true, 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'h-advanced' => [ 'label' => esc_html__('Advanced', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before', 'condition' => ['query_type' => 'custom'], ], 'exclude_tags' => [ 'label' => esc_html__('Exclude Tags', 'bunyad-admin'), 'type' => 'select2', 'options' => [], 'description' => esc_html__('Skip posts using these tags.', 'bunyad-admin'), 'multiple' => true, 'label_block' => true, 'separator' => 'before', 'condition' => ['query_type' => ['custom', 'main-custom']], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'tags'); } ], 'exclude_ids' => [ 'label' => esc_html__('Exclude Post IDs', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Post IDs separated by commas, ex: 25, 34', 'bunyad-admin'), 'multiple' => true, 'label_block' => true, 'condition' => ['query_type' => 'custom'], ], 'taxonomy' => [ 'label' => esc_html__('Taxonomy', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('A custom taxonomy limit instead of category or post_tag. This will disable category and tags limits from above.', 'bunyad-admin'), 'label_block' => true, 'condition' => ['query_type' => 'custom'], ], 'tax_ids' => [ 'label' => esc_html__('Taxonomy Terms IDs', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('IDs of the taxonomy items to use separated by comma, for example ids of categories under product_cat.', 'bunyad-admin'), 'label_block' => true, 'condition' => [ 'taxonomy!' => '', 'query_type' => 'custom' ] ], 'post_type' => [ 'label' => esc_html__('Post Type', 'bunyad-admin'), 'type' => 'select', 'options' => function() { return wp_list_pluck( get_post_types([ 'public' => true, ], 'objects'), 'label' ); }, 'condition' => ['query_type' => 'custom'], ], 'query_id' => [ 'label' => esc_html__('Devs: Query ID', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Optional custom query ID to modify query args using the bunyad_block_query_args filter.', 'bunyad-admin'), 'separator' => 'before', 'label_block' => true, 'condition' => ['query_type' => ['custom', 'main-custom']], ], 'exclude_current' => [ 'label' => esc_html__('Exclude Current Post', 'bunyad-admin'), 'description' => esc_html__('If using on a single post sidebar, this will ignore the post being viewed.', 'bunyad-admin'), 'return_value' => '1', 'type' => 'switcher', // 'label_block' => true, 'condition' => ['query_type' => ['custom']], ], ]; /** * Heading Options */ $options['sec-heading'] = [ 'heading_type' => [ 'label' => esc_html__('Heading Style', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'none' => esc_html__('Disabled', 'bunyad-admin'), '' => esc_html__('Global / Default Style', 'bunyad-admin'), ] + $this->common['block_headings'], 'default' => '', 'label_block' => true ], 'heading_colors' => [ 'label' => esc_html__('Base Colors', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Auto', 'bunyad-admin'), 'force' => esc_html__('Accent / Category', 'bunyad-admin'), 'none' => esc_html__('Default', 'bunyad-admin'), ], 'condition' => [ 'heading_type!' => ['g', 'e2'] ] // 'label_block' => true, ], 'heading' => [ 'label' => esc_html__('Heading Text', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Optional. By default, main category name will be used. Note: Some heading styles can have multi-color headings when used with asterisks, example: World *News*', 'bunyad-admin'), 'label_block' => true ], 'heading_link' => [ 'label' => esc_html__('Heading Link', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Optional. By default, main category link will be used.', 'bunyad-admin'), 'label_block' => true ], 'heading_more_text' => [ 'label' => esc_html__('View More', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Add view more text with link.', 'bunyad-admin'), 'label_block' => true ], 'heading_more' => [ 'label' => esc_html__('View More Style', 'bunyad-admin'), 'type' => 'select', 'description' => '', 'options' => [ 'a' => 'Simple Text', 'b' => 'Round Pill Style', ], 'condition' => ['heading_more_text!' => ''], ], 'heading_more_link' => [ 'label' => esc_html__('View More Link', 'bunyad-admin'), 'type' => 'text', 'description' => esc_html__('Optional. By default, main category link will be used.', 'bunyad-admin'), 'label_block' => true, 'condition' => ['heading_more_text!' => ''], ], 'h-filters' => [ 'label' => esc_html__('Filters', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before' ], 'filters' => [ 'label' => esc_html__('Heading Filters', 'bunyad-admin'), 'type' => 'select', 'description' => esc_html__('Filters when enabled, are displayed as links in the heading on right side.', 'bunyad-admin'), 'options' => [ '' => esc_html__('None', 'bunyad-admin'), 'category' => esc_html__('Categories', 'bunyad-admin'), 'tag' => esc_html__('Tags', 'bunyad-admin'), ], 'label_block' => true ], 'filters_terms' => [ 'label' => esc_html__('Categories', 'bunyad-admin'), 'type' => 'select2', 'description' => esc_html__('If no categories are selected, it will default to showing 3 sub-categories.', 'bunyad-admin'), 'options' => [$this, '_option_categories'], 'label_block' => true, 'multiple' => true, 'condition' => ['filters' => 'category'], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'categories'); } ], 'filters_tags' => [ 'label' => esc_html__('Tags', 'bunyad-admin'), 'type' => 'select2', 'description' => esc_html__('Filters when enabled, are displayed as links in the heading on right side.', 'bunyad-admin'), // 'options' => [$this, '_option_tags'], 'label_block' => true, 'multiple' => true, 'condition' => ['filters' => 'tag'], 'editor_callback' => function($option) { return $this->maybe_ajax_for_terms($option, 'tags'); } ], 'heading_tag' => [ 'label' => esc_html__('SEO: Heading Tag', 'bunyad-admin'), 'type' => 'select', 'options' => $this->common['heading_tags'], ], // 'h-bh-styles' => [ // 'label' => esc_html__('Styling', 'bunyad-admin'), // 'type' => 'heading', // 'separator' => 'before' // ], ]; /** * Style - General. */ $options['sec-style'] = [ 'css_accent_color' => [ 'label' => esc_html__('Accent / Main Color', 'bunyad-admin'), 'description' => esc_html__('Used for hovers, heading text (unless changed in Heading Settings) and accent, and so on.', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}}, {{WRAPPER}} .cat-labels .category' => '--c-main: {{VALUE}};', '{{WRAPPER}} .block-head' => '--c-block: {{VALUE}};', ], 'default' => '', ], 'css_accent_color_sd' => [ 'label' => esc_html__('Dark: Accent / Main Color', 'bunyad-admin'), 'description' => esc_html__('For dark mode.', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark {{WRAPPER}}, {{WRAPPER}} .s-dark' => '--c-main: {{VALUE}};', '.s-dark {{WRAPPER}} .block-head, {{WRAPPER}} .s-dark .block-head' => '--c-block: {{VALUE}};', ], 'default' => '', ], 'column_gap' => [ 'label' => esc_html__('Column Gap', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Default', 'bunyad-admin'), 'sm' => esc_html__('Small Gap', 'bunyad-admin'), 'lg' => esc_html__('Large Gap', 'bunyad-admin'), 'xlg' => esc_html__('X-Large Gap', 'bunyad-admin'), ], 'default' => '', 'separator' => 'before' ], 'css_column_gap' => [ 'label' => esc_html__('Column Gap Custom', 'bunyad-admin'), 'description' => esc_html__('Vertical spacing between posts.', 'bunyad-admin'), 'type' => 'slider', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .loop' => '--grid-gutter: {{SIZE}}{{UNIT}};' ], 'default' => [], ], 'css_row_gap' => [ 'label' => esc_html__('Row Gap', 'bunyad-admin'), 'type' => 'slider', 'description' => esc_html__('Horizontal spacing between posts.', 'bunyad-admin'), 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .loop' => '--grid-row-gap: {{SIZE}}{{UNIT}};' ], 'default' => [], ], 'separators' => [ 'label' => esc_html__('Add Separators', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '', 'separator' => 'before' ], 'separators_cols' => [ 'label' => esc_html__('Add Column Separators', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '', 'separator' => 'after' ], 'css_format_icon_size' => [ 'label' => esc_html__('Post Format Icon Scale', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 0.4, 'max' => 3.5, 'step' => .1], 'devices' => true, 'selectors' => [ '{{WRAPPER}} .l-post' => '--post-format-scale: {{SIZE}};' ], 'default' => [], ], 'css_media_radius' => [ 'label' => esc_html__('Media/Image Roundness', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .l-post' => '--media-radius: {{SIZE}}px;' ], 'default' => '', ], 'media_style_shadow' => [ 'label' => esc_html__('Add Media Shadow', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Default / Global', 'bunyad-admin'), '1' => esc_html__('Enabled', 'bunyad-admin'), 'none' => esc_html__('Disabled', 'bunyad-admin'), ], 'default' => '', ], ]; /** * Style: Content */ $options['sec-style-content'] = [ 'css_l_post_shadow' => [ 'label' => esc_html__('Post Box Shadow', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'box-shadow', 'selector' => '{{WRAPPER}} .l-post', // 'default' => [], ], 'css_l_post_border' => [ 'label' => esc_html__('Post Box Border', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'bunyad-border', 'selector' => '{{WRAPPER}} .l-post', 'selector_color_dark' => '.s-dark {{WRAPPER}} .l-post, {{WRAPPER}} .s-dark .l-post', // 'default' => [], ], 'css_l_post_radius' => [ 'label' => esc_html__('Post Box Roundness', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .l-post' => 'border-radius: {{VALUE}}px; overflow: hidden;' ], 'default' => '', ], 'css_l_post_bg' => [ 'label' => esc_html__('Post Box Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .l-post' => 'background-color: {{VALUE}};' ], 'default' => '', ], 'css_l_post_bg_sd' => [ 'label' => esc_html__('Dark: Box Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark {{WRAPPER}} .l-post, {{WRAPPER}} .s-dark .l-post' => 'background-color: {{VALUE}};' ], 'default' => '', 'condition' => ['css_l_post_bg!' => ''] ], 'css_l_post_pad' => [ 'label' => esc_html__('Post Box Paddings', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .l-post' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_content_pad' => [ 'label' => esc_html__('Content Paddings', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'separator' => 'before', 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_content_margin' => [ 'label' => esc_html__('Content Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .content' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_content_border' => [ 'label' => esc_html__('Content Border', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'bunyad-border', 'selector' => '{{WRAPPER}} .content', 'selector_color_dark' => '.s-dark {{WRAPPER}} .content, {{WRAPPER}} .s-dark .content', // 'default' => [], ], 'css_content_shadow' => [ 'label' => esc_html__('Content Shadow', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'box-shadow', 'selector' => '{{WRAPPER}} .content', // 'default' => [], ], 'css_content_bg' => [ 'label' => esc_html__('Content Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .content' => 'background-color: {{VALUE}};' ], 'default' => '', ], 'css_content_bg_sd' => [ 'label' => esc_html__('Dark: Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark {{WRAPPER}} .content, {{WRAPPER}} .s-dark .content' => 'background-color: {{VALUE}};' ], 'default' => '', 'condition' => ['css_content_bg!' => ''] ], 'css_meta_above_margins' => [ 'label' => esc_html__('Post Meta Above Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'separator' => 'before', 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .meta-above' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_meta_below_margins' => [ 'label' => esc_html__('Post Meta Below Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .meta-below' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_meta_typography' => [ 'label' => esc_html__('Post Meta Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .post-meta .meta-item, {{WRAPPER}} .post-meta .text-in', 'default' => [], ], 'css_meta_icons_size' => [ 'label' => esc_html__('Post Meta Icons Size', 'bunyad-admin'), 'type' => 'number', 'separator' => 'after', 'devices' => true, 'selectors' => [ '{{WRAPPER}} .post-meta' => '--p-meta-icons-s: {{SIZE}}px;' ], 'default' => [], ], 'css_excerpt_typo' => [ 'label' => esc_html__('Excerpts Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .excerpt', 'default' => [], ], 'css_excerpt_margin' => [ 'label' => esc_html__('Excerpt Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, // 'size_units' => ['px'], 'selectors' => [ '{{WRAPPER}} .excerpt' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_excerpt_visible' => [ 'label' => esc_html__('Excerpt Visibility', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => 'Default', 'block' => esc_html__('Show', 'bunyad-admin'), 'none' => esc_html__('Hide', 'bunyad-admin'), ], 'devices' => true, 'selectors' => [ '{{WRAPPER}} .excerpt' => 'display: {{VALUE}}', ], 'condition' => ['excerpts' => '1'], ], 'css_excerpt_lines' => [ 'label' => esc_html__('Excerpts Lines Per Device', 'bunyad-admin'), 'type' => 'number', 'devices' => true, 'selectors' => [ '{{WRAPPER}} .excerpt' => '--limit-lines: {{VALUE}};' ], 'default' => [], 'condition' => ['excerpt_lines!' => ['', '0']] ], ]; /** * Style: Post Titles. */ $options['sec-style-titles'] = [ 'css_title_typo' => [ 'label' => esc_html__('Post Titles Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .post-title', 'default' => [], ], 'css_title_margin' => [ 'label' => esc_html__('Titles Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'allowed_dimensions' => ['top', 'bottom'], 'selectors' => [ '{{WRAPPER}} .post-title' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};' ], 'default' => [], ], 'css_title_padding' => [ 'label' => esc_html__('Titles Paddings', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .post-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_title_color' => [ 'label' => esc_html__('Titles Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.elementor-element-{{ID}} .post-title' => '--c-headings: {{VALUE}};' ], 'default' => '', ], 'css_title_color_sd' => [ 'label' => esc_html__('Dark: Titles Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark .elementor-element-{{ID}} .post-title, .elementor-element-{{ID}} .s-dark .post-title' => '--c-headings: {{VALUE}};' ], 'default' => '', ], 'css_title_hov_color' => [ 'label' => esc_html__('Hover Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.elementor-element-{{ID}} .post-title a:hover' => '--c-a-hover: {{VALUE}};' ], 'default' => '', ], 'css_title_hov_color_sd' => [ 'label' => esc_html__('Dark: Hover Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark .elementor-element-{{ID}} .post-title a:hover, .elementor-element-{{ID}} .s-dark .post-title a:hover' => '--c-a-hover: {{VALUE}};' ], 'default' => '', ], ]; /** * Style: Block Heading */ $options['sec-style-bhead'] = [ 'heading_align' => [ 'label' => esc_html__('Heading Align', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'left' => esc_html__('Default / Left', 'bunyad-admin'), 'center' => esc_html__('Centered (Filters Not Supported)', 'bunyad-admin'), ], 'label_block' => true, ], 'css_bhead_typo' => [ 'label' => esc_html__('Heading Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .block-head .heading', 'default' => [], ], 'css_bhead_space_below' => [ 'label' => esc_html__('Space Below', 'bunyad-admin'), 'type' => 'slider', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .block-head' => '--space-below: {{SIZE}}{{UNIT}};' ], 'default' => [], ], // Note: Only makes sense for elementor, not for customizer. 'css_bhead_accent' => [ 'label' => esc_html__('Heading Accent Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .block-head' => '--c-main: {{VALUE}}; --c-block: {{VALUE}};' ], 'default' => '', 'condition' => [ 'heading_type!' => ['g'] ] ], 'css_bhead_accent_sd' => [ 'label' => esc_html__('Dark: Heading Accent', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .s-dark .block-head, .s-dark {{WRAPPER}} .block-head' => '--c-main: {{VALUE}}; --c-block: {{VALUE}};' ], 'default' => '', 'condition' => [ 'heading_type!' => ['g'] ] ], 'css_bhead_color' => [ 'label' => esc_html__('Heading Text Color', 'bunyad-admin'), 'type' => 'color', // 'description' => esc_html__('Category color or theme main color will be used by default.', 'bunyad-admin'), 'selectors' => [ '{{WRAPPER}} .block-head .heading' => 'color: {{VALUE}};' ], 'default' => '', ], 'css_bhead_color_sd' => [ 'label' => esc_html__('Dark: Heading Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .s-dark .block-head .heading, .s-dark {{WRAPPER}} .block-head .heading' => 'color: {{VALUE}};' ], 'default' => '', ], 'css_bhead_line_weight' => [ 'label' => esc_html__('Accent Line Weight', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .block-head' => '--line-weight: {{VALUE}}px;' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_line_weight']], ], 'css_bhead_line_width' => [ 'label' => esc_html__('Accent Line Width', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .block-head' => '--line-width: {{VALUE}}px;' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_line_width']], ], 'css_bhead_line_color' => [ 'label' => esc_html__('Accent Line Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .block-head' => '--c-line: {{VALUE}};' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_line_color']], ], 'css_bhead_line_color_sd' => [ 'label' => esc_html__('Dark: Accent Line Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .s-dark .block-head, .s-dark {{WRAPPER}} .block-head' => '--c-line: {{VALUE}};' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_line_color']], ], // Only for style c and h. 'css_bhead_border_weight' => [ 'label' => esc_html__('Border Line Weight', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .block-head' => '--border-weight: {{VALUE}}px;' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_border_weight']], ], 'css_bhead_border_color' => [ 'label' => esc_html__('Border Line Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .block-head' => '--c-border: {{VALUE}};' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_border_color']], ], 'css_bhead_border_color_sd' => [ 'label' => esc_html__('Dark: Border Line Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .s-dark .block-head, .s-dark {{WRAPPER}} .block-head' => '--c-border: {{VALUE}};' ], 'default' => '', 'condition' => ['heading_type' => $this->common['supports_bhead_border_color']], ], 'css_bhead_bg' => [ 'label' => esc_html__('Background Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .block-head' => 'background-color: {{VALUE}};' ], 'default' => '', ], 'css_bhead_pad' => [ 'label' => esc_html__('Padding', 'bunyad-admin'), 'type' => 'dimensions', 'size_units' => ['%', 'px'], 'devices' => true, 'selectors' => [ '{{WRAPPER}} .block-head' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], 'condition' => ['heading_type!' => ['e']], ], 'css_bhead_inner_pad' => [ 'label' => esc_html__('Inner Padding', 'bunyad-admin'), 'type' => 'number', 'devices' => true, 'selectors' => [ '{{WRAPPER}} .block-head' => '--inner-pad: {{VALUE}}px;' ], 'default' => [], 'condition' => ['heading_type' => ['e']], ], 'css_bhead_roundness' => [ 'label' => esc_html__('Roundness', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .block-head' => '--box-roundness: {{VALUE}}px;' ], 'default' => [], 'condition' => ['heading_type' => $this->common['supports_bhead_roundness']], ], 'css_bhead_filters_typo' => [ 'label' => esc_html__('Filters Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .block-head .filters', 'default' => [], ], 'h-style-view-more' => [ 'label' => esc_html__('View More Link', 'bunyad-admin'), 'type' => 'heading', 'separator' => 'before', 'condition' => ['heading_more_text!' => ''], ], 'css_bhead_more_typo' => [ 'label' => esc_html__('More Link Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .block-head .view-link', 'default' => [], 'condition' => ['heading_more_text!' => ''], ], 'css_bhead_more_pad' => [ 'label' => esc_html__('More Link Padding', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'selector' => '{{WRAPPER}} .block-head .view-link', 'selectors' => [ '{{WRAPPER}} .block-head .view-link' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'condition' => ['heading_more_text!' => ''], ], ]; /** * Style: Load More */ $options['sec-style-pagination'] = [ 'css_pagination_margin' => [ 'label' => esc_html__('Pagination Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['px'], 'selectors' => [ '{{WRAPPER}} .loop + .main-pagination' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'load_more_style' => [ 'label' => esc_html__('Load More Style', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Default / Global', 'bunyad-admin'), ] + $this->common['load_more_options'], 'label_block' => true, 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_typo' => [ 'label' => esc_html__('Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .load-button', 'default' => [], 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_color' => [ 'label' => esc_html__('Text Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .load-button' => 'color: {{VALUE}};' ], 'default' => '', 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_color_sd' => [ 'label' => esc_html__('Dark: Text Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark {{WRAPPER}} .load-button, {{WRAPPER}} .s-dark .load-button' => 'color: {{VALUE}};' ], 'default' => '', 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_bg' => [ 'label' => esc_html__('Button Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .load-button' => 'background-color: {{VALUE}};' ], 'default' => '', 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_bg_sd' => [ 'label' => esc_html__('Dark: Button Background', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '.s-dark {{WRAPPER}} .load-button, {{WRAPPER}} .s-dark .load-button' => 'background-color: {{VALUE}};' ], 'default' => '', 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_bg_sd' => [ 'label' => esc_html__('Border Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .load-button' => 'border-color: {{VALUE}};' ], 'default' => '', 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_pad' => [ 'label' => esc_html__('Button Padding', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['px'], 'selectors' => [ '{{WRAPPER}} .load-button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_width' => [ 'label' => esc_html__('Button Width', 'bunyad-admin'), 'type' => 'slider', 'devices' => false, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .load-button' => 'width: {{SIZE}}{{UNIT}}; min-width: 0;' ], 'default' => [], 'condition' => ['pagination_type' => 'load-more'] ], 'css_load_more_bradius' => [ 'label' => esc_html__('Border Radius', 'bunyad-admin'), 'type' => 'number', 'default' => '', 'selectors' => [ '{{WRAPPER}} .load-button' => 'border-radius: {{VALUE}}px' ], 'condition' => ['pagination_type' => 'load-more'] ], ]; /** * Style: Category labels */ $options['sec-style-cat-labels'] = [ '_n_cat_labels' => [ 'type' => 'html', 'raw' => esc_html__('These only apply to category overlay label style, when enabled for this block.', 'bunyad-admin'), 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info', ], 'css_cat_labels_typo' => [ 'label' => esc_html__('Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .cat-labels .category', ], 'css_cat_labels_bg' => [ 'label' => esc_html__('Background Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .cat-labels .category' => 'background-color: {{VALUE}}' ], ], 'css_cat_labels_color' => [ 'label' => esc_html__('Text Color', 'bunyad-admin'), 'type' => 'color', 'selectors' => [ '{{WRAPPER}} .cat-labels .category' => 'color: {{VALUE}}' ], ], 'css_cat_labels_border_radius' => [ 'label' => esc_html__('Border Radius', 'bunyad-admin'), 'type' => 'number', 'selectors' => [ '{{WRAPPER}} .cat-labels .category' => 'border-radius: {{VALUE}}px' ], ], 'css_cat_labels_pad' => [ 'label' => esc_html__('Padding', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .cat-labels .category' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], ], 'css_cat_labels_margins' => [ 'label' => esc_html__('Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .cat-labels .category' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], ], ]; return $options; } public function get_common_data(array $options = []) { $options['meta_options'] = [ 'cat' => esc_html__('Category', 'bunyad-admin'), 'author' => esc_html__('Author', 'bunyad-admin'), 'date' => esc_html__('Date', 'bunyad-admin'), 'comments' => esc_html__('Comments', 'bunyad-admin'), 'read_time' => esc_html__('Read Time', 'bunyad-admin'), ]; /** * Carousel fields aren't to be used elsewhere, so defined here. */ $options['carousel_fields'] = [ 'carousel' => [ 'label' => esc_html__('Enable Carousel', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', ], 'carousel_slides' => [ 'label' => esc_html__('Custom Slides', 'bunyad-admin'), 'description' => esc_html__('Optional. Columns number by default.', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 1, 'max' => 7], 'default' => '', 'condition' => ['carousel' => '1'] ], 'carousel_slides_md' => [ 'label' => esc_html__('Slides: Tablets', 'bunyad-admin'), 'description' => esc_html__('Optional. Auto by default.', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 1, 'max' => 7], 'default' => '', 'condition' => ['carousel' => '1'] ], 'carousel_slides_sm' => [ 'label' => esc_html__('Slides: Phones', 'bunyad-admin'), 'description' => esc_html__('Optional. Auto by default.', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 1, 'max' => 7], 'default' => '', 'condition' => ['carousel' => '1'] ], 'carousel_arrows' => [ 'label' => esc_html__('Arrows', 'bunyad-admin'), 'type' => 'select', 'options' => [ '' => esc_html__('Disabled', 'bunyad-admin'), 'a' => esc_html__('A: Transparent (Dark BG Only)', 'bunyad-admin'), 'b' => esc_html__('B: Modern Round', 'bunyad-admin'), ], 'default' => '', ], 'carousel_dots' => [ 'label' => esc_html__('Navigation Dots', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'condition' => ['carousel' => '1'] ], 'carousel_autoplay' => [ 'label' => esc_html__('Autoplay', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', 'condition' => ['carousel' => '1'] ], 'carousel_play_speed' => [ 'label' => esc_html__('Autoplay Speed', 'bunyad-admin'), 'type' => 'number', 'input_attrs' => ['min' => 50], 'default' => '', 'condition' => ['carousel' => '1'] ], 'css_carousel_nav_spacing' => [ 'label' => esc_html__('Navigation Dots Distance', 'bunyad-admin'), 'description' => '', 'type' => 'number', 'devices' => true, 'selectors' => [ '{{WRAPPER}} .common-slider .nav-dots' => 'margin-top: {{SIZE}}px;' ], 'default' => [], ], ]; return parent::get_common_data($options); } /** * Get option sections */ public function get_sections() { return [ 'sec-general' => ['label' => esc_html__('General', 'bunyad-admin')], 'sec-layout' => ['label' => esc_html__('Layout', 'bunyad-admin')], 'sec-filter' => ['label' => esc_html__('Posts Source', 'bunyad-admin')], 'sec-heading' => ['label' => esc_html__('Heading', 'bunyad-admin')], 'sec-style' => [ 'label' => esc_html__('Style', 'bunyad-admin'), 'tab' => 'style' ], 'sec-style-titles' => [ 'label' => esc_html__('Style: Post Titles', 'bunyad-admin'), 'tab' => 'style' ], 'sec-style-content' => [ 'label' => esc_html__('Style: Content & Box', 'bunyad-admin'), 'tab' => 'style' ], 'sec-style-bhead' => [ 'label' => esc_html__('Style: Block Heading', 'bunyad-admin'), 'tab' => 'style', ], 'sec-style-pagination' => [ 'label' => esc_html__('Style: Pagination', 'bunyad-admin'), 'tab' => 'style', ], 'sec-style-cat-labels' => [ 'label' => esc_html__('Style: Category Labels', 'bunyad-admin'), 'tab' => 'style' ], ]; } /** * Generate number of column options based on supported. * * @return array */ public function _option_columns() { $column_options = [ '1' => esc_html__('1 Column', 'bunyad-admin'), '2' => esc_html__('2 Columns', 'bunyad-admin'), '3' => esc_html__('3 Columns', 'bunyad-admin'), '4' => esc_html__('4 Columns', 'bunyad-admin'), '5' => esc_html__('5 Columns', 'bunyad-admin'), '6' => esc_html__('6 Columns', 'bunyad-admin'), ]; if (!is_array($this->supported_columns)) { $this->supported_columns = range(1, intval($this->supported_columns)); } // Remove unsupported. $column_options = array_filter( $column_options, function($value) { return in_array($value, $this->supported_columns); }, ARRAY_FILTER_USE_KEY ); $options = [ '' => esc_html__('Auto', 'bunyad-admin'), ]; $options += $column_options; return $options; } /** * Get categories for control options */ public function _option_categories() { $categories = $this->get_limited_terms('category', $this->limit_cats); return $this->_recurse_terms_array(0, $categories); } /** * Get tags for control options * * @deprecated 5.1.0 */ public function _option_tags() { $tags = $this->get_limited_terms('post_tag'); return $this->_recurse_terms_array(0, $tags); } /** * Image sizing options for blocks * * @deprecated 5.1.0 */ public function _option_images() { global $_wp_additional_image_sizes; foreach (get_intermediate_image_sizes() as $_size) { // Default sizes if (in_array($_size, array('thumbnail', 'medium', 'medium_large', 'large'))) { $size = [ 'width' => get_option("{$_size}_size_w"), 'height' => get_option("{$_size}_size_h"), ]; } else if (isset($_wp_additional_image_sizes[ $_size ])) { $size = $_wp_additional_image_sizes[ $_size ]; } $sizes[$_size] = "{$size['width']}x{$size['height']} - {$_size}"; } $sizes = array_merge( [ '' => esc_html__('Default / Auto', 'bunyad-admin'), ], $sizes ); return $sizes; } /** * Get terms (from cache if already called), with a limit applied. * * @param string $taxonomy * @param integer $limit * @return array */ protected function get_limited_terms($taxonomy, $limit = 200) { if (isset($this->terms_cache[$taxonomy])) { return $this->terms_cache[$taxonomy]; } $terms = []; switch ($taxonomy) { case 'post_tag': $terms = get_terms('post_tag', [ 'hide_empty' => false, 'order_by' => 'count', 'number' => $limit ]); break; default: $terms = get_terms($taxonomy, [ 'hide_empty' => false, 'hide_if_empty' => false, 'hierarchical' => 1, 'order_by' => 'name', 'number' => $limit ]); break; } $this->terms_cache[$taxonomy] = $terms; return $terms; } /** * Add AJAX config for an option, if the terms exceed a certain number. * * @param array $option * @param string $type categories or tags. * @param integer $limit * @return array */ protected function maybe_ajax_for_terms($option, $type, $limit = null) { switch ($type) { case 'tags': $taxonomy = 'post_tag'; break; case 'categories': $taxonomy = 'category'; // Keep same as _option_categories for cache. $limit = $limit ? $limit : $this->limit_cats; break; } // If no limit, assume always. Otherwise test if it's equal or exceeds. if (!$limit || count($this->get_limited_terms($taxonomy, $limit)) >= $limit) { $option = array_replace($option, [ 'type' => 'bunyad-selectize', 'options' => [], 'selectize_options' => [ 'multiple' => !empty($option['multiple']), 'sortable' => false, 'create' => false, 'ajax' => true, 'preload' => true, // Will preload 50 too. 'endpoint' => $type . '?per_page=50&orderby=count&order=desc&_fields=id,name&search={query}', // To fetch existing saved cats by id. 'endpoint_saved' => $type . '?_fields=id,name&include={ids}', ], ]); } return $option; } /** * Create hierarchical terms drop-down via recursion on parent-child relationship * * @param integer $parent * @param object $terms * @param integer $depth */ public function _recurse_terms_array($parent, $terms, $depth = 0) { $the_terms = array(); $output = array(); foreach ($terms as $term) { // add tab to children if ($term->parent == $parent) { $output[ $term->term_id ] = str_repeat(" · ", $depth) . $term->name; $output = array_replace( $output, $this->_recurse_terms_array($term->term_id, $terms, $depth+1) ); } } return $output; } }PK 03Y� �8� � * smartmag-core/blocks/base/options-data.php<?php namespace Bunyad\Blocks\Base; /** * Common base data. */ class OptionsData implements \ArrayAccess { protected $data = []; public function __construct() { $this->data = [ 'cat_labels_pos_options' => [], 'ratio_options' => [], 'read_more_options' => [], 'meta_options' => [], 'reviews_options' => [], 'heading_tags' => [], 'block_headings' => [], 'load_more_options' => [], 'featured_grid_options' => [], 'featured_type_options' => [], 'post_format_pos_options' => [], 'supports_bhead_line_width' => [], 'supports_bhead_line_color' => [], 'supports_bhead_border_color' => [], 'supports_bhead_line_weight' => [], 'supports_bhead_border_weight' => [], 'supports_bhead_roundness' => [], 'post_title_styles' => [], ]; return $this; } #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->offsetExists($offset) ? $this->data[$offset] : null; } public function offsetSet($offset, $value): void { $this->data[$offset] = $value; } public function offsetExists($offset): bool { return isset($this->data[$offset]); } public function offsetUnset($offset): void { if ($this->offsetExists($offset)) { unset($this->data[$offset]); } } public function append($array) { $this->data = array_replace($this->data, $array); return $this->data; } } PK 03Y�N¿ � % smartmag-core/blocks/base/options.php<?php namespace Bunyad\Blocks\Base; use Bunyad\Util; /** * Block options for page builders, widgets and so on. */ abstract class Options { public $options = []; /** * @var array Map of option_key => section_key */ private $options_map = []; /** * @var array Commonly used options data. */ protected $common = []; /** * Block name to be used for displaying. */ public $block_name; /** * Configuration for Elementor Widget */ public $elementor_conf = []; /** * Class name of the associated loop block */ public $block_class; /** * Init and setup options. */ abstract public function init(); /** * Get option sections. * * @return array */ abstract public function get_sections(); /** * Run only when we're in the page builder. * * @return void */ public function init_editor() { // Create a reference map and setup option callbacks. foreach ($this->options as $section_key => $section) { foreach ($section as $key => $option) { $this->options_map[$key] = $section_key; // Run the callback for the options, usually for in editor. $this->options[$section_key][$key] = $this->do_option_callbacks($option); } } // Re-position as needed. foreach ($this->options as $section_key => $section) { foreach ($section as $key => $option) { if (isset($option['position'])) { $this->move_option( $key, $option['position']['of'], $option['position']['at'] ); } } } } /** * Get the class name of the block these options are for */ public function get_block_class() { if (!$this->block_class) { $block_class = explode('\\', get_class($this)); $this->block_class = str_replace( '_Options', '', end($block_class) ); // Special case: Loops. if ($block_class[ count($block_class) - 2 ] === 'Loops') { $this->block_class = 'Loops\\' . $this->block_class; } } $class = '\Bunyad\Blocks\\' . $this->block_class; // Fallback if doesn't exist. if (!class_exists($class)) { $class = '\Bunyad\Blocks\Base\\' . ( strpos($class, 'Loops') !== false ? 'LoopBlock' : 'Block' ); } return $class; } /** * Add defaults from the relevant block to the options */ protected function _add_defaults($props = []) { if (!$props) { $class = $this->get_block_class(); $props = $class::get_default_props(); } foreach ($this->options as $section_key => $section) { foreach ($section as $key => $option) { // This default should be preserved (can't be overwritten). if (!empty($option['default_forced'])) { continue; } // Add default from props. if (array_key_exists($key, $props)) { $new_value = $props[$key]; if (isset($option['default'])) { $expected_type = gettype($option['default']); // Convert boolean and integers to string if string expected as default. if ($expected_type === 'string' && in_array(gettype($new_value), ['boolean', 'integer'])) { $new_value = (string) $new_value; } // Set empty value for switcher with falsey defaults. We want them to be always saved. // As they may inherit from global by default. // if (!$new_value && $option['type'] === 'switcher') { // $new_value = ''; // } } $this->options[$section_key][$key]['default'] = $new_value; } } } } /** * Move an item in the options array. * * @uses \Bunyad\Util\array_insert() * @param string $key The option key to move. * @param string $target Target option key to move before/after. * @param string $position To move 'before' or 'after' the target. * @return void */ public function move_option($key, $target, $position = 'before') { $section = $this->options_map[$key]; $section_target = $this->options_map[$target]; // Remove it first and update section in map. $value = $this->options[$section][$key]; unset($this->options[$section][$key]); $this->options_map[$key] = $section_target; // Move it now. Util\array_insert( $this->options[$section_target], $target, [$key => $value], $position ); } /** * Get all the options. * * @param boolean $key_value Whether to return key => value pairs * @return array */ public function get_all($key_value = false) { if (!$this->options) { $this->init(); } if (!$key_value) { return $this->options; } // Convert to key value pair. $options = []; foreach ($this->options as $section) { foreach ($section as $key => $option) { $options[$key] = $option; } } return $options; } /** * Remove a registered option from the array * * @param array $keys Array of keys to remove */ public function remove_options($keys) { $to_remove = (array) $keys; foreach ($this->options as $sec_key => $section) { foreach ($section as $key => $option) { if (in_array($key, $to_remove)) { unset($this->options[$sec_key][$key]); } } } } /** * Update an existing option array. * * @param string $key * @param array $value * @return void */ public function change_option($key, $value) { $to_change = [$key => $value]; foreach ($this->options as $sec_key => $section) { foreach ($section as $key => $option) { if (!isset($to_change[$key])) { continue; } if (is_array($to_change[$key])) { $this->options[$sec_key][$key] = array_replace( $this->options[$sec_key][$key], $to_change[$key] ); } else { $this->options[$sec_key][$key] = $to_change[$key]; } } } } /** * Do the callbacks for a specified options. * * This will ensure it's called via correct scope and protected methods get called. * * @param array $option * @return array */ public function do_option_callbacks(array $option) { if (isset($option['editor_callback']) && is_callable($option['editor_callback'])) { $option = call_user_func($option['editor_callback'], $option); unset($option['editor_callback']); } if (isset($option['options']) && is_callable($option['options'])) { $option['options'] = call_user_func($option['options']); } return $option; } public function get_common_data(array $options = []) { if (!$this->common) { $this->common = new OptionsData; // Replace common from theme. if (is_callable([\Bunyad::core(), 'get_common_data'])) { $options = array_replace($options, (array) \Bunyad::core()->get_common_data('options')); } } if (count($options)) { $this->common->append($options); } return $this->common; } }PK 03Y˻��9 9 # smartmag-core/blocks/base/query.php<?php namespace Bunyad\Blocks\Base; use \WP_Query; /** * Dynamic Blocks Query Class */ class Query { protected $block; protected $data = []; protected $props = []; protected $query_args = []; /** * @param Bunyad_Blocks_Base $block */ public function __construct($props = [], $block = null) { $this->props = $props; $this->block = $block; } /** * Process props and setup the query * * @return \WP_Query|null */ public function setup() { /** * Applying a heading filter. Set the correct term/cat. */ if ($this->props['filter']) { unset( $this->props['cat'], $this->props['offset'], $this->props['orig_offset'] ); $taxonomy = 'category'; if ($this->props['filters'] === 'tag') { $taxonomy = 'post_tag'; } // Only for shortcode yet. if ($this->props['filters_tax']) { $taxonomy = $this->props['filters_tax']; } $this->props = array_replace($this->props, [ 'query_type' => 'custom', 'tax_ids' => [$this->props['filter']], 'filters' => false, 'taxonomy' => $taxonomy, ]); } /** * Setup and execute the query. */ if (isset($props['query_args']) && is_array($props['query_args'])) { $this->query_args = $props['query_args']; } if (isset($this->props['cat']) && $this->props['cat'] === '__current') { $main = get_queried_object(); if (is_object($main) && !empty($main->term_id)) { $this->props['cat'] = $main->term_id; } } $this->query_args = array_replace($this->query_args, [ 'posts_per_page' => (!empty($this->props['posts']) ? intval($this->props['posts']) : 4), 'post_status' => 'publish', 'order' => ($this->props['sort_order'] == 'asc' ? 'asc' : 'desc'), ]); $this->setup_query_data(); // Add a filter $query_args = apply_filters( 'bunyad_block_query_args', $this->query_args, $this->block, $this->props // redundant but backward compatibility ); $this->data['query'] = new WP_Query($query_args); // Disable title if empty if (empty($this->data['heading']) && is_object($this->block)) { $this->block->props['heading_type'] = 'none'; } // Process filters $this->process_filters(); return $this->data; } /** * Processs and setup the query args and block data. * * @return array */ public function setup_query_data() { $props = $this->props; /** * Setup internal variables and some legacy aliases. */ // Main category / taxonomy term object. $term = ''; $main_term = ''; $link = ''; $title = $props['heading']; /** * Initialize the query args. */ $query_args = array_replace($this->query_args, [ 'posts_per_page' => !empty($props['posts']) ? intval($props['posts']) : '', 'offset' => !empty($props['offset']) ? $props['offset'] : '' ]); $query_args = array_filter($query_args); if (isset($props['sticky_posts']) && !$props['sticky_posts']) { $query_args['ignore_sticky_posts'] = 1; } if (!empty($props['skip_posts'])) { $offset = !empty($query_args['offset']) ? $query_args['offset'] : ''; $query_args['offset'] = intval($offset) + intval($props['skip_posts']); } // Add pagination if available. if (!empty($props['page'])) { $query_args['paged'] = $props['page']; } /** * Sortng criteria and order. */ if (!empty($props['sort_order'])) { $query_args['order'] = $props['sort_order'] == 'asc' ? 'asc' : 'desc'; } $sort_by = !empty($props['sort_by']) ? $props['sort_by'] : ''; switch ($sort_by) { case 'modified': $query_args['orderby'] = 'modified'; break; case 'random': $query_args['orderby'] = 'rand'; break; case 'comments': $query_args['orderby'] = 'comment_count'; break; case 'alphabetical': $query_args['orderby'] = 'title'; break; case 'rating': $query_args = array_replace( $query_args, [ 'meta_key' => '_bunyad_review_overall', 'orderby' => 'meta_value_num' ] ); break; case 'jetpack_views': $jetpack_args = $this->get_jetpack_args(); $query_args = array_replace($query_args, $jetpack_args); break; case 'views': case 'views-7days': case 'views-days': $query_args = array_replace($query_args, $this->get_post_views_args()); break; } /** * Limit by custom taxonomy? * * Note: Only makes sense if there are tax_ids provided too as you can't get all * posts from a taxonomy. That's same as getting all posts, a la posts from all post_tags. * But we have added a fallback since v7.0.1 * * Important: Also used by filters. */ if (!empty($props['taxonomy'])) { $_taxonomy = $props['taxonomy']; $terms = !empty($props['tax_ids']) ? (array) $props['tax_ids'] : (array) $props['terms']; // Backward compat: Add main cat to terms list, if any. if (!empty($props['cat'])) { array_push($terms, $props['cat']); } // Get all the terms that belong to this taxonomy if no taxonomy ids specified. if (empty($terms)) { $_terms = get_terms([ 'taxonomy' => $_taxonomy, 'hide_empty' => false ]); if ($_terms) { $terms = wp_list_pluck($_terms, 'term_id'); } } if (!empty($terms)) { $query_args['tax_query'] = [[ 'taxonomy' => $_taxonomy, 'field' => 'term_id', 'terms' => $terms ]]; // Get and configure the main term. $term = get_term_by('id', (!empty($props['cat']) ? $props['cat'] : current($terms)), $_taxonomy); if (empty($title)) { $title = $term->name; } $link = get_term_link($term, $_taxonomy); } } else { // Terms / cats may have slug strings instead of ids. if (!empty($props['terms'])) { $terms = $props['terms']; $slug_terms = $this->get_slug_ids($props['terms']); if ($slug_terms) { $terms = array_merge($props['terms'], $slug_terms); } } else { $terms = []; } /** * Got main category/term? Use it for filter, link, and title */ if (!empty($props['cat'])) { // Might be an id or a slug $term = $category = is_numeric($props['cat']) ? get_category($props['cat']) : get_category_by_slug($props['cat']); // Category is always the priority main term $main_term = $term; if (!empty($category)) { array_push($terms, $category->term_id); if (empty($title)) { $title = $category->cat_name; } if (empty($link)) { $link = get_category_link($category); } } } /** * Filtering by tag(s)? */ if (!empty($props['tags'])) { $tag_ids = $props['tags']; // Get ids from slugs, if any. $slug_terms = $this->get_slug_ids($props['tags'], 'post_tag'); if ($slug_terms) { $tag_ids = array_merge($tag_ids, $slug_terms); } if ($tag_ids) { $query_args['tag__in'] = $tag_ids; } // Legacy: Get the first tag for main term, assuming it's a slug. $tax_tag = current($props['tags']); if (!is_numeric($tax_tag)) { $term = get_term_by('slug', $tax_tag, 'post_tag'); if ($term) { // Use the first tag as main term if a category isn't already the main term if (!$main_term) { $main_term = $term; } if (empty($title)) { $title = $term->slug; } if (empty($link)) { $link = get_term_link($term, 'post_tag'); } } } } /** * Multiple categories/terms filter */ if (count($terms)) { $query_args['cat'] = join(',', $terms); // No category as main and no tag either? Pick first category from multi cats. if (!$main_term) { $main_term = current($terms); } } } /** * By specific post IDs? */ if (!empty($props['post_ids'])) { $ids = array_map('intval', $props['post_ids']); $query_args['post__in'] = $ids; } /** * Post Formats? */ if (!empty($props['post_formats'])) { if (!isset($query_args['tax_query'])) { $query_args['tax_query'] = []; } // Add post format prefix $formats = array_map(function($val) { return 'post-format-' . trim($val); }, $props['post_formats']); $query_args['tax_query'][] = [ 'taxonomy' => 'post_format', 'field' => 'slug', 'terms' => (array) $formats, ]; } /** * Exclude posts IDs. */ if (!empty($props['exclude_ids'])) { $ids = array_map('intval', (array) $props['exclude_ids']); $query_args['post__not_in'] = $ids; } /** * Exclude tags by ids or slugs. */ if (!empty($props['exclude_tags'])) { $tag_ids = $props['exclude_tags']; // Get ids from slugs, if any. $slug_terms = $this->get_slug_ids($tag_ids, 'post_tag'); if ($slug_terms) { $tag_ids = array_merge($tag_ids, $slug_terms); } if ($tag_ids) { $query_args['tag__not_in'] = $tag_ids; } } /** * Exclude terms (mainly categories) by ids or slugs. */ if (!empty($props['exclude_terms'])) { $exclude_term_ids = $props['exclude_terms']; // Get ids from slugs, if any. $slug_terms = $this->get_slug_ids($exclude_term_ids); if ($slug_terms) { $tag_ids = array_merge($exclude_term_ids, $slug_terms); } if ($exclude_term_ids) { $taxonomy = $props['taxonomy'] ?: 'category'; if (!isset($query_args['tax_query'])) { $query_args['tax_query'] = []; } $query_args['tax_query'][] = [ 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $exclude_term_ids, 'operator' => 'NOT IN', ]; } } /** * Review Posts Only. */ if (!empty($props['reviews_only'])) { $query_args['meta_key'] = '_bunyad_review_overall'; } /** * Custom Post Types? * * Legacy: Supports multiple post types */ if (!empty($props['post_type'])) { $query_args['post_type'] = array_map('trim', explode(',', $props['post_type'])); } /** * Enable post views additions for Sphere Post Views. */ if (!empty($this->props['post_views'])) { $query_args['views_query'] = $query_args['views_query'] ?? []; } // Setup accessible variables $this->data = array_replace($this->data, [ 'term_link' => $link, 'heading' => $title, 'query_args' => $query_args, 'term' => $main_term, 'display_filters' => [], ]); $this->query_args = $query_args; return $query_args; } /** * Get term IDs given term slugs of a taxonomy. * * Note: Numeric slugs will be ignored. * * @param array $slugs * @param string $taxonomy * @return array */ protected function get_slug_ids(array $slugs, $taxonomy = 'category') { $terms = []; $slug_terms = []; // Ignore numeric slugs. foreach ((array) $slugs as $term) { if (!is_numeric($term)) { array_push($slug_terms, $term); } } // If we have slug terms, get their ids and add. if ($slug_terms) { $results = get_terms($taxonomy, [ 'slug' => $slug_terms, 'hide_empty' => false, 'hierarchical' => false ]); if ($results) { $terms = wp_list_pluck($results, 'term_id'); } } return $terms; } /** * Get Sphere Post Views sort arguments to add to the query. * * @return array */ public function get_post_views_args() { // Fallback to comments if plugin not active. if (!class_exists('\Sphere\PostViews\Plugin')) { return [ 'orderby' => 'comment_count' ]; } $sort = $this->props['sort_by']; $query_args = [ 'orderby' => 'post_views' ]; if ($sort !== 'views') { switch ($sort) { case 'views-7days': $days = 7; break; default: $days = $this->props['sort_days'] <= 0 ? 30 : $this->props['sort_days']; break; } $query_args['views_query'] = [ 'range' => true, 'time_unit' => 'day', 'time_quantity' => $days, 'add_totals' => false, ]; } return $query_args; } /** * Get query args to fetch posts based on Jetpack Views Counters sort. * * @uses \stats_get_csv() * @return array Query args to add. */ public function get_jetpack_args() { if (!function_exists('\stats_get_csv')) { return []; } /** * Get posts by views from Jetpack stat module (wordpress.com stats) */ $post_views = \stats_get_csv('postviews', [ 'days' => absint($this->props['sort_days']), 'limit' => 100 ]); $post_ids = array_filter(wp_list_pluck((array) $post_views, 'post_id')); $query_args = []; // No posts found to be sorted by views. if (!$post_ids || !count($post_ids)) { // Fallback to comment count. $query_args['orderby'] = 'comment_count'; } else { // Use specific posts to get if available. $query_args += [ 'offset' => 0, 'post__in' => $post_ids, 'orderby' => 'post__in' ]; } return $query_args; } /** * Process block filters to be used later in the heading. */ public function process_filters() { $props = $this->props; if (empty($props['filters']) || !is_object($this->block)) { return; } $display_filters = array(); /** * Process display filters - supports ids or slugs */ $filters_terms = $props['filters_terms']; if (!empty($props['filters_tags'])) { $filters_terms = $props['filters_tags']; } // Which taxonomy? Default to category $tax = 'category'; if ($props['filters'] == 'tag') { $tax = 'post_tag'; } // Not implemented in Elementor yet. Shortcode only. else if ($props['filters'] == 'taxonomy' && !empty($props['filters_tax'])) { $tax = $props['filters_tax']; } // Auto-select 3 sub-cats for category if terms are missing if ($tax == 'category' && empty($filters_terms) && is_object($this->data['term'])) { $filters_terms = wp_list_pluck( get_categories(array( 'child_of' => $this->data['term']->term_id, 'number' => 3, 'hierarchical' => false )), 'term_id' ); } // Still no filter terms? if (empty($filters_terms)) { return; } foreach ($filters_terms as $id) { // Supports slugs if (!is_numeric($id)) { $term = get_term_by('slug', $id, $tax); } else { $term = get_term($id); } if (!is_object($term)) { continue; } $link = get_term_link($term); $display_filters[] = '<li><a href="'. esc_url($link) .'" data-id="' . esc_attr($term->term_id) . '">'. esc_html($term->name) .'</a></li>'; } return ($this->data['display_filters'] = $display_filters); } public function get_data() { return $this->data; } }PK 03Y��h8 0 smartmag-core/blocks/breadcrumbs/breadcrumbs.php<?php namespace Bunyad\Blocks; use \Bunyad; use Bunyad\Blocks\Base\Block; /** * Breadcrumbs block. */ class Breadcrumbs extends Block { public $id = 'breadcrumbs'; /** * @inheritdoc */ public static function get_default_props() { $props = [ 'classes' => '', 'inner_classes' => '', 'style' => 'b', 'width' => 'full', 'disable_at' => [], 'enabled' => true, // @deprecated v9.2, use renderer instead. 'use_yoast' => true, // Empty is auto. Options: rankmath, sphere, yoast. 'renderer' => '', // Add context like Category: etc. 'add_context' => 1, // Add You Are At: label. 'add_label' => false, 'label_text' => '', 'show_current_single' => true, ]; // Setup from global options. if (Bunyad::options()) { // Set if enabled. $props = array_replace($props, [ 'enabled' => Bunyad::options()->breadcrumbs_enable, 'add_label' => Bunyad::options()->breadcrumbs_add_label, 'renderer' => Bunyad::options()->breadcrumbs_renderer, 'label_text' => Bunyad::options()->get_or( 'breadcrumbs_label_text', esc_html_x('You are at:', 'breadcrumbs', 'bunyad') ), 'style' => Bunyad::options()->breadcrumbs_style, 'add_context' => Bunyad::options()->breadcrumbs_add_context, 'show_current_single' => Bunyad::options()->breadcrumbs_current_single, ]); // Only valid for style b. if ($props['style'] === 'b') { $props['width'] = Bunyad::options()->breadcrumbs_width; } // Find disabled locations from theme settings. // Note: Homepage is disabled by default by the Sphere breadcrumbs. $location_keys = [ 'single', 'page', 'search', 'archive' ]; $disable_at = []; foreach ($location_keys as $key) { if (!Bunyad::options()->get('breadcrumbs_' . $key)) { $disable_at[] = $key; } } $props['disable_at'] = $disable_at; } return $props; } /** * Render the breadcrumbs. * * @return void */ public function render() { // Check if Yoast or RankMath SEO's Breadcrumbs are enabled or chosen as renderer. $is_yoast = $this->is_yoast(); $is_rankmath = $this->is_rankmath(); // Neither theme nor Yoast's Breadcrumbs enabled. if (!$is_yoast && !$is_rankmath && !$this->props['enabled']) { return; } // Sphere Core Class is required. if (!class_exists('\Sphere\Core\Plugin', false)) { return; } $wrap_classes = array_filter(array_merge( [ 'breadcrumbs', $this->props['width'] !== 'full' ? 'ts-contain' : 'is-full-width', 'breadcrumbs-' . $this->props['style'], ], (array) $this->props['classes'] )); $inner_classes = array_merge(['inner ts-contain'], (array) $this->props['inner_classes']); $before = sprintf( '<nav class="%1$s" id="breadcrumb"><div class="%2$s">', esc_attr(join(' ', $wrap_classes)), esc_attr(join(' ', $inner_classes)) ); if ($this->props['add_label']) { $before .= '<span class="label">' . esc_html($this->props['label_text']) .'</span>'; } $after = '</div></nav>'; // Output using RankMath breadcrumbs. if ($is_rankmath) { return \rank_math_the_breadcrumbs([ 'wrap_before' => $before, 'wrap_after' => $after, ]); } // Output Yoast Breadcrumbs. if ($is_yoast) { return \yoast_breadcrumb($before, $after); } /** @var \Sphere\Core\Breadcrumbs\Module $breadcrumbs */ $breadcrumbs = \Sphere\Core\Plugin::get('breadcrumbs'); if (!$breadcrumbs) { return; } $labels = [ 'home' => esc_html_x('Home', 'breadcrumbs', 'bunyad'), 'search' => esc_html_x('Search Results for "%s"', 'breadcrumbs', 'bunyad'), '404' => esc_html_x('Error 404', 'breadcrumbs', 'bunyad'), 'paged' => esc_html_x(' (Page %d)', 'breadcrumbs', 'bunyad'), 'category' => '%s', 'tax' => '%s', 'tag' => '%s', 'author' => '%s', ]; if ($this->props['add_context']) { $labels = array_replace($labels, [ 'category' => esc_html_x('Category: "%s"', 'breadcrumbs', 'bunyad'), 'tax' => esc_html_x('Archive for "%s"', 'breadcrumbs', 'bunyad'), 'tag' => esc_html_x('Posts Tagged "%s"', 'breadcrumbs', 'bunyad'), 'author' => esc_html_x('Author: %s', 'breadcrumbs', 'bunyad'), ]); } $breadcrumbs->render([ 'primary_cat_callback' => [Bunyad::blocks(), 'get_primary_cat'], // Spaces added left and right to be same as Yoast. 'delimiter' => '<span class="delim">»</span>', 'before' => $before, 'after' => $after, 'disable_at' => $this->props['disable_at'], 'labels' => $labels, 'show_current_single' => $this->props['show_current_single'], ]); } /** * Check if RankMath Breadcrumb enabled. * * @return boolean */ public function is_rankmath() { if ($this->props['renderer'] === 'sphere') { return false; } if ($this->props['renderer'] === 'rankmath') { return function_exists('rank_math_the_breadcrumbs'); } if (class_exists('\RankMath\Helper', false) && is_callable(['\RankMath\Helper', 'is_breadcrumbs_enabled'])) { if (function_exists('rank_math_the_breadcrumbs')) { return \RankMath\Helper::is_breadcrumbs_enabled(); } } return false; } /** * Check if Yoast Breadcrumb enabled. * * @return boolean */ public function is_yoast() { if ($this->props['renderer'] === 'sphere') { return false; } if (!$this->props['use_yoast']) { return false; } if ($this->props['renderer'] === 'yoast') { return function_exists('yoast_breadcrumb'); } $is_yoast = false; if (class_exists('\WPSEO_Options') && function_exists('yoast_breadcrumb')) { if (is_callable(['WPSEO_Options', 'get']) && \WPSEO_Options::get('breadcrumbs-enable', false)) { $is_yoast = true; } } return $is_yoast; } }PK 03YD�,�P P , smartmag-core/blocks/breadcrumbs/options.php<?php namespace Bunyad\Blocks; /** * Ads block options */ class Breadcrumbs_Options extends Base\Options { public $block_id = 'Breadcrumbs'; public function init($type = '') { // Block name to be used by page builders $this->block_name = esc_html__('Breadcrumbs', 'bunyad-admin'); $this->elementor_conf = [ 'title' => $this->block_name, 'icon' => 'ts-ele-icon eicon-progress-tracker', 'categories' => ['smart-mag-blocks'], ]; /** * General Options. */ $options['sec-general'] = [ 'style' => [ 'label' => esc_html__('Breadcrumbs Style', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'a' => esc_html__('A: Simple', 'bunyad-admin'), 'b' => esc_html__('B: With Background', 'bunyad-admin'), ], 'label_block' => true, 'default' => 'a', ], 'width' => [ 'label' => esc_html__('Breadcrumbs Width', 'bunyad-admin'), 'type' => 'select', 'options' => [ 'full' => esc_html__('Full Width', 'bunyad-admin'), 'wrap' => esc_html__('Site Width', 'bunyad-admin'), ], 'label_block' => true, 'condition' => ['style' => 'b'], 'default' => 'full', ], 'add_label' => [ 'label' => esc_html__('Add Label?', 'bunyad-admin'), 'type' => 'switcher', 'return_value' => '1', 'default' => '1', ], 'renderer' => [ 'label' => esc_html__('Breadcrumbs Renderer', 'bunyad-admin'), 'type' => 'select', 'default' => '', 'options' => [ '' => esc_html__('Auto', 'bunyad-admin'), 'sphere' => esc_html__('Theme Breadcrumbs', 'bunyad-admin'), 'rankmath' => esc_html__('RankMath Plugin', 'bunyad-admin'), 'yoast' => esc_html__('Yoast', 'bunyad-admin'), ], ], 'label_text' => [ 'label' => esc_html__('Label Text', 'bunyad-admin'), 'type' => 'text', 'condition' => ['add_label' => '1'], 'default' => '', ], 'disable_at' => [ 'label' => '', 'type' => 'hidden', 'default' => [] ] ]; /** * Style options. */ $options['sec-style'] = [ 'css_margins' => [ 'label' => esc_html__('Margins', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .breadcrumbs' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_paddings' => [ 'label' => esc_html__('Padding', 'bunyad-admin'), 'type' => 'dimensions', 'devices' => true, 'size_units' => ['%', 'px'], 'selectors' => [ '{{WRAPPER}} .breadcrumbs' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'default' => [], ], 'css_typography' => [ 'label' => esc_html__('Typography', 'bunyad-admin'), 'type' => 'group', 'group_type' => 'typography', 'selector' => '{{WRAPPER}} .breadcrumbs', 'default' => [], ], ]; $this->options = $options; $this->_add_defaults(); } public function get_sections() { return [ 'sec-general' => [ 'label' => esc_html__('General', 'bunyad-admin') ], 'sec-style' => [ 'label' => esc_html__('Style', 'bunyad-admin'), 'tab' => 'style' ], ]; } }PK 03Y��Y�q q $ smartmag-core/blocks/codes/codes.php<?php namespace Bunyad\Blocks; use \Bunyad; use Bunyad\Blocks\Base\Block; /** * Ads and Custom Code block. */ class Codes extends Block { public $id = 'codes'; /** * @inheritdoc */ public static function get_default_props() { $props = [ 'label' => '', 'code' => '', 'code_amp' => '', ]; return $props; } /** * Render all of the post meta HTML. * * @return void */ public function render() { $label = ''; if ($this->props['label']) { $label = sprintf('<div class="label">%s</div>', esc_html($this->props['label'])); } $wrap = sprintf( '<div class="a-wrap">%1$s %2$s</div>', $label, // This code is saved by valid priveleged users. Bunyad::amp()->active() ? $this->props['code_amp'] : $this->props['code'] ); $wrap = str_replace('<img', '<img loading="lazy"', $wrap); echo do_shortcode($wrap); } }PK 03Y�� &