Completed
Push — master ( f2187f...c03a3a )
by Sam
02:40
created

src/Template.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This file contains only the Text class
4
 *
5
 * @package Tabulate
6
 */
7
8
namespace WordPress\Tabulate;
9
10
/**
11
 * A Template is a wrapper for a Twig file
12
 */
13
class Template {
14
15
	/**
16
	 * The name of the template to render (if not using a Twig string).
17
	 *
18
	 * @var string
19
	 */
20
	protected $template_name;
21
22
	/**
23
	 * The Twig string to render (if not using a template file).
24
	 *
25
	 * @var string
26
	 */
27
	protected $template_string;
28
29
	/**
30
	 * The template data, all of which is passed to the Twig template.
31
	 *
32
	 * @var string[]
33
	 */
34
	protected $data;
35
36
	/**
37
	 * Paths at which to find templates.
38
	 *
39
	 * @var string[]
40
	 */
41
	protected static $paths = array();
42
43
	/**
44
	 * The name of the transient used to store notices.
45
	 *
46
	 * @var string
47
	 */
48
	protected $transient_notices;
49
50
	/**
51
	 * Create a new template either with a file-based Twig template, or a Twig string.
52
	 *
53
	 * @global \wpdb $wpdb
54
	 * @param string|false $template_name   The name of a Twig file to render.
55
	 * @param string|false $template_string A Twig string to render.
56
	 */
57
	public function __construct( $template_name = false, $template_string = false ) {
58
		global $wpdb;
59
		$this->template_name = $template_name;
60
		$this->template_string = $template_string;
61
		$this->transient_notices = TABULATE_SLUG . '_notices';
62
		$notices = get_transient( $this->transient_notices );
63
		if ( ! is_array( $notices ) ) {
64
			$notices = array();
65
		}
66
		$this->data = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('tabulate_version'...r_can('promote_users')) of type array<string,?,{"tabulat...nt_user_is_admin":"?"}> is incompatible with the declared type array<integer,string> of property $data.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
67
			'tabulate_version' => TABULATE_VERSION,
68
			'notices' => $notices,
69
			'tfo_graphviz' => Util::is_plugin_active( 'tfo-graphviz/tfo-graphviz.php' ),
70
			'wpdb_prefix' => $wpdb->prefix,
71
			'current_user_is_admin' => current_user_can( 'promote_users' ),
72
		);
73
		self::add_path( __DIR__ . '/../templates' );
74
	}
75
76
	/**
77
	 * Add a filesystem path under which to look for template files.
78
	 *
79
	 * @param string $new_path The path to add.
80
	 */
81
	public static function add_path( $new_path ) {
82
		$path = realpath( $new_path );
83
		if ( ! in_array( $path, self::$paths, true ) ) {
84
			self::$paths[] = $path;
85
		}
86
	}
87
88
	/**
89
	 * Get a list of the filesystem paths searched for template files.
90
	 *
91
	 * @return string[] An array of paths
92
	 */
93
	public static function get_paths() {
94
		return self::$paths;
95
	}
96
97
	/**
98
	 * Get a list of templates in a given directory, across all registered template paths.
99
	 *
100
	 * @param string $directory The directory to search in.
101
	 */
102
	public function get_templates( $directory ) {
103
		$templates = array();
104
		foreach ( self::$paths as $path ) {
105
			$dir = $path . '/' . ltrim( $directory, '/' );
106
			foreach ( preg_grep( '/^[^\.].*\.(twig|html)$/', scandir( $dir ) ) as $file ) {
107
				$templates[] = $directory . '/' . $file;
108
			}
109
		}
110
		return $templates;
111
	}
112
113
	/**
114
	 * Magically set a template variable.
115
	 *
116
	 * @param string $name  The name of the variable.
117
	 * @param mixed  $value The value of the variable.
118
	 */
119
	public function __set( $name, $value ) {
120
		$this->data[ $name ] = $value;
121
	}
