initialize(); // Return the instance. return self::$instance; } /** * Setup the singleton instance * * @access private */ private static function setup_instance() { self::$instance = new Theme(); } /** * Return whether the main loading class has been instantiated or not. * * @access private * @return boolean True if instantiated. False if not. */ private static function is_instantiated() { // Return true if instance is correct class. if ( ! empty( self::$instance ) && ( self::$instance instanceof Theme ) ) { return true; } // Return false if not instantiated correctly. return false; } /** * Constructor. * * Sets the theme components. * * @param array $components Optional. List of theme components. Only intended for custom initialization, typically * the theme components are declared by the theme itself. Each theme component must * implement the Component_Interface interface. * * @throws InvalidArgumentException Thrown if one of the $components does not implement Component_Interface. */ public function __construct( array $components = array() ) { spl_autoload_register( array( $this, 'autoload' ) ); if ( empty( $components ) ) { $components = $this->get_default_components(); } // Set the components. foreach ( $components as $component ) { // Bail if a component is invalid. if ( ! $component instanceof Component_Interface ) { throw new InvalidArgumentException( sprintf( /* translators: 1: classname/type of the variable, 2: interface name */ __( 'The theme component %1$s does not implement the %2$s interface.', 'kadence' ), gettype( $component ), Component_Interface::class ) ); } $this->components[ $component->get_slug() ] = $component; } // Instantiate the template tags instance for all theme templating components. $this->template_tags = new Template_Tags( array_filter( $this->components, function( Component_Interface $component ) { return $component instanceof Templating_Component_Interface; } ) ); } /** * Custom autoloader function for theme classes. * * @access private * * @param string $class_name Class name to load. * @return bool True if the class was loaded, false otherwise. */ private function autoload( $class_name ) { $namespace = 'Kadence'; if ( strpos( $class_name, $namespace . '\\' ) !== 0 ) { return false; } $parts = explode( '\\', substr( $class_name, strlen( $namespace . '\\' ) ) ); $path = get_template_directory() . '/inc/components'; foreach ( $parts as $part ) { $path .= '/' . strtolower( $part ); } $path .= '.php'; if ( ! file_exists( $path ) ) { return false; } require_once $path; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound return true; } /** * Throw error on object clone. * * The whole idea of the singleton design pattern is that there is a single * object therefore, we don't want the object to be cloned. * * @return void */ public function __clone() { // Cloning instances of the class is forbidden. _doing_it_wrong( __FUNCTION__, esc_html__( 'Something went wrong.', 'kadence' ), '1.0' ); } /** * Disable un-serializing of the class. * * @return void */ public function __wakeup() { // Unserializing instances of the class is forbidden. _doing_it_wrong( __FUNCTION__, esc_html__( 'Something went wrong.', 'kadence' ), '1.0' ); } /** * Adds the action and filter hooks to integrate with WordPress. * * This method must only be called once in the request lifecycle. */ public function initialize() { array_walk( $this->components, function( Component_Interface $component ) { $component->initialize(); } ); } /** * Retrieves the template tags instance, the entry point exposing template tag methods. * * Calling `kadence()` is a short-hand for calling this method on the main theme instance. The instance then allows * for actual template tag methods to be called. For example, if there is a template tag called `posted_on`, it can * be accessed via `kadence()->posted_on()`. * * @return Template_Tags Template tags instance. */ public function template_tags() : Template_Tags { return $this->template_tags; } /** * Retrieves the component for a given slug. * * This should typically not be used from outside of the theme classes infrastructure. * * @param string $slug Slug identifying the component. * @return Component_Interface Component for the slug. * * @throws InvalidArgumentException Thrown when no theme component with the given slug exists. */ public function component( string $slug ) : Component_Interface { if ( ! isset( $this->components[ $slug ] ) ) { throw new InvalidArgumentException( sprintf( /* translators: %s: slug */ __( 'No theme component with the slug %s exists.', 'kadence' ), $slug ) ); } return $this->components[ $slug ]; } /** * Gets the default theme components. * * This method is called if no components are passed to the constructor, which is the common scenario. * * @return array List of theme components to use by default. */ protected function get_default_components() : array { $components = array( new Options\Component(), new Localization\Component(), new Base_Support\Component(), new Editor\Component(), new Accessibility\Component(), new Image_Sizes\Component(), new AMP\Component(), new Microdata\Component(), //new PWA\Component(), new Comments\Component(), new Nav_Menus\Component(), new Custom_Header\Component(), new Custom_Footer\Component(), new Custom_Logo\Component(), new Color_Palette\Component(), new Styles\Component(), new Scripts\Component(), new Breadcrumbs\Component(), new Template_Parts\Component(), new Clean_Frontend\Component(), new Icons\Component(), new Layout\Component(), new Entry_Title\Component(), new Archive_Title\Component(), new Third_Party\Component(), ); if ( class_exists( '\Elementor\Plugin' ) ) { $components[] = new Elementor\Component(); } if ( class_exists( 'ElementorPro\Modules\ThemeBuilder\Module' ) ) { $components[] = new Elementor_Pro\Component(); } if ( class_exists( 'FLThemeBuilderLayoutData' ) ) { $components[] = new BeaverThemer\Component(); } if ( class_exists( 'FLBuilderModel' ) ) { $components[] = new Beaver\Component(); } if ( class_exists( 'TUTOR\Tutor' ) ) { $components[] = new TutorLMS\Component(); } if ( class_exists( 'woocommerce' ) ) { $components[] = new Woocommerce\Component(); } if ( class_exists( 'HT_Knowledge_Base' ) ) { $components[] = new Heroic_Kb\Component(); } if ( defined( 'JETPACK__VERSION' ) ) { $components[] = new Jetpack\Component(); } if ( class_exists( 'LifterLMS' ) ) { $components[] = new LifterLMS\Component(); } if ( defined( 'LEARNDASH_VERSION' ) ) { $components[] = new LearnDash\Component(); } if ( class_exists( 'Essential_Real_Estate' ) ) { $components[] = new Essential_Real_Estate\Component(); } if ( class_exists( 'Restrict_Content_Pro' ) ) { $components[] = new Restrict_Content_Pro\Component(); } if ( class_exists( 'Estatik' ) ) { $components[] = new Estatik\Component(); } if ( class_exists( 'BBPress' ) && apply_filters( 'kadence_theme_enable_bbpress_component', true ) ) { $components[] = new BBPress\Component(); } if ( defined( 'BP_PLATFORM_VERSION' ) ) { $components[] = new BuddyBoss\Component(); } if ( defined( 'POLYLANG_VERSION' ) ) { $components[] = new Polylang\Component(); } if ( defined( 'TRIBE_EVENTS_FILE' ) ) { $components[] = new The_Events_Calendar\Component(); } if ( defined( 'GIVE_VERSION' ) ) { $components[] = new Give\Component(); } if ( defined( 'WPZOOM_RCB_VERSION' ) ) { $components[] = new Zoom_Recipe_Card\Component(); } return $components; } }