diff --git a/includes/core/classes/endpoints/class-endpoint-template.php b/includes/core/classes/endpoints/class-endpoint-template.php new file mode 100644 index 000000000..cc213be25 --- /dev/null +++ b/includes/core/classes/endpoints/class-endpoint-template.php @@ -0,0 +1,168 @@ +plugin_template_dir = ( ! empty( $plugin_template_dir ) ) ? $plugin_template_dir : sprintf( + '%s/includes/templates/endpoints', + GATHERPRESS_CORE_PATH + ); + } + + + /** + * Activate Endpoint_Type by hooking into relevant parts. + * + * @since 1.0.0 + * + * @return void + */ + public function activate(): void { + // Filters the path of the current template before including it. + add_filter( 'template_include', array( $this, 'template_include' ) ); + } + + /** + * Filters the path of the current template before including it. + * + * This method checks if the theme or child theme provides a custom template for the + * current endpoint. If a theme template exists, it will use that; otherwise, it will + * fall back to the default template provided by the plugin. The template information + * is provided by the callback set during the construction of the endpoint. + * + * @since 1.0.0 + * + * @param string $template The path of the default template to include. + * @return string The path of the template to include, either from the theme or plugin. + */ + public function template_include( string $template ): string { + $presets = $this->get_template_presets(); + + $file_name = $presets['file_name']; + $dir_path = $presets['dir_path'] ?? $this->plugin_template_dir; + + // Check if the theme provides a custom template. + $theme_template = $this->get_template_from_theme( $file_name ); + if ( $theme_template ) { + return $theme_template; + } + + // Check if the plugin has a template file. + $plugin_template = $this->get_template_from_plugin( $file_name, $dir_path, ); + if ( $plugin_template ) { + return $plugin_template; + } + + // Fallback to the default template. + return $template; + } + + + /** + * Retrieve template presets by invoking the callback. + * + * @return array Template preset data including file_name and optional dir_path. + */ + protected function get_template_presets(): array { + return ( $this->callback )(); + } + + /** + * Locate a template in the theme or child theme. + * + * @todo Maybe better put in the Utility class? + * + * @param string $file_name The name of the template file. + * @return string|false The path to the theme template or false if not found. + */ + protected function get_template_from_theme( string $file_name ) { + + // locate_template() doesn't cares, + // but locate_block_template() needs this to be an array. + $templates = array( $file_name ); + + // First, search for PHP templates, which block themes can also use. + $template = locate_template( $templates ); + + // Pass the result into the block template locator and let it figure + // out whether block templates are supported and this template exists. + $template = locate_block_template( + $template, + pathinfo( $file_name, PATHINFO_FILENAME ), // Name of the file without extension. + $templates + ); + + return ( is_string( $template ) && ! empty( $template ) ) ? $template : false; + } + + /** + * Build the full path to the plugin's template file. + * + * @todo Maybe better put in the Utility class? + * + * @param string $file_name The name of the template file. + * @param string $dir_path The directory path where the template is stored. + * @return string|false The full path to the template file or false if file not exists. + */ + protected function get_template_from_plugin( string $file_name, string $dir_path ): string { + // Remove prefix to keep file-names simple, + // for templates of core GatherPress. + if ( $this->plugin_template_dir === $dir_path ) { + $file_name = Utility::unprefix_key( $file_name ); + } + + $template = trailingslashit( $dir_path ) . $file_name; + return file_exists( $template ) ? $template : false; + } +} \ No newline at end of file