122
123
	/**
124
	 * Find out whether a given item of template data is set.
125
	 *
126
	 * @param string $name The property name.
127
	 * @return boolean
128
	 */
129
	public function __isset( $name ) {
130
		return isset( $this->data[ $name ] );
131
	}
132
133
	/**
134
	 * Get an item from this template's data.
135
	 *
136
	 * @param string $name The name of the template variable.
137
	 * @return mixed
138
	 */
139
	public function __get( $name ) {
140
		return $this->data[ $name ];
141
	}
142
143
	/**
144
	 * Add a notice. All notices are saved to a Transient, which is deleted when
145
	 * the template is rendered but otherwise available to all subsequent
146
	 * instances of the Template class.
147
	 *
148
	 * @param string $type Either 'updated' or 'error'.
149
	 * @param string $message The message to display.
150
	 */
151
	public function add_notice( $type, $message ) {
152
		$this->data['notices'][] = array(
153
			'type' => $type,
154
			'message' => $message,
155
		);
156
		set_transient( $this->transient_notices, $this->data['notices'] );
157
	}
158
159
	/**
160
	 * Render the template and output it.
161
	 *
162
	 * @return void
163
	 */
164
	public function __toString() {
165
		echo $this->render();
166
	}
167
168
	/**
169
	 * Render the template and return the output.
170
	 *
171
	 * @return string
172
	 */
173
	public function render() {
174
		delete_transient( $this->transient_notices );
175
		$loader = new \Twig_Loader_Filesystem( self::$paths );
176
		$twig = new \Twig_Environment( $loader );
177
178
		// Add some useful functions to Twig.
179
		$funcs = array( 'admin_url', '__', '_e', 'wp_create_nonce' );
180
		foreach ( $funcs as $f ) {
181
			$twig->addFunction( $f, new \Twig_SimpleFunction( $f, $f ) );
182
		}
183
		// Handle wp_nonce_field() differently in order to default it to returning the string.
184
		$wp_nonce_field = new \Twig_SimpleFunction( 'wp_nonce_field', function ( $action = -1, $name = "_wpnonce", $referer = true, $echo = false ) {
185
			return wp_nonce_field( $action, $name, $referer, $echo );
186
		} );
187
		$twig->addFunction( $wp_nonce_field );
188
189
		// Add titlecase filter.
190
		$titlecase_filter = new \Twig_SimpleFilter( 'titlecase', '\\WordPress\\Tabulate\\Text::titlecase' );
191
		$twig->addFilter( $titlecase_filter );
192
193
		// Add date and time filters.
194
		$date_filter = new \Twig_SimpleFilter( 'wp_date_format', '\\WordPress\\Tabulate\\Text::wp_date_format' );
195
		$twig->addFilter( $date_filter );
196
		$time_filter = new \Twig_SimpleFilter( 'wp_time_format', '\\WordPress\\Tabulate\\Text::wp_time_format' );
197
		$twig->addFilter( $time_filter );
198
		$twig->addFilter( new \Twig_SimpleFilter( 'get_date_from_gmt', 'get_date_from_gmt' ) );
199
200
		// Add strtolower filter.
201
		$strtolower_filter = new \Twig_SimpleFilter( 'strtolower', function( $str ) {
202
			if ( is_array( $str ) ) {
203
				return array_map( 'strtolower', $str );
204
			} else {
205
				return strtolower( $str );
206
			}
207
		} );
208
		$twig->addFilter( $strtolower_filter );
209
210
		// Enable debugging.
211
		if ( WP_DEBUG ) {
212
			$twig->enableDebug();
213
			$twig->addExtension( new \Twig_Extension_Debug() );
214
		}
215
216
		// Render the template.
217
		if ( ! empty( $this->template_string ) ) {
218
			$template = $twig->createTemplate( $this->template_string );
219
		} else {
220
			$template = $twig->loadTemplate( $this->template_name );
221
		}
222
		return $template->render( $this->data );
223
	}
224
}
225