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/fyntric.com/wp-content/themes/smart-mag/lib/vendor/plugins/ |
Upload File : |
PK 03Y�Ĕ�� � sphere-core/sphere-core.php<?php /** * Plugin Name: Sphere Core * Plugin URI: https://theme-sphere.com * Description: Core plugin for ThemeSphere themes. * Version: 1.6.9 * Requires PHP: 7.0 * Author: ThemeSphere * Author URI: https://theme-sphere.com * License: GPL2 */ namespace Sphere\Core; // Note: This class name will NOT change due to dependencies class Plugin { /** * @since 1.0.2 */ const VERSION = '1.6.9'; public $components; public $registry; protected static $instance; /** * Path to plugin folder, trailing slashed. */ public $path; public $path_url; public function __construct() { $this->path = plugin_dir_path(__FILE__); // URL for the plugin dir $this->path_url = plugin_dir_url(__FILE__); add_action('bunyad_core_pre_init', array($this, 'setup')); /** * Directory path to components * @deprecated 1.1.4 */ define('SPHERE_COMPONENTS', plugin_dir_path(__FILE__) . 'components/'); define('SPHERE_LIBS_VENDOR', plugin_dir_path(__FILE__) . 'components/vendor/'); /** * Register autoloader. Usually uses the loader from theme if present. */ if (!class_exists('\Bunyad\Lib\Loader', false)) { require_once $this->path . 'lib/loader.php'; } $loader = new \Bunyad\Lib\Loader([ 'Sphere\Core\\' => $this->path . 'components', ]); require_once $this->path . 'lib/plugin-updates.php'; new \Bunyad_Plugin_Updates; } /** * Initialize and include the components * * Note: Setup is called before after_setup_theme and Bunyad::options()->init() * at the hook bunyad_core_pre_init. */ public function setup() { /** * Registered components can be filtered with a hook at bunyad_core_pre_init or in the * Bunyad::core()->init() bootstrap function via the key sphere_components. */ $this->components = apply_filters('sphere_plugin_components', array( 'social-share', 'likes', 'social-follow', // 'breadcrumbs', // 'auto-load-post', // 'adblock-detect', // 'elementor\layouts', // 'elementor\dynamic-tags' )); foreach ($this->components as $component) { $module_name = implode('', array_map('ucfirst', explode('-', $component))); $class = '\Sphere\Core\\' . $module_name . '\Module'; if (class_exists($class)) { // Use singleton or init new instance. $this->registry[$component] = ( method_exists($class, 'instance') ? $class::instance() : new $class ); // Legacy: Aliases for legacy versions. Deprecated. class_alias($class, 'Sphere_Plugin_' . $module_name); } } } /** * Static shortcut to retrieve component object from registry * * @param string $component * @return object|boolean */ public static function get($component) { $object = self::instance(); if (isset($object->registry[$component])) { return $object->registry[$component]; } return false; } /** * Get singleton object * * @return self */ public static function instance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } } // Legacy: Aliases for legacy versions. Deprecated. class_alias('\Sphere\Core\Plugin', 'Sphere_Plugin_Core'); Plugin::instance();PK 03Y���^D D 0 sphere-core/components/adblock-detect/module.php<?php namespace Sphere\Core\AdblockDetect; use Sphere\Core\Plugin; /** * Adblocker Detection. */ class Module { protected $path_url; protected $path; public function __construct() { $this->path_url = Plugin::instance()->path_url . 'components/adblock-detect/'; $this->path = Plugin::instance()->path . 'components/adblock-detect/'; add_action('wp', [$this, 'setup']); $options = new Options; $options->register_hooks(); } public function setup() { // Only for ThemeSphere themes. if (!class_exists('\Bunyad', false)) { return; } // Auto-load next post is disabled. The filter can return true to force enable. $is_enabled = apply_filters('sphere/adblock/enabled', $this->get_option('adblock_enabled')); if (!$is_enabled) { return; } add_action('wp_enqueue_scripts', [$this, 'register_assets']); add_action('wp_footer', [$this, 'add_modal_markup']); add_action('wp_footer', [$this, 'add_js']); } /** * Registe frontend assets. * * @return void */ public function register_assets() { if (!class_exists('Bunyad_Theme_SmartMag', false)) { wp_enqueue_style( 'ts_modal', $this->path_url . 'css/ts-modal.css', [], Plugin::VERSION ); } wp_enqueue_style( 'detect-modal', $this->path_url . 'css/modal.css', [], Plugin::VERSION ); } /** * Modal markup and configs. * * @return void */ public function add_modal_markup() { ?> <div id="detect-modal" class="ts-modal detect-modal" aria-hidden="true" data-delay="<?php echo esc_attr($this->get_option('adblock_delay')); ?>" <?php echo ($this->get_option('adblock_no_reshow') ? ' data-no-reshow ' : ''); ?> data-reshow-timeout="<?php echo esc_attr($this->get_option('adblock_reshow_timeout')); ?>"> <div class="ts-modal-overlay" tabindex="-1"> <div class="ts-modal-container" role="dialog" aria-modal="true" aria-labelledby="detect-modal-title"> <header class="ts-modal-header"> <div id="detect-modal-title" class="visuallyhidden"> <?php echo esc_html($this->get_option('adblock_title')); ?> </div> <?php if ($this->get_option('adblock_dismissable')): ?> <button class="close-btn" aria-label="<?php esc_attr_e('Close modal', 'bunyad'); ?>" data-micromodal-close></button> <?php endif; ?> </header> <div class="detect-modal-content"> <svg class="stop-icon" width="70px" height="70px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="Warning"><path id="Vector" d="M5.75 5.75L18.25 18.25M12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g></svg> <h5 class="heading"><?php echo esc_html($this->get_option('adblock_title')); ?></h5> <div class="message"> <?php echo wp_kses_post($this->get_option('adblock_message')); ?> </div> <?php if ($this->get_option('adblock_button')): ?> <div class="buttons"> <a href="<?php echo esc_attr($this->get_option('adblock_button_link')); ?>" class="ts-button" target="_blank"> <?php echo esc_html($this->get_option('adblock_button_label')); ?> </a> </div> <?php endif; ?> </div> </div> </div> </div> <?php } /** * Add JS code to the footer. * Inline JS so adblocks don't block the detection script URL. * * @return void */ public function add_js() { $inline_js = file_get_contents($this->path . 'js/detect.js'); if (!WP_DEBUG) { $inline_js = str_replace(["\r", "\n", "\t"], '', $inline_js); } echo '<script>' . $inline_js . '</script>'; } /** * Get an option from the theme customizer options if available. * * @param string $key * @return mixed|null */ public function get_option($key) { if (class_exists('\Bunyad') && \Bunyad::options()) { return \Bunyad::options()->get($key); } $defaults = [ 'adblock_enabled' => 0, 'adblock_title' => '', 'adblock_message' => '', 'adblock_delay' => 0, 'adblock_dismissable' => 1, 'adblock_no_reshow' => 0, 'adblock_reshow_timeout' => 24, 'adblock_button' => 0, 'adblock_button_label' => '', 'adblock_button_link' => '' ]; return isset($defaults[$key]) ? $defaults[$key] : null; } }PK 03YT'��� � 1 sphere-core/components/adblock-detect/options.php<?php namespace Sphere\Core\AdblockDetect; /** * Adblock Detection options. */ class Options { public function register_hooks() { // Add relevant options add_filter('bunyad_theme_options', [$this, 'add_options'], 10, 2); } /** * Callback: Add options to theme customizer. * * @param array $options * @param string $type * @return array */ public function add_options($options, $type = 'short') { // Note: To be made translatable + localized by the theme. $strings = apply_filters('sphere/adblock/options_strings', [ 'title' => 'Adblocker Detected', 'message' => 'Please disable your Ad Blocker to continue browsing this site.', ]); $fields = [ [ 'name' => 'adblock_enabled', 'label' => esc_html__('Enable Adblock Detection', 'sphere-core'), 'desc' => '', 'value' => 0, // 'style' => 'inline-sm', 'classes' => 'sep-bottom', 'type' => 'toggle', ], [ 'name' => 'adblock_title', 'label' => esc_html__('Message Title', 'sphere-core'), 'desc' => '', 'value' => $strings['title'], 'type' => 'text', ], [ 'name' => 'adblock_message', 'label' => esc_html__('Message', 'sphere-core'), 'desc' => 'Basic html allowed.', 'value' => $strings['message'], 'type' => 'textarea', ], [ 'name' => 'adblock_delay', 'label' => esc_html__('Modal Delay', 'sphere-core'), 'desc' => '', 'value' => 0, 'style' => 'inline-sm', 'type' => 'number', ], [ 'name' => 'adblock_dismissable', 'label' => esc_html__('Allow Dismissing Message', 'sphere-core'), 'desc' => '', 'value' => 0, 'type' => 'toggle', 'style' => 'inline-sm', ], [ 'name' => 'adblock_no_reshow', 'label' => esc_html__('Dont Show After Dismissed', 'sphere-core'), 'desc' => '', 'value' => 0, 'type' => 'toggle', 'style' => 'inline-sm', 'context' => [['key' => 'adblock_dismissable', 'value' => 1]] ], [ 'name' => 'adblock_reshow_timeout', 'label' => esc_html__('Dont Show For Hours', 'sphere-core'), 'desc' => '', 'value' => 24, 'type' => 'number', 'style' => 'inline-sm', 'context' => [['key' => 'adblock_no_reshow', 'value' => 1]] ], [ 'name' => 'adblock_button', 'label' => esc_html__('Show Button', 'sphere-core'), 'desc' => '', 'value' => 0, 'type' => 'toggle', 'style' => 'inline-sm', ], [ 'name' => 'adblock_button_label', 'label' => esc_html__('Button Label', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'text', 'style' => 'inline-sm', 'context' => [['key' => 'adblock_button', 'value' => 1]] ], [ 'name' => 'adblock_button_link', 'label' => esc_html__('Button Link', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'text', 'context' => [['key' => 'adblock_button', 'value' => 1]] ], ]; if ($type !== 'short') { array_push($fields, ...[ [ 'name' => 'css_adblock_bg_color', 'label' => esc_html__('Modal Background', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'classes' => 'sep-top', 'css' => [ '.detect-modal .ts-modal-container' => ['props' => ['background' => '%s']] ] ], [ 'name' => 'css_adblock_bg_color_sd', 'label' => esc_html__('Dark: Modal Background', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'css' => [ '.s-dark .detect-modal .ts-modal-container' => ['props' => ['background' => '%s']] ] ], [ 'name' => 'css_adblock_h_color', 'label' => esc_html__('Heading Color', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'css' => [ '.detect-modal .heading' => ['props' => ['color' => '%s']] ] ], [ 'name' => 'css_adblock_h_color_sd', 'label' => esc_html__('Dark: Heading Color', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'css' => [ '.s-dark .detect-modal .heading' => ['props' => ['color' => '%s']] ] ], [ 'name' => 'css_adblock_text_color', 'label' => esc_html__('Text Color', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'css' => [ '.detect-modal .message' => ['props' => ['color' => '%s']] ] ], [ 'name' => 'css_adblock_text_color_sd', 'label' => esc_html__('Dark: Text Color', 'sphere-core'), 'desc' => '', 'value' => '', 'type' => 'color', 'style' => 'inline-sm', 'css' => [ '.detect-modal .message' => ['props' => ['color' => '%s']] ] ], [ 'name' => 'css_adblock_hide_icon', 'label' => esc_html__('Hide Icon', 'sphere-core'), 'desc' => '', 'value' => 0, 'type' => 'toggle', 'style' => 'inline-sm', 'css' => [ '.detect-modal .stop-icon' => ['props' => ['display' => 'none']] ] ], ]); } $add_options = [ 'priority' => 40, 'sections' => [[ 'title' => esc_html__('Ad Blocker Detection', 'sphere-core'), 'id' => 'sphere-adblock-detect', 'fields' => $fields ]] ]; $options['sphere-adblock-detect'] = apply_filters('sphere/adblock/options', $add_options); return $options; } }PK 03Y�\VG 3 sphere-core/components/adblock-detect/css/modal.css/** * Detection Modal */ .detect-modal .ts-modal-container { width: 600px; padding: 50px 45px; text-align: center; } .detect-modal .heading { margin-top: 12px; margin-bottom: 18px; font-size: 28px; line-height: 1.3; font-weight: 700; } .detect-modal .message { font-size: 15px; margin-top: 4px; margin-bottom: 0; } .detect-modal .message p:last-child { margin-bottom: 0; } .detect-modal .stop-icon { color: rgb(211, 14, 14); } .detect-modal .buttons { margin-top: 22px; display: flex; justify-content: center; }PK 03Y�2n� � 6 sphere-core/components/adblock-detect/css/ts-modal.css/** * ThemeSphere Modal CSS */ .ts-modal { display: none; position: relative; z-index: 10001; } .ts-modal.is-open { display: block; } .ts-modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.6); display: flex; justify-content: center; align-items: center; outline: none; } .ts-modal[aria-hidden=false] .ts-modal-overlay { animation: fade-in-up-lg .3s ease-in-out; } .ts-modal[aria-hidden=true] .ts-modal-overlay { animation: fade-in .3s ease-in-out; animation-direction: reverse; } .ts-modal-container { position: relative; background-color: #fff; padding: 30px; max-width: 98vw; max-height: 98vh; border-radius: 4px; overflow-y: auto; } .ts-modal-header { display: flex; } .ts-modal .close-btn { position: absolute; top: 8px; right: 9px; padding: 10px; height: auto; line-height: 1; background: none; border: 0; box-shadow: none; color: #777; font-size: 1.1em; } .ts-modal .close-btn:hover { color: #000; } .ts-modal .close-btn:before { content: "\2715"; } @keyframes fade-in-up-lg { from { opacity: 0; transform: translate3d(0, 8px, 0); } to { opacity: 1; transform: none; } } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }PK 03Y�ʬD D . sphere-core/components/adblock-detect/js/ad.js"use strict"; var Bunyad_Adblock_Detect_Run = 1; var $tieE3 = true; PK 03Y�n�� � 2 sphere-core/components/adblock-detect/js/detect.js/** @copyright 2023 ThemeSphere. */ "use strict"; (function() { let theModal; let noReshow = 0; let didTest = false; const STORAGE_KEY = 'detect-message-shown'; function init() { document.readyState === 'complete' ? ready() : window.addEventListener('load', ready); } function ready() { theModal = document.querySelector('#detect-modal'); const delay = parseFloat(theModal.dataset.delay); (delay > 0 ? setTimeout(() => doTest(), delay*1000) : doTest() ); } function doTest() { const random = max => Math.floor(Math.random() * max); if (didTest) { return; } const testWrap = document.createElement('ins'); const classes = [ 'adsbygoogle', 'ad-slot', random(1000) ]; const testStyle = 'background: transparent; z-index: -1; height: 1px; width: 0; position: absolute;'; Object.assign(testWrap, { className: classes.sort(() => .5 - Math.random()).join(' '), style: testStyle, 'data-ad-slot': random(10^6) }); document.body.append(testWrap); const testWrap2 = document.createElement('div'); document.body.append(Object.assign( testWrap2, { className: 'ad-250', style: testStyle } )); requestAnimationFrame(() => { if (!testWrap.clientHeight || !testWrap2.clientHeight) { showModal(); } testWrap.remove(); testWrap2.remove(); didTest = true; }); } function toggleScroll(toggle) { switch (toggle) { case 'enable': Object.assign(document.body.style, { overflow: '' }); break; case 'disable': Object.assign(document.body.style, { overflow: 'hidden' }); break; default: } } function initModal() { noReshow = theModal.hasAttribute('data-no-reshow') ? 1 : 0; } function showModal() { initModal(); if (noReshow) { const value = localStorage.getItem(STORAGE_KEY); if (value && value > Date.now()) { return; } } theModal.classList.toggle('is-open'); theModal.setAttribute('aria-hidden', 'false'); toggleScroll('disable'); theModal.addEventListener('click', e => { if (e.target.hasAttribute('data-micromodal-close')) { closeModal(); e.preventDefault(); } }); } function closeModal() { theModal.classList.toggle('is-open'); theModal.setAttribute('aria-hidden', 'true'); toggleScroll('enable'); if (noReshow) { localStorage.setItem( STORAGE_KEY, Date.now() + (parseInt(theModal.dataset.reshowTimeout) * 3600 * 1000) ); } else { localStorage.removeItem(STORAGE_KEY); } } init(); })();PK 03Y�^��A A 7 sphere-core/components/adblock-detect/js/micro-modal.js/* Credit: https://github.com/Ghosh/micromodal */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).MicroModal=t()}(this,(function(){"use strict";function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function t(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var o=0,n=new Array(t);o<t;o++)n[o]=e[o];return n}var n,i,a,r,s,l=(n=["a[href]","area[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex^="-"])'],i=function(){function o(e){var n=e.targetModal,i=e.triggers,a=void 0===i?[]:i,r=e.onShow,s=void 0===r?function(){}:r,l=e.onClose,c=void 0===l?function(){}:l,d=e.openTrigger,u=void 0===d?"data-micromodal-trigger":d,f=e.closeTrigger,h=void 0===f?"data-micromodal-close":f,v=e.openClass,m=void 0===v?"is-open":v,g=e.disableScroll,b=void 0!==g&&g,y=e.disableFocus,p=void 0!==y&&y,w=e.awaitCloseAnimation,E=void 0!==w&&w,k=e.awaitOpenAnimation,M=void 0!==k&&k,C=e.debugMode,A=void 0!==C&&C;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,o),this.modal=document.getElementById(n),this.config={debugMode:A,disableScroll:b,openTrigger:u,closeTrigger:h,openClass:m,onShow:s,onClose:c,awaitCloseAnimation:E,awaitOpenAnimation:M,disableFocus:p},a.length>0&&this.registerTriggers.apply(this,t(a)),this.onClick=this.onClick.bind(this),this.onKeydown=this.onKeydown.bind(this)}var i,a,r;return i=o,(a=[{key:"registerTriggers",value:function(){for(var e=this,t=arguments.length,o=new Array(t),n=0;n<t;n++)o[n]=arguments[n];o.filter(Boolean).forEach((function(t){t.addEventListener("click",(function(t){return e.showModal(t)}))}))}},{key:"showModal",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if(this.activeElement=document.activeElement,this.modal.setAttribute("aria-hidden","false"),this.modal.classList.add(this.config.openClass),this.scrollBehaviour("disable"),this.addEventListeners(),this.config.awaitOpenAnimation){var o=function t(){e.modal.removeEventListener("animationend",t,!1),e.setFocusToFirstNode()};this.modal.addEventListener("animationend",o,!1)}else this.setFocusToFirstNode();this.config.onShow(this.modal,this.activeElement,t)}},{key:"closeModal",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=this.modal;if(this.modal.setAttribute("aria-hidden","true"),this.removeEventListeners(),this.scrollBehaviour("enable"),this.activeElement&&this.activeElement.focus&&this.activeElement.focus(),this.config.onClose(this.modal,this.activeElement,e),this.config.awaitCloseAnimation){var o=this.config.openClass;this.modal.addEventListener("animationend",(function e(){t.classList.remove(o),t.removeEventListener("animationend",e,!1)}),!1)}else t.classList.remove(this.config.openClass)}},{key:"closeModalById",value:function(e){this.modal=document.getElementById(e),this.modal&&this.closeModal()}},{key:"scrollBehaviour",value:function(e){if(this.config.disableScroll){var t=document.querySelector("body");switch(e){case"enable":Object.assign(t.style,{overflow:""});break;case"disable":Object.assign(t.style,{overflow:"hidden"})}}}},{key:"addEventListeners",value:function(){this.modal.addEventListener("touchstart",this.onClick),this.modal.addEventListener("click",this.onClick),document.addEventListener("keydown",this.onKeydown)}},{key:"removeEventListeners",value:function(){this.modal.removeEventListener("touchstart",this.onClick),this.modal.removeEventListener("click",this.onClick),document.removeEventListener("keydown",this.onKeydown)}},{key:"onClick",value:function(e){e.target.hasAttribute(this.config.closeTrigger)&&this.closeModal(e)}},{key:"onKeydown",value:function(e){27===e.keyCode&&this.closeModal(e),9===e.keyCode&&this.retainFocus(e)}},{key:"getFocusableNodes",value:function(){var e=this.modal.querySelectorAll(n);return Array.apply(void 0,t(e))}},{key:"setFocusToFirstNode",value:function(){var e=this;if(!this.config.disableFocus){var t=this.getFocusableNodes();if(0!==t.length){var o=t.filter((function(t){return!t.hasAttribute(e.config.closeTrigger)}));o.length>0&&o[0].focus(),0===o.length&&t[0].focus()}}}},{key:"retainFocus",value:function(e){var t=this.getFocusableNodes();if(0!==t.length)if(t=t.filter((function(e){return null!==e.offsetParent})),this.modal.contains(document.activeElement)){var o=t.indexOf(document.activeElement);e.shiftKey&&0===o&&(t[t.length-1].focus(),e.preventDefault()),!e.shiftKey&&t.length>0&&o===t.length-1&&(t[0].focus(),e.preventDefault())}else t[0].focus()}}])&&e(i.prototype,a),r&&e(i,r),o}(),a=null,r=function(e){if(!document.getElementById(e))return console.warn("MicroModal: ❗Seems like you have missed %c'".concat(e,"'"),"background-color: #f8f9fa;color: #50596c;font-weight: bold;","ID somewhere in your code. Refer example below to resolve it."),console.warn("%cExample:","background-color: #f8f9fa;color: #50596c;font-weight: bold;",'<div class="modal" id="'.concat(e,'"></div>')),!1},s=function(e,t){if(function(e){e.length<=0&&(console.warn("MicroModal: ❗Please specify at least one %c'micromodal-trigger'","background-color: #f8f9fa;color: #50596c;font-weight: bold;","data attribute."),console.warn("%cExample:","background-color: #f8f9fa;color: #50596c;font-weight: bold;",'<a href="#" data-micromodal-trigger="my-modal"></a>'))}(e),!t)return!0;for(var o in t)r(o);return!0},{init:function(e){var o=Object.assign({},{openTrigger:"data-micromodal-trigger"},e),n=t(document.querySelectorAll("[".concat(o.openTrigger,"]"))),r=function(e,t){var o=[];return e.forEach((function(e){var n=e.attributes[t].value;void 0===o[n]&&(o[n]=[]),o[n].push(e)})),o}(n,o.openTrigger);if(!0!==o.debugMode||!1!==s(n,r))for(var l in r){var c=r[l];o.targetModal=l,o.triggers=t(c),a=new i(o)}},show:function(e,t){var o=t||{};o.targetModal=e,!0===o.debugMode&&!1===r(e)||(a&&a.removeEventListeners(),(a=new i(o)).showModal())},close:function(e){e?a.closeModalById(e):a.closeModal()}});return window.MicroModal=l,l}));PK 03Y��( � � 0 sphere-core/components/auto-load-post/module.php<?php namespace Sphere\Core\AutoLoadPost; use Sphere\Core\Plugin; use Sphere\Debloat\Plugin as DebloatPlugin; /** * Auto load next post. */ class Module { protected $path_url; public function __construct() { $this->path_url = Plugin::instance()->path_url . 'components/auto-load-post/'; add_action('wp', [$this, 'setup']); $options = new Options; $options->register_hooks(); } public function setup() { // Only for ThemeSphere themes. if (!class_exists('Bunyad', false)) { return; } // Auto-load next post is disabled. The filter can return true to force enable. $is_enabled = apply_filters('sphere/alp/enabled', $this->get_option('alp_enabled')); if (!$is_enabled) { return; } $supported_types = apply_filters('sphere/alp/post_types', ['post']); $is_supported = is_single() && in_array(get_post_type(), $supported_types); if (!$is_supported) { return; } // Only needed for iframe. // add_action('wp_head', [$this, 'add_head_js']); add_action('wp_enqueue_scripts', [$this, 'register_assets']); add_action('wp_footer', [$this, 'add_next_post_ref']); /** * Debloat plugin compatibility for ALP. * * If remove CSS is enabled, delayed load of all CSS must also be enabled as * dynamically loaded posts may have a lot of classes missing in original CSS. */ add_action('debloat/process_markup', function() { $options = DebloatPlugin::options(); if ( $options->remove_css && (!$options->delay_css_load || !in_array('posts', $options->delay_css_on)) ) { $options->delay_css_load = true; $options->delay_css_on = ['posts']; } }); } /** * Registe frontend assets. * * @return void */ public function register_assets() { // Only enqueue on single. if (is_single()) { wp_enqueue_script( 'spc-auto-load-post', $this->path_url . 'js/auto-load-post.js', [], Plugin::VERSION, true ); } } public function add_head_js() { $css_link = $this->path_url . 'css/iframe.css'; ?> <script data-cfasync="false"> <?php // var instead of let for window.BunyadIsIframe / global context. ?> var BunyadIsIframe; (() => { if (location.hash && location.hash.indexOf('auto-load-post') !== -1 && self !== top) { BunyadIsIframe = true; document.documentElement.style.opacity = 0; <?php // For race-conditions where header maybe rendered first and give a flash, before iframe.css renders. ?> document.head.append( Object.assign(document.createElement('link'), {rel: 'stylesheet', href: '<?php echo esc_url($css_link); ?>'}), Object.assign(document.createElement('base'), {target: '_top'}) ); } })(); </script> <?php } /** * Get an option from the theme customizer options if available. * * @param string $key * @return mixed|null */ public function get_option($key) { if (class_exists('\Bunyad') && \Bunyad::options()) { return \Bunyad::options()->get($key); } $defaults = [ 'alp_enabled' => 0, 'alp_posts' => 5, 'alp_load_type' => 'previous', 'alp_same_term' => false, ]; return isset($defaults[$key]) ? $defaults[$key] : null; } /** * Add reference data for the next post. * * @return void */ public function add_next_post_ref() { $posts = $this->get_adjacent_posts( $this->get_option('alp_posts'), $this->get_option('alp_load_type'), $this->get_option('alp_same_term') ); if (!$posts) { return; } $final_posts = []; $have_gallery = false; foreach ($posts as $post) { $final_posts[] = [ 'id' => $post->ID, 'title' => $post->post_title, 'url' => get_permalink($post) ]; if (get_post_format($post) === 'gallery') { $have_gallery = true; } } // Add slickslider if needed and available. if ($have_gallery) { $script = \Bunyad::options()->get_config('theme_name') . '-slick'; if (wp_script_is($script, 'registered')) { wp_enqueue_script($script); } } do_action('sphere/alp/next_post_ref', $final_posts, $posts); printf( '<script data-cfasync="false">SphereCore_AutoPosts = %s;</script>', json_encode($final_posts) ); } /** * Get adjacent posts to the current post. * * @param integer $count Number of posts. * @param string $type Selection type: 'previous', 'next' and 'random'. * @param boolean $same_term * * @return array */ public function get_adjacent_posts($count, $type = 'previous', $same_term = false) { wp_reset_query(); $current_post = get_queried_object(); if (!$current_post || !$current_post->ID) { return; } $query_args = [ 'post_type' => $current_post->post_type, 'posts_per_page' => $count, 'no_found_rows' => true, 'supress_filters' => true, 'ignore_sticky_posts' => true ]; /** * Additional query params based on type of posts needed. */ if ($type !== 'random') { $adjacent = $type === 'previous' ? 'before' : 'after'; $query_args += [ 'date_query' => [ [ $adjacent => $current_post->post_date, 'inclusive' => false ] ], // For previous posts, order by date desc. asc for next. 'order' => $adjacent === 'before' ? 'DESC' : 'ASC' ]; } else { $query_args += [ 'orderby' => 'rand', 'post__not_in' => [$current_post->ID], ]; } /** * Posts from the same term. */ if ($same_term) { $terms = wp_get_post_terms($current_post->ID, 'category', ['fields' => 'ids']); if ($terms) { $query_args['tax_query'] = [ [ 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => $terms ] ]; } } $posts = get_posts( apply_filters('sphere/alp/posts_query_args', $query_args) ); return $posts; } }PK 03YÝ�b� � 1 sphere-core/components/auto-load-post/options.php<?php namespace Sphere\Core\AutoLoadPost; /** * Autoload post options. */ class Options { public function register_hooks() { // Add relevant options add_filter('bunyad_theme_options', [$this, 'add_options']); } /** * Callback: Add options to theme customizer. * * @param array $options * @return array */ public function add_options($options) { $add_options = [ 'priority' => 40, 'sections' => [[ 'title' => esc_html__('Auto-load Next Post', 'sphere-core'), 'id' => 'sphere-auto-load-post', 'fields' => [ [ 'name' => 'alp_enabled', 'label' => esc_html__('Enable Auto-load Posts', 'sphere-core'), 'desc' => esc_html__('Activate the auto-load post on scroll for single post pages.', 'sphere-core'), 'value' => 0, 'classes' => 'sep-bottom', 'type' => 'toggle', ], [ 'name' => 'alp_posts', 'label' => esc_html__('Number of Posts', 'sphere-core'), 'desc' => esc_html__('Max number of posts to auto-load on scroll.', 'sphere-core'), 'value' => 6, 'type' => 'number', 'input_attrs' => ['min' => 1, 'max' => 25], ], [ 'name' => 'alp_load_type', 'label' => esc_html__('Load Type', 'sphere-core'), 'desc' => '', 'value' => 'previous', 'type' => 'radio', 'options' => [ 'previous' => esc_html__('Previous By Date', 'sphere-core'), 'next' => esc_html__('Next By Date', 'sphere-core'), 'random' => esc_html_x('Random', 'sphere-core'), ] ], [ 'name' => 'alp_same_term', 'label' => esc_html__('From Same Category', 'sphere-core'), 'desc' => esc_html__('Select posts from same category(s) only as the original post.', 'sphere-core'), 'value' => 0, 'type' => 'toggle', ], ] ]] ]; $options['sphere-auto-load-post'] = apply_filters('sphere/alp/options', $add_options); return $options; } }PK 03Y���PV V : sphere-core/components/auto-load-post/js/auto-load-post.js/** * Auto load post module front-end JS. * * @copyright 2022 ThemeSphere. */ "use strict"; (function() { // Percentage reading to trigger the next. const TRIGGER_NEXT_FACTOR = 0.65; /** @type {!Array<Object>} */ let postsToLoad = []; /** @type {HTMLElement} */ let mainPostElement; /** @type {IntersectionObserver} */ let inViewObserver; /** * States and current refs. */ let isLoading = false; // All the loaded posts elements. let postElements = []; // Latest loaded post element. let postElement; /** * Set up. */ function init() { // Set posts on ready. callOnReady(setup); } /** * Setup events. Should be called after DOMContentLoaded. */ function setup() { if (typeof SphereCore_AutoPosts === 'undefined' || !window.fetch) { return; } postsToLoad = SphereCore_AutoPosts; postElement = document.querySelector('.main'); mainPostElement = postElement; postElements.push(mainPostElement); if (!mainPostElement) { return; } Object.assign(mainPostElement.dataset, { title: document.title, url: window.location.href }); document.addEventListener('scroll', () => { // isLoading is false once iframe is inserted but iframe's dataset.loading // is empty only once onload event has fired (on full load). if (isLoading || postElement.dataset.loading) { return; } let triggerLoad = postElement.offsetTop + (postElement.offsetHeight * TRIGGER_NEXT_FACTOR); if (window.scrollY > triggerLoad) { isLoading = true; requestAnimationFrame(loadPost); } }); inViewObserver = new IntersectionObserver(observePostsInView, { root: null, rootMargin: '0px 0px -50%', threshold: 0 }); } /** * Observe posts entering the viewport and update URL etc. * * @param {Array} entries */ function observePostsInView(entries) { let thePost; // Current visible post, that will be inactivated, if any. let currentPost; for (let element of entries) { if (element.intersectionRatio <= 0) { currentPost = element.target; continue; } thePost = element.target; break; } // Revert to previous post if available. if (!thePost) { const index = postElements.findIndex(post => post === currentPost); const prevPost = postElements[index - 1]; if (prevPost && prevPost.getBoundingClientRect().bottom >= 0) { thePost = prevPost; } } if (thePost && thePost.dataset.url) { window.history.pushState(null, thePost.dataset.title, thePost.dataset.url); document.title = thePost.dataset.title; sendPageView(); } } /** * Add a loader before the current post element/iframe. */ function addLoader(target) { target = target || postElement; const loader = document.createElement('div'); Object.assign(loader, { className: 'spc-alp-loader ts-spinner' }); target.after(loader); } /** * Load the next post. */ function loadPost() { const post = postsToLoad.shift(); if (!post) { return; } // Loading for the first time, add class to main element. if (mainPostElement === postElement) { mainPostElement.classList.add('spc-alp-main'); } const addPostContainer = (html) => { if (!html) { return; } const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); // Get the post content. const content = doc.querySelector('.main-wrap > .main'); if (!content) { return; } const container = document.createElement('div'); postElement.after(container); Object.assign(container.dataset, { url: post.url, title: post.title, id: post.id // loading: '1' }); Object.assign(container, { id: `spc-alp-${post.id}`, className: 'spc-auto-load-post', innerHTML: content.outerHTML }); postElement = container; postElements.push(container); return container; }; addLoader(); fetch(post.url) .then(resp => resp.text()) .then(html => { const container = addPostContainer(html); // Remove loader. document.querySelectorAll('.spc-alp-loader').forEach(e => e.remove()); if (!container) { return; } executeScripts(container); // Reload twitter embeds. if (window.twttr && twttr.widgets && twttr.widgets.load) { twttr.widgets.load(); } requestAnimationFrame(() => { isLoading = false; // Ensure visibility. ensureVisible(container); // Add to observers after visibility. inViewObserver.observe(container); document.dispatchEvent(new Event('spc-alp-loaded')); // Do the theme reinit functions. const theme = Bunyad.theme || Bunyad_Theme; if (theme.reInit) { theme.reInit(container); } }); }); } /** * Execute script tags for content added via innerHTML. * * @param {HTMLElement} element */ function executeScripts(element) { let debloatDelay; element.querySelectorAll('script').forEach(item => { const script = document.createElement('script'); script.text = item.textContent; // Set attributes. const attrs = item.attributes; for (const attr of attrs) { script.setAttribute(attr.name, attr.value || true); } // Lazy / delay loads. if (script.type && ['rocketlazyloadscript', 'text/debloat-script', '/javascript'].includes(script.type)) { script.type = 'text/javascript'; } if (script.dataset.debloatDelay) { debloatDelay = true; } if (!script.src && script.dataset.src) { script.src = script.dataset.src; } document.body.append(script); }); if (debloatDelay) { document.dispatchEvent(new Event('debloat-load-js')); } } /** * Ensure the post element is visible, if at end of the page. * * @param {HTMLElement} postElement */ function ensureVisible(postElement) { // Scroll to post if at footer / almost end of page. const doc = document.documentElement; if (doc.scrollHeight - doc.scrollTop <= doc.clientHeight + 75) { if (Bunyad.theme) { Bunyad.theme.stickyBarPause = true; setTimeout(() => Bunyad.theme.stickyBarPause = false, 5); } postElement.scrollIntoView(); } } /** * Send a pageview to analytics - should be called when post is visible. */ function sendPageView() { if (!postElement || postElement.dataset.viewTracked) { return; } // New Google Tag if (window.gtag) { window.gtag('event', 'page_view', { page_title: postElement.dataset.title, page_location: postElement.dataset.url }); } // Analytics.js if (window.ga) { window.ga('send', 'pageview', postElement.dataset.url); } document.dispatchEvent( new CustomEvent('spc-alp-pageview', { detail: { id: postElement.dataset.id, ele: postElement } }) ); postElement.dataset.viewTracked = 1; } function callOnReady(cb) { document.readyState !== 'loading' ? cb() : document.addEventListener('DOMContentLoaded', cb); } init(); })();PK 03Y��l�O O 0 sphere-core/components/breadcrumbs/generator.php<?php namespace Sphere\Core\Breadcrumbs; /** * Generate the breadcrumbs trail. * * Originally based on WooCommerce breadcrumbs. */ class Generator { protected $crumbs = []; protected $primary_cat_callback; protected $labels = []; public function __construct($args = []) { foreach ($args as $option => $value) { if (property_exists($this, $option)) { $this->{$option} = $value; } } } /** * Generate breadcrumb trail. * * @return array of breadcrumbs */ public function generate() { // Doesn't make sense to have it for home. if (is_home() || is_front_page()) { return; } // Add homepage trail always. $this->add_crumb( $this->labels['home'], home_url('/') ); $conditionals = array( 'is_404', 'is_attachment', 'is_single', 'is_page', 'is_post_type_archive', 'is_category', 'is_tag', 'is_author', 'is_date', 'is_tax', ); foreach ($conditionals as $conditional) { if (call_user_func($conditional)) { call_user_func([ $this, 'add_crumbs_' . substr($conditional, 3) ]); break; } } $this->search_trail(); $this->paged_trail(); return $this->get_breadcrumb(); } /** * Add a crumb so we don't get lost. * * @param string $name Text. * @param string $link Link. * @param array $extras */ public function add_crumb($name, $link = '', $extras = []) { $this->crumbs[] = array_replace([ 'text' => wp_strip_all_tags($name), 'url' => $link, ], $extras); } /** * Reset crumbs. */ public function reset() { $this->crumbs = array(); } /** * Get the breadcrumb. * * @return array */ public function get_breadcrumb() { return apply_filters('sphere_breadcrumbs_get', $this->crumbs, $this); } /** * 404 trail. */ protected function add_crumbs_404() { $this->add_crumb($this->labels['404']); } /** * Attachment trail. */ protected function add_crumbs_attachment() { global $post; $this->add_crumbs_single($post->post_parent, get_permalink($post->post_parent)); $this->add_crumb(get_the_title(), get_permalink()); } /** * Single post trail. * * @param int $post_id Post ID. * @param string $permalink Post permalink. */ protected function add_crumbs_single($post_id = null, $permalink = '') { $post = get_post($post_id); if (!$permalink) { $permalink = get_permalink($post); } if ('post' !== get_post_type($post)) { $post_type = get_post_type_object(get_post_type($post)); if (!empty($post_type->has_archive)) { $this->add_crumb( $post_type->labels->singular_name, get_post_type_archive_link(get_post_type($post)) ); } } else { $cat = $this->get_primary_cat($post_id); if ($cat) { $this->term_ancestors($cat->term_id, 'category'); $this->add_crumb($cat->name, get_term_link($cat)); } } $this->add_crumb(get_the_title($post), $permalink); } /** * Page trail. */ protected function add_crumbs_page() { $post = get_post(); if ($post->post_parent) { $parent_crumbs = array(); $parent_id = $post->post_parent; while ($parent_id) { $page = get_post($parent_id); $parent_id = $page->post_parent; $parent_crumbs[] = array( get_the_title($page->ID), get_permalink($page->ID) ); } $parent_crumbs = array_reverse($parent_crumbs); foreach ($parent_crumbs as $crumb) { $this->add_crumb($crumb[0], $crumb[1]); } } $this->add_crumb(get_the_title(), get_permalink()); } /** * Post type archive trail. */ protected function add_crumbs_post_type_archive($type = null) { $type = $type ? $type : get_post_type(); $post_type = get_post_type_object($type); if ($post_type) { $this->add_crumb($post_type->labels->name, get_post_type_archive_link($type)); } } /** * Category trail. */ protected function add_crumbs_category() { $this_category = get_category($this->get_current_object()); if (0 !== intval($this_category->parent)) { $this->term_ancestors($this_category->term_id, 'category'); } $this->add_crumb( sprintf($this->labels['category'], single_term_title('', false)), get_category_link($this_category->term_id) ); } /** * Tag trail. */ protected function add_crumbs_tag() { $queried_object = $this->get_current_object(); $this->add_crumb( sprintf( $this->labels['tag'], single_tag_title('', false) ), get_tag_link($queried_object->term_id) ); } /** * Add crumbs for date based archives. */ protected function add_crumbs_date() { if (is_year() || is_month() || is_day()) { $this->add_crumb( get_the_time('Y'), get_year_link(get_the_time('Y')) ); } if (is_month() || is_day()) { $this->add_crumb( get_the_time('F'), get_month_link(get_the_time('Y'), get_the_time('m')) ); } if (is_day()) { $this->add_crumb(get_the_time('d')); } } /** * Add crumbs for taxonomies */ protected function add_crumbs_tax() { $this_term = $this->get_current_object(); $taxonomy = get_taxonomy($this_term->taxonomy); // Add a parent Custom Post Type if it exists. $post_types = array_diff($taxonomy->object_type, ['post', 'page', 'attachment', 'nav_menu_item', 'revision']); if (count($post_types)) { $this->add_crumbs_post_type_archive($post_types[0]); } // $this->add_crumb($taxonomy->labels->name); if (0 !== intval($this_term->parent)) { $this->term_ancestors($this_term->term_id, $this_term->taxonomy); } $this->add_crumb( sprintf($this->labels['tax'], single_term_title('', false)), get_term_link($this_term->term_id, $this_term->taxonomy) ); } /** * Add a breadcrumb for author archives. */ protected function add_crumbs_author() { global $author; $userdata = get_userdata($author); $this->add_crumb(sprintf( $this->labels['author'], $userdata->display_name )); } /** * Add crumbs for a term. * * @param int $term_id Term ID. * @param string $taxonomy Taxonomy. */ protected function term_ancestors($term_id, $taxonomy) { $ancestors = get_ancestors($term_id, $taxonomy); $ancestors = array_reverse($ancestors); foreach ($ancestors as $ancestor) { $ancestor = get_term($ancestor, $taxonomy); if (!is_wp_error($ancestor) && $ancestor) { $this->add_crumb($ancestor->name, get_term_link($ancestor)); } } } /** * Add a breadcrumb for search results. */ protected function search_trail() { if (is_search()) { $this->add_crumb( sprintf( $this->labels['search'], get_search_query() ), remove_query_arg('paged') ); } } /** * Add a breadcrumb for pagination. */ protected function paged_trail() { if (get_query_var('paged')) { $last = array_pop($this->crumbs); $last['text'] .= sprintf( $this->labels['paged'], get_query_var('paged') ); array_push($this->crumbs, $last); } } // -------------------- /** * Get primary category for the post. * * @param int $post_id * @return void */ protected function get_primary_cat($post_id = null) { if (isset($this->primary_cat_callback)) { return call_user_func($this->primary_cat_callback, $post_id); } return current(get_the_category($post_id)); } /** * Return current global queried object (taxonomy, post, page etc.) * * @return object */ protected function get_current_object() { return $GLOBALS['wp_query']->get_queried_object(); } }PK 03Yv�O�� � - sphere-core/components/breadcrumbs/module.php<?php namespace Sphere\Core\Breadcrumbs; /** * Breadcrumbs trail. */ class Module { protected $labels = []; /** * Initialize can be with options specified. * * @param array $args */ public function __construct() { $this->labels = [ 'home' => esc_html_x('Home', 'breadcrumbs', 'sphere-core'), // text for the 'Home' link 'category' => esc_html_x('Category: "%s"', 'breadcrumbs', 'sphere-core'), // text for a category page 'tax' => esc_html_x('Archive for "%s"', 'breadcrumbs', 'sphere-core'), // text for a taxonomy page 'search' => esc_html_x('Search Results for "%s"', 'breadcrumbs', 'sphere-core'), // text for a search results page 'tag' => esc_html_x('Posts Tagged "%s"', 'breadcrumbs', 'sphere-core'), // text for a tag page '404' => esc_html_x('Error 404', 'breadcrumbs', 'sphere-core'), // text for the 404 page 'author' => esc_html_x('Author: %s', 'breadcrumbs', 'sphere-core'), // text for an author page 'paged' => esc_html_x(' (Page %d)', 'breadcrumbs', 'sphere-core'), // appended to paged. ]; } /** * Output the breadcrumbs. * * @param array $options * @return void */ public function render($options = array()) { $defaults = array( 'before' => '<nav class="breadcrumbs">', 'after' => '</nav>', 'delimiter' => '<span class="delim">»</span>', 'current_before' => '<span class="current">', 'current_after' => '</span>', 'home_link' => home_url() . '/', 'show_current' => true, // Whether to show current item on single page. 'show_current_single' => true, // Callback for getting primary category. 'primary_cat_callback' => null, 'link_before' => '<span>', 'link_after' => '</span>', 'link_in_before' => '<span>', 'link_in_after' => '</span>', 'disable_at' => [] ); extract( apply_filters('sphere_breadcrumbs_defaults', $defaults) ); require_once SPHERE_COMPONENTS . '/breadcrumbs/schema.php'; require_once SPHERE_COMPONENTS . '/breadcrumbs/generator.php'; // Form whole link option. $link = '<a href="%1$s">' . $link_in_before . '%2$s' . $link_in_after . '</a>'; $link = $link_before . $link . $link_after; if (isset($options['labels'])) { $this->labels = array_replace($this->labels, (array) $options['labels']); } // This is final before render. Options already applied. $this->labels = apply_filters('sphere_breadcrumbs_labels', $this->labels); $options = array_replace($defaults, $options); // Check if breadcrumbs are disabled at this location. foreach ($options['disable_at'] as $check) { $checker = 'is_' . $check; if (call_user_func($checker)) { return; } } /** * Use bbPress's breadcrumbs when available */ if (function_exists('bbp_breadcrumb') && is_bbpress()) { $bbp_crumbs = bbp_get_breadcrumb(array( 'home_text' => $this->labels['home'], 'sep' => $options['delimiter'], 'sep_before' => '', 'sep_after' => '', 'pad_sep' => 0, 'before' => $options['before'], 'after' => $options['after'], 'current_before' => $options['current_before'], 'current_after' => $options['current_after'], )); if ($bbp_crumbs) { echo $bbp_crumbs; return; } } /** * Use WooCommerce's breadcrumbs when available */ if (function_exists('woocommerce_breadcrumb') && (is_woocommerce() || is_cart() || is_shop())) { add_filter('woocommerce_get_breadcrumb', [$this, 'add_shop_woocommerce']); woocommerce_breadcrumb(array( 'delimiter' => $options['delimiter'], 'before' => '', 'after' => '', 'wrap_before' => $options['before'], 'wrap_after' => $options['after'], 'home' => $this->labels['home'], )); return; } // Show on homepage? if (is_home() || is_front_page()) { return; } $breadcrumbs = new Generator([ 'labels' => $this->labels, 'primary_cat_callback' => $options['primary_cat_callback'] ]); $crumbs = $breadcrumbs->generate(); // Start the output. $items = count($crumbs); $count = 0; $output = []; $show_current = $options['show_current']; if (is_single() && !$options['show_current_single']) { $show_current = false; } foreach ($crumbs as $crumb) { $count++; // Last item. $is_last = $count === $items; if ($is_last) { if ($show_current) { $output[] = $options['current_before'] . esc_html($crumb['text']) . $options['current_after']; } break; } $output[] = sprintf($link, esc_url($crumb['url']), esc_html($crumb['text'])); } // Safe output generated above. echo $options['before'] . join($options['delimiter'], $output) . $options['after']; // Setup JSON+LD to be output. add_action('wp_footer', function() use ($crumbs) { $schema = new Schema($crumbs); $schema->render(); }); } /** * Callback: Add WooCommerce shop link. */ public function add_shop_woocommerce($crumbs) { $permalinks = wc_get_permalink_structure(); $shop_page_id = wc_get_page_id('shop'); $shop_page = get_post( $shop_page_id ); // If currently at shop, or home is same as shop page, do nothing. if (is_shop() || !$shop_page || intval(get_option('page_on_front')) == $shop_page_id) { return $crumbs; } // Opposite test. If WC didn't append the shop page to the crumbs. if ( !isset($permalinks['product_base']) || !strstr($permalinks['product_base'], '/' . $shop_page->post_name) ) { $crumb = [ wp_strip_all_tags(get_the_title($shop_page)), get_permalink($shop_page) ]; $first = array_shift($crumbs); array_unshift($crumbs, $first, $crumb); } return $crumbs; } }PK 03Y�zB�� � - sphere-core/components/breadcrumbs/schema.php<?php namespace Sphere\Core\Breadcrumbs; /** * Generate JSON+LD schema for breadcrumbs. */ class Schema { /** * Breadcrumbs to use * * @var array */ public $crumbs = []; public function __construct($crumbs) { $this->crumbs = $crumbs; } /** * Output breadcrumbs schema data. * * @return void */ public function render() { foreach ($this->crumbs as $index => $item) { // Both text and URL are needed for schema. if (empty($item['text']) || empty($item['url'])) { continue; } $items[] = [ '@type' => 'ListItem', 'position' => ($index + 1), // Consistent with how Yoast does it. 'item' => [ '@type' => 'WebPage', '@id' => $item['url'], 'name' => $item['text'], ] // This can also be used instead of item above, for brevity. Google's example // uses this way, but it differs from the schema.org definition. // 'name' => $item['text'], // 'item' => $item['url'], ]; } $schema = [ '@context' => 'https://schema.org', '@type' => 'BreadcrumbList', 'itemListElement' => $items, ]; echo '<script type="application/ld+json">' . json_encode($schema) . "</script>\n"; } }PK 03YV�B�� � 8 sphere-core/components/elementor/dynamic-tags/module.php<?php namespace Sphere\Core\Elementor\DynamicTags; use Elementor\Plugin; /** * Our custom dynamic tags for Elementor. */ class Module { public $path; public $path_url; /** * Types of custom layouts. * * @var array */ public $types = []; protected $groups_registered = false; protected static $instance; public function __construct() { // Register CPT whether elementor exists or not, mainly for import. add_action('elementor/dynamic_tags/register', [$this, 'register_tags']); // Elementor plugin missing. if (!did_action('elementor/loaded')) { return; } $this->path = \Sphere\Core\Plugin::instance()->path . 'components/elementor/layouts/'; $this->path_url = \Sphere\Core\Plugin::instance()->path_url . 'components/elementor/layouts/'; } public function register_tags($dynamic_tags) { $this->register_groups(); $tags = [ 'ArchiveTitle', 'Copyright', ]; // These are very similar to Elementor Pro, so skip in pro. if (!defined('ELEMENTOR_PRO_VERSION')) { array_push($tags, ...[ 'ArchiveDescription', 'AuthorName', 'SiteUrl', ]); } foreach ($tags as $tag_class) { $class = __NAMESPACE__ . '\Tags\\' . $tag_class; $dynamic_tags->register(new $class); } } public function get_groups() { if (defined('ELEMENTOR_PRO_VERSION')) { return []; } return [ 'site' => [ 'title' => 'Site', ], 'archive' => [ 'title' => 'Archive', ], 'author' => [ 'title' => 'Author', ] ]; } public function register_groups() { if ($this->groups_registered) { return; } foreach ($this->get_groups() as $group => $settings) { Plugin::instance()->dynamic_tags->register_group($group, $settings); } } /** * Get singleton object * * @return self */ public static function instance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } }PK 03Y%Qa> > J sphere-core/components/elementor/dynamic-tags/tags/archive-description.php<?php namespace Sphere\Core\Elementor\DynamicTags\Tags; use Elementor\Core\DynamicTags\Tag; use Elementor\Modules\DynamicTags\Module as TagsModule; class ArchiveDescription extends Tag { public function get_name() { return 'archive-description'; } public function get_title() { return esc_html__('Archive Description', 'sphere-core'); } public function get_group() { return 'archive'; } public function get_categories() { return [TagsModule::TEXT_CATEGORY]; } public function render() { echo wp_kses_post(get_the_archive_description()); } }PK 03Y�Yt t D sphere-core/components/elementor/dynamic-tags/tags/archive-title.php<?php namespace Sphere\Core\Elementor\DynamicTags\Tags; use Elementor\Controls_Manager; use Elementor\Core\DynamicTags\Tag; use Elementor\Modules\DynamicTags\Module as TagsModule; class ArchiveTitle extends Tag { public function get_name() { return 'archive-title'; } public function get_title() { return esc_html__('Archive Title', 'sphere-core'); } public function get_group() { return 'archive'; } public function get_categories() { return [TagsModule::TEXT_CATEGORY]; } public function render() { $include_context = 'yes' === $this->get_settings('include_context'); if ($include_context) { $title = \Bunyad::archives() ? \Bunyad::archives()->get_heading() : get_the_archive_title(); } else { add_filter('get_the_archive_title_prefix', '__return_empty_string'); $title = get_the_archive_title(); remove_filter('get_the_archive_title_prefix', '__return_empty_string'); } // Fix for archive preview sample titles. if ($title === 'Sample Title') { if ($include_context && strpos($title, ':') === false) { $title = 'Browsing: <span>' . $title . '</span>'; } } echo wp_kses_post($title); } protected function register_controls() { $this->add_control( 'include_context', [ 'label' => esc_html__('Include Context', 'sphere-core'), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', ] ); } }PK 03Y B sphere-core/components/elementor/dynamic-tags/tags/author-meta.phpPK 03YRi0� B sphere-core/components/elementor/dynamic-tags/tags/author-name.php<?php namespace Sphere\Core\Elementor\DynamicTags\Tags; use Elementor\Core\DynamicTags\Tag; use Elementor\Modules\DynamicTags\Module as TagsModule; class AuthorName extends Tag { public function get_name() { return 'author-name'; } public function get_title() { return esc_html__('Author Name', 'sphere-core'); } public function get_group() { return 'author'; } public function get_categories() { return [TagsModule::TEXT_CATEGORY]; } public function render() { echo wp_kses_post(get_the_author()); } }PK 03Y���� @ sphere-core/components/elementor/dynamic-tags/tags/copyright.php<?php namespace Sphere\Core\Elementor\DynamicTags\Tags; use Elementor\Core\DynamicTags\Tag; use Elementor\Modules\DynamicTags\Module as TagsModule; class Copyright extends Tag { public function get_name() { return 'ts-copyright'; } public function get_title() { return esc_html__('Footer Copyright', 'sphere-core'); } public function get_group() { return 'site'; } public function get_categories() { return [TagsModule::TEXT_CATEGORY]; } public function render() { \Bunyad::theme()->the_copyright(); } }PK 03Y�p ? sphere-core/components/elementor/dynamic-tags/tags/site-url.php<?php namespace Sphere\Core\Elementor\DynamicTags\Tags; use Elementor\Core\DynamicTags\Data_Tag; use Elementor\Modules\DynamicTags\Module as TagsModule; class SiteUrl extends Data_Tag { public function get_name() { return 'site-url'; } public function get_title() { return esc_html__('Site URL', 'sphere-core'); } public function get_group() { return 'site'; } public function get_categories() { return [TagsModule::URL_CATEGORY]; } public function get_value(array $options = []) { return home_url(); } }PK 03Y���J� � 2 sphere-core/components/elementor/layouts/admin.php<?php namespace Sphere\Core\Elementor\Layouts; /** * Admin related functionality. */ class Admin { public function __construct() { add_action('admin_init', [$this, 'init']); add_action('admin_menu', [$this, 'add_menu']); add_action('admin_enqueue_scripts', [$this, 'register_assets']); } public function init() { // Remove page template options for this CPT. add_action('add_meta_boxes_' . Module::POST_TYPE, function() { unset( $GLOBALS['wp_meta_boxes'][ Module::POST_TYPE ]['side']['core']['pageparentdiv'] ); }, 999); add_filter('views_edit-' . Module::POST_TYPE, [$this, 'output_tabs']); add_action('admin_action_spc_el_layout_add', [$this, 'create_template']); } public function register_assets() { wp_enqueue_style( 'spc-el-layout-admin', Module::instance()->path_url . 'css/admin.css', [], \Sphere\Core\Plugin::VERSION ); $screen = get_current_screen(); if ($screen->id === 'edit-' . Module::POST_TYPE) { wp_enqueue_style('wp-jquery-ui-dialog'); wp_enqueue_script( 'spc-el-layout-admin-js', Module::instance()->path_url . 'js/admin.js', ['jquery-ui-dialog'], \Sphere\Core\Plugin::VERSION ); add_action('admin_footer', [$this, 'output_modal_template']); } } public function add_menu() { // Add submenu but render using the default CPT page. add_submenu_page( 'sphere-dash', esc_html__('Custom Layouts', 'sphere-core'), esc_html__('Custom Layouts', 'sphere-core'), 'edit_pages', 'edit.php?post_type=' . Module::POST_TYPE ); } /** * Action callback to create the custom template. * * @return void */ public function create_template() { if (!check_admin_referer('spc-el-layout-add') || !current_user_can('edit_posts')) { wp_die( esc_html__('Sorry, you do not have permission for this.', 'sphere-core' ), esc_html__('Error', 'sphere-core') ); } $template_type = $_POST['template_type']; if (!$template_type) { wp_die('Missing fields. Please select correct template type.'); } if (!class_exists('\Elementor\Plugin')) { wp_die('Elementor plugin is required to create the template. Please install and activate and the Elementor plugin.'); } $document = \Elementor\Plugin::instance()->documents->get_document_type($template_type); $post_data = [ 'post_type' => Module::POST_TYPE, 'tax_input' => [ Module::TAXONOMY => $template_type, ], 'post_title' => $_POST['template_name'], 'meta_input' => [ '_elementor_edit_mode' => 'builder', $document::TYPE_META_KEY => $template_type ] ]; $post_id = wp_insert_post($post_data); wp_safe_redirect( \Elementor\Plugin::$instance->documents->get($post_id)->get_edit_url() ); } /** * Filter callback: Print our custom tabs on views_edit-CPT filter due to lack of * a better one in core. * * @param $current * @return void */ public function output_tabs($current) { $tabs = [ 'ts-archive' => esc_html__('Archive', 'sphere-core'), 'ts-footer' => esc_html__('Footer', 'sphere-core'), ]; $tabs = ['all' => esc_html__('All', 'sphere-core')] + $tabs; /** * Variables below are used by view file. */ $active_tab = isset($_GET[ Module::TAXONOMY ]) ? $_GET[ Module::TAXONOMY ] : 'all'; if (!isset($tabs[$active_tab])) { $active_tab = 'all'; } $tab_link = admin_url('edit.php?post_type=' . Module::POST_TYPE); $query_arg = Module::TAXONOMY; require_once Module::instance()->path . 'views/tabs.php'; return $current; } public function output_modal_template() { $submit_url = admin_url('admin.php?action=spc_el_layout_add'); $types = Module::instance()->types; require_once Module::instance()->path . 'views/add-modal.php'; } }PK 03YP:t 3 sphere-core/components/elementor/layouts/module.php<?php namespace Sphere\Core\Elementor\Layouts; /** * Elementor Custom Layouts. */ class Module { const TAXONOMY = 'spc-el-layout'; const POST_TYPE = 'spc-el-layouts'; public $path; public $path_url; /** * Types of custom layouts. * * @var array */ public $types = []; /** * Classes objects references. */ public $preview; public $template; public $admin; protected static $instance; public function __construct() { // Register CPT whether elementor exists or not, mainly for import. add_action('init', [$this, 'register_cpt']); // Elementor plugin missing. if (!did_action('elementor/loaded')) { return; } $this->types = [ 'ts-archive' => [ 'label' => esc_html__('Archive', 'admin'), 'doc_class' => 'Archive', 'doc_id' => 'ts-archive', ], 'ts-footer' => [ 'label' => esc_html__('Footer', 'admin'), 'doc_class' => 'Footer', 'doc_id' => 'ts-footer', ], ]; // Initialize the admin. if (is_admin()) { $this->admin = new Admin; } $this->preview = new Preview; // Handle templates at the correct locations. $this->template = new Template; $this->path = \Sphere\Core\Plugin::instance()->path . 'components/elementor/layouts/'; $this->path_url = \Sphere\Core\Plugin::instance()->path_url . 'components/elementor/layouts/'; } public function register_cpt() { $args = [ 'labels' => [ 'name' => esc_html__('Custom Templates', 'sphere-core'), 'singular_name' => esc_html__('Template', 'sphere-core'), 'add_new' => esc_html__('Add New', 'sphere-core'), 'add_new_item' => esc_html__('Add New Template', 'sphere-core'), 'edit_item' => esc_html__('Edit Template', 'sphere-core'), 'new_item' => esc_html__('Add New Template', 'sphere-core'), 'view_item' => esc_html__('View Template', 'sphere-core'), 'search_items' => esc_html__('Search Template', 'sphere-core'), 'not_found' => esc_html__('No Templates Found', 'sphere-core'), 'not_found_in_trash' => esc_html__('No Templates Found In Trash', 'sphere-core'), 'menu_name' => esc_html__('Custom Templates', 'sphere-core'), ], 'public' => true, 'hierarchical' => false, 'show_ui' => true, 'show_in_menu' => false, 'show_in_nav_menus' => false, 'can_export' => true, 'exclude_from_search' => true, 'rewrite' => false, 'capability_type' => 'post', 'supports' => [ 'title', 'editor', 'thumbnail', 'author', 'elementor' ], ]; register_post_type(self::POST_TYPE, $args); // Taxonomy to store the type. register_taxonomy(self::TAXONOMY, self::POST_TYPE, [ 'label' => esc_html__('Type', 'sphere-core'), 'hierarchical' => false, 'query_var' => is_admin(), 'show_ui' => true, 'show_admin_column' => true, 'show_in_nav_menus' => false, 'public' => false, 'rewrite' => false, ]); } /** * Get custom layouts options array. * * @param string $type * @return array */ public function get_options($type = '') { $query_args = [ 'post_type' => Module::POST_TYPE, 'post_status' => 'publish', 'posts_per_page' => -1 ]; if ($type) { $query_args['tax_query'] = [ [ 'taxonomy' => Module::TAXONOMY, 'field' => 'slug', 'terms' => [$type] ] ]; } $results = get_posts($query_args); $layouts = []; foreach ($results as $post) { $layouts[$post->ID] = $post->post_title; } return $layouts; } /** * Get singleton object * * @return self */ public static function instance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } }PK 03Ys��% % 4 sphere-core/components/elementor/layouts/preview.php<?php namespace Sphere\Core\Elementor\Layouts; /** * Preview handlers. */ class Preview { public function __construct() { add_action('elementor/dynamic_tags/before_render', [$this, 'switch_to_preview_query']); add_action('elementor/dynamic_tags/after_render', [$this, 'restore_current_query']); } public function get_document() { $current_post_id = get_the_ID(); $document = \Elementor\Plugin::instance()->documents->get_doc_or_auto_save($current_post_id); return $document; } public function switch_to_preview_query() { $document = $this->get_document(); if (!is_object($document) || !method_exists($document, 'get_preview_as_query_args')) { return; } $new_query_vars = $document->get_preview_as_query_args(); if (!$new_query_vars) { return; } \Elementor\Plugin::instance()->db->switch_to_query($new_query_vars, true); if (method_exists($document, 'after_preview_switch_to_query')) { $document->after_preview_switch_to_query(); } } public function restore_current_query() { \Elementor\Plugin::instance()->db->restore_current_query(); $document = $this->get_document(); if (!is_object($document)) { return; } if (method_exists($document, 'after_restore_current_query')) { $document->after_restore_current_query(); } } } PK 03YV=ִ � 5 sphere-core/components/elementor/layouts/template.php<?php namespace Sphere\Core\Elementor\Layouts; use \Bunyad; use Elementor\Core\Base\Document; /** * Template handlers. */ class Template { public $types = []; /** * @var array */ protected $templates = null; public function __construct() { add_action('elementor/documents/register', [$this, 'register_documents']); add_action('wp_enqueue_scripts',[$this, 'enqueue_styles']); // 11 = after WooCommerce. add_filter('template_include', [$this, 'set_editor_template'], 11); /** * Change page template if one of the content locations have a custom layout. * * Currently 'ts-archive' is the location that goes in content and requires a * canvas page template. */ add_filter('template_include', function($current) { if (!$this->get_for_current('content')) { return $current; } $template = Module::instance()->path . 'page-templates/canvas.php'; return apply_filters('sphere/el-layouts/page_template', $template); }, 99); /** * Render custom templates using the filters. */ $filters = [ 'bunyad_do_partial_footer' => 'ts-footer', ]; foreach ($filters as $filter => $location) { add_filter($filter, function() use ($location) { return !$this->render_by_location($location); }); } } public function enqueue_styles() { $templates = $this->get_templates(); if (!$templates) { return; } $css_files = []; $current_post_id = get_the_ID(); foreach ($templates as $template_id) { // Don't enqueue current post here (let the preview/frontend components to handle it) if ($current_post_id !== $template_id) { $css_files[] = new \Elementor\Core\Files\CSS\Post($template_id); } } if ($css_files) { $front_end = \Elementor\Plugin::instance()->frontend; if (!is_object($front_end)) { return; } $front_end->enqueue_styles(); foreach ($css_files as $css_file) { $css_file->enqueue(); } } } /** * Set the template for CPT (hence the editor). * * @param string $template * @return string */ public function set_editor_template($template) { if (!is_singular(Module::POST_TYPE)) { return $template; } $doc_type = $this->get_doc_type(); $template = 'canvas.php'; switch($doc_type) { case 'ts-footer': $template = 'ts-footer.php'; break; } $template = Module::instance()->path . 'page-templates/' . $template; return apply_filters('sphere/el-layouts/editor_template', $template); } /** * Get document meta type: ts-archive, ts-footer etc. * * @return string */ protected function get_doc_type() { return get_post_meta(get_the_ID(), Document::TYPE_META_KEY, true); } /** * Get templates for current WP view by location. * * @see self::get_templates() * @return array|string */ public function get_for_current(string $location) { $templates = $this->get_templates(); $current_template = null; if ($location && isset($templates[$location])) { $current_template = $templates[$location]; } else if ($location === 'content') { /** * Content locations have a single result, usually. See if there's any available * in the $templates array from above. * * Note: 'ts-archive' is the only template that goes in content location yet. */ $content_templates = array_intersect_key($templates, array_flip([ 'ts-archive' ])); if (count($content_templates)) { $current_template = current($content_templates); } } return apply_filters('sphere/el-layouts/current_template', $current_template, $location); } /** * Get valid configured templates based on current WP view. * * @return array */ protected function get_templates() { // Already computed for current view. if (is_array($this->templates)) { return $this->templates; } $templates = []; /** * Custom Archives templates. */ if (is_archive()) { // Woocommerce doesn't respect is_post_type_archive(). $is_woocommerce = class_exists('woocommerce') && is_woocommerce(); if (Bunyad::options()->category_loop_custom && is_category()) { $templates['ts-archive'] = Bunyad::options()->category_loop_custom; } else if (Bunyad::options()->author_loop_custom && is_author()) { $templates['ts-archive'] = Bunyad::options()->author_loop_custom; } else if (Bunyad::options()->archive_loop_custom && !is_post_type_archive()) { // These have explicit settings, checked above. if (!$is_woocommerce && !is_author() && !is_search() && !is_category()) { $templates['ts-archive'] = Bunyad::options()->archive_loop_custom; } } else if (Bunyad::options()->cpt_loop_custom && is_post_type_archive()) { if (!$is_woocommerce) { $templates['ts-archive'] = Bunyad::options()->cpt_loop_custom; } } /** * Setup template from term meta configs, such as per-category settings. */ $object = get_queried_object(); if (is_object($object) && property_exists($object, 'term_id')) { $term_template = get_term_meta($object->term_id, '_bunyad_custom_template', true); if ($term_template) { $templates['ts-archive'] = $term_template; } // If it's none, the global shouldn't apply either. if ($term_template === 'none') { unset($templates['ts-archive']); } } } /** * Custom footer templates. */ if (Bunyad::options()->footer_custom) { // Global layout. $templates['ts-footer'] = Bunyad::options()->footer_custom; } if (Bunyad::options()->footer_custom_conditions) { $conditions = [ 'pages' => 'is_page', 'posts' => 'is_single', 'archives' => 'is_archive', 'home' => function() { return is_home() || is_front_page(); }, ]; $template_id = false; foreach ($conditions as $type => $condition) { // Check if a custom layout for this type even set. $value = Bunyad::options()->get('footer_custom_' . $type); if (!$value) { continue; } if (call_user_func($condition)) { $template_id = $value; break; } } if ($template_id) { $templates['ts-footer'] = $template_id; } } // Remove any empty values. $this->templates = array_filter($templates); return apply_filters('sphere/el-layouts/location_templates', $templates); } /** * Render a template for a particular location. * * @param string $location * @return boolean */ public function render_by_location($location) { // Showing the template CPT (editor or front preview) if (is_singular(Module::POST_TYPE)) { if ($location === 'ts-footer' && $this->get_doc_type() === 'ts-footer') { the_content(); return true; } } $template = $this->get_for_current($location); if (!$template) { return false; } $this->render($template); return true; } public function render_content() { if (did_action('elementor/preview/init')) { return the_content(); } $this->render_by_location('content'); } public function render($template_id) { echo \Elementor\Plugin::instance()->frontend->get_builder_content($template_id, false); // XSS ok } public function register_documents($manager) { foreach (Module::instance()->types as $type) { $manager->register_document_type( $type['doc_id'], '\Sphere\Core\Elementor\Layouts\Documents\\' . $type['doc_class'] ); } } }PK 03YeӬ6 6 sphere-core/components/elementor/layouts/css/admin.css.spc-el-tabs { margin-top: 10px; margin-bottom: 18px; } .spc-el-add-layout { border-radius: 3px; } .spc-el-add-layout .ui-dialog-titlebar { padding: 10px 25px; height: auto; font-size: 16px; } .spc-el-add-layout .ui-dialog-titlebar-close { top: 8px; right: 6px; } .spc-el-add-layout-content { min-width: 500px; max-width: 95vw; padding: 30px 25px; } .spc-modal-form-field { display: flex; flex-direction: column; margin-bottom: 20px; } .spc-modal-form-field label { margin-bottom: 3px; } .spc-modal-form-field select, .spc-modal-form-field input { width: 100%; max-width: 700px; padding: 6px 12px; border-radius: 3px; } .spc-el-add-layout .form-buttons { text-align: center; } .spc-el-add-layout .button-hero { width: 100%; margin-top: 10px; margin-bottom: 3px; }PK 03Y� #/� � >