PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Helpers / TemplateLocator.php

TemplateLocator.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.0, at includes/Helpers/TemplateLocator.php

127 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Theme-overridable template lookup.
4 *
5 * @package Easy_Invoice
6 * @subpackage Helpers
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Resolve a template name to a file, letting the theme override it.
15 *
16 * Lookup order:
17 * 1. {child theme}/easy-invoice/{template}
18 * 2. {parent theme}/easy-invoice/{template}
19 * 3. {plugin}/templates/{template}
20 *
21 * This is the same convention WooCommerce established, so anyone who has
22 * customised a shop knows what to do: copy the file into the theme, keep the
23 * path, edit. Until now every template path in the plugin was hard-coded, so
24 * the only way to change what a client saw was to edit the plugin and lose
25 * it on the next update.
26 *
27 * The plugin's own screens (the admin pages under templates/admin) go
28 * through this too, but a theme has no business overriding those; only the
29 * public documents, the design templates and the PDFs are documented as
30 * overridable.
31 *
32 * @param string $template Path relative to the plugin's templates/ directory,
33 * e.g. 'document/single.php'.
34 * @param array $args Context, passed to the filter for callers that want
35 * to switch templates on it.
36 * @return string Absolute path, or '' when nothing exists anywhere.
37 */
38 function easy_invoice_locate_template( string $template, array $args = [] ): string {
39 $template = ltrim( str_replace( '\\', '/', $template ), '/' );
40
41 // Never let a template name climb out of the directories we search.
42 if ( '' === $template || false !== strpos( $template, '..' ) ) {
43 return '';
44 }
45
46 /**
47 * Filter the folder inside a theme that holds overrides.
48 *
49 * @param string $dir Folder name, default 'easy-invoice'.
50 */
51 $theme_dir = trim( (string) apply_filters( 'easy_invoice_template_directory', 'easy-invoice' ), '/' );
52
53 $candidates = [];
54 if ( '' !== $theme_dir ) {
55 $candidates[] = trailingslashit( get_stylesheet_directory() ) . $theme_dir . '/' . $template;
56 if ( get_template_directory() !== get_stylesheet_directory() ) {
57 $candidates[] = trailingslashit( get_template_directory() ) . $theme_dir . '/' . $template;
58 }
59 }
60 $candidates[] = EASY_INVOICE_PLUGIN_DIR . 'templates/' . $template;
61
62 $located = '';
63 foreach ( $candidates as $candidate ) {
64 if ( file_exists( $candidate ) ) {
65 $located = $candidate;
66 break;
67 }
68 }
69
70 /**
71 * Filter the resolved template path.
72 *
73 * Lets an addon or a site ship a template somewhere other than the
74 * theme. Return '' to declare it missing.
75 *
76 * @param string $located Absolute path found, or ''.
77 * @param string $template The relative name asked for.
78 * @param array $args Context passed by the caller.
79 */
80 $located = (string) apply_filters( 'easy_invoice_locate_template', $located, $template, $args );
81
82 return ( '' !== $located && file_exists( $located ) ) ? $located : '';
83 }
84
85 /**
86 * Include a template, exposing $args as variables.
87 *
88 * @param string $template Relative template name.
89 * @param array $args Variables the template may read.
90 * @return void
91 */
92 function easy_invoice_get_template( string $template, array $args = [] ): void {
93 $located = easy_invoice_locate_template( $template, $args );
94 if ( '' === $located ) {
95 return;
96 }
97
98 if ( ! empty( $args ) ) {
99 extract( $args, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- template context, keys are ours.
100 }
101
102 include $located;
103 }
104
105 /**
106 * Resolve a design template (the look of an invoice or quote) by name.
107 *
108 * Falls back through the plugin's 'default' design when the requested one
109 * does not exist anywhere, so an invoice that references a design from an
110 * addon that has since been switched off still renders.
111 *
112 * @param string $type 'invoice' or 'quote'.
113 * @param string $name Design name, e.g. 'standard'.
114 * @return string Absolute path to the design file.
115 */
116 function easy_invoice_design_template( string $type, string $name ): string {
117 $folder = ( 'quote' === $type ) ? 'quote-templates' : 'invoice-templates';
118 $name = sanitize_file_name( '' !== $name ? $name : 'standard' );
119
120 $path = easy_invoice_locate_template( $folder . '/' . $name . '.php', [ 'type' => $type, 'design' => $name ] );
121 if ( '' === $path ) {
122 $path = easy_invoice_locate_template( $folder . '/default.php', [ 'type' => $type, 'design' => 'default' ] );
123 }
124
125 return $path;
126 }
127