@@ -134,53 +134,93 @@ public function getEditor($subtype = NULL,
134
134
* Array of metadata objects found.
135
135
*/
136
136
protected function getRawMetadata () {
137
- $ id = $ this ->getId ();
138
- $ it = new RecursiveDirectoryIterator ($ this ->path );
139
- $ filter = array ('json ' );
140
- $ metadata = array ();
141
- /** @var \SplFileInfo $file */
142
- foreach (new RecursiveIteratorIterator ($ it ) as $ file ) {
143
- if (!$ file ->isFile ()) {
144
- continue ;
145
- }
146
- $ file_path = $ file ->getPath ();
147
- $ dirs = explode (DIRECTORY_SEPARATOR , $ file_path );
148
- // All JSON schema must be in an 'api' folder at this time.
149
- // @todo Add support for custom setups.
150
- // @todo Look at a standard for JSON Schema + JSON Sample data.
151
- $ num_dirs = count ($ dirs );
152
- if ($ num_dirs < 2
153
- || array_pop ($ dirs ) !== 'api ' ) {
154
- continue ;
155
- }
156
- $ file_ext = $ file ->getExtension ();
157
- if (!in_array (strtolower ($ file_ext ), $ filter , TRUE )) {
158
- continue ;
137
+ static $ metadata ;
138
+
139
+ // Use static pattern to avoid rebuilding multiple times per request.
140
+ if (is_null ($ metadata )) {
141
+
142
+ $ it = new RecursiveDirectoryIterator ($ this ->path );
143
+ $ filter = ['json ' , 'twig ' ];
144
+ $ metadata = [];
145
+ $ components = [];
146
+
147
+ /** @var \SplFileInfo $file */
148
+ foreach (new RecursiveIteratorIterator ($ it ) as $ file ) {
149
+ // Skip directories and non-files.
150
+ if (!$ file ->isFile ()) {
151
+ continue ;
152
+ }
153
+ $ file_path = $ file ->getPath ();
154
+
155
+ // Skip tests folders.
156
+ if (strpos ($ file_path , '/tests ' ) !== FALSE ) {
157
+ continue ;
158
+ }
159
+
160
+ // Get the file extension for the file.
161
+ $ file_ext = $ file ->getExtension ();
162
+ if (!in_array (strtolower ($ file_ext ), $ filter , TRUE )) {
163
+ continue ;
164
+ }
165
+
166
+ // We use file_basename as a unique key, it is required that the
167
+ // JSON and twig file share this basename.
168
+ $ file_basename = $ file ->getBasename ('. ' . $ file_ext );
169
+
170
+ // Build an array of all the filenames of interest, keyed by name.
171
+ $ components [$ file_basename ][$ file_ext ] = $ file_path ;
159
172
}
160
- if ($ file_contents = file_get_contents ($ file )) {
161
- $ pattern = $ this ->createPattern (json_decode ($ file_contents ));
162
- $ file_basename = $ file ->getBasename ('.json ' );
163
- $ subtype = "pk_ $ file_basename " ;
164
- $ pattern ->subtype = $ subtype ;
165
- $ pattern ->url = url ("patternkit/ajax/ $ id/ $ subtype/schema " );
166
- $ twig_file = $ file_path
167
- . DIRECTORY_SEPARATOR . $ file_basename . '.twig ' ;
168
- if (file_exists ($ twig_file )) {
169
- $ pattern ->filename = $ twig_file ;
170
- $ pattern ->template = file_get_contents ($ twig_file );
173
+
174
+ foreach ($ components as $ module_name => $ data ) {
175
+ // If the component has a json file, create the pattern from it.
176
+ if (!empty ($ data ['json ' ]) && $ file_contents = file_get_contents ($ data ['json ' ])) {
177
+ $ pattern = $ this ->createPattern (json_decode ($ file_contents ));
178
+
179
+ $ subtype = "pk_ $ module_name " ;
180
+ $ pattern ->subtype = $ subtype ;
181
+ // URL is redundant for the twig based components.
182
+ $ pattern ->url = $ module_name ;
183
+ }
184
+ else {
185
+ // Create the pattern from defaults.
186
+ $ pattern = $ this ->createPattern (
187
+ (object ) [
188
+ '$schema ' => 'http =>//json-schema.org/draft-04/schema# ' ,
189
+ 'category ' => 'atom ' ,
190
+ 'title ' => $ module_name ,
191
+ 'type ' => 'object ' ,
192
+ 'format ' => 'grid ' ,
193
+ 'properties ' => (object ) [],
194
+ 'required ' => [],
195
+ ]
196
+ );
197
+ }
198
+
199
+ if (!empty ($ data ['twig ' ])) {
200
+ $ twig_file = $ data ['twig ' ]
201
+ . DIRECTORY_SEPARATOR . $ module_name . '.twig ' ;
202
+ if (file_exists ($ twig_file )) {
203
+ $ pattern ->filename = $ twig_file ;
204
+ $ pattern ->template = file_get_contents ($ twig_file );
205
+ }
171
206
}
172
- $ metadata [$ file_basename ] = $ pattern ;
207
+
208
+ $ metadata [$ module_name ] = $ pattern ;
173
209
}
174
- }
175
- foreach ($ metadata as $ pattern_type => $ pattern ) {
176
- // Replace any $ref links with relative paths.
177
- if (!isset ($ pattern ->schema ->properties )) {
178
- continue ;
210
+
211
+ foreach ($ metadata as $ pattern_type => $ pattern ) {
212
+ // Replace any $ref links with relative paths.
213
+ if (!isset ($ pattern ->schema ->properties )) {
214
+ continue ;
215
+ }
216
+ $ pattern ->schema ->properties = _patternkit_schema_ref (
217
+ $ pattern ->schema ->properties ,
218
+ $ metadata
219
+ );
220
+ $ metadata [$ pattern_type ] = $ pattern ;
179
221
}
180
- $ pattern ->schema ->properties = _patternkit_schema_ref ($ pattern ->schema ->properties ,
181
- $ metadata );
182
- $ metadata [$ pattern_type ] = $ pattern ;
183
222
}
223
+
184
224
return $ metadata ;
185
225
}
186
226
@@ -195,14 +235,115 @@ protected function getRawMetadata() {
195
235
* @return string
196
236
* The rendered pattern HTML.
197
237
*/
198
- public function getRenderedPatternMarkup (PatternkitPattern $ pattern ,
199
- PatternkitEditorConfig $ config ) {
238
+ public function getRenderedPatternMarkup (
239
+ PatternkitPattern $ pattern ,
240
+ PatternkitEditorConfig $ config
241
+ ) {
200
242
if (empty ($ pattern ->filename ) || empty ($ config ->fields )) {
201
243
return '' ;
202
244
}
203
245
$ template = $ pattern ->filename ;
204
246
$ variables = $ config ->fields ;
205
- return twig_render_template ($ template , $ variables );
247
+
248
+ return $ this ->renderTwigTemplate ($ template , $ variables );
249
+ }
250
+
251
+ /**
252
+ * Returns a singleton version of the twig template engine.
253
+ *
254
+ * @return Twig_Environment
255
+ * Twig environment object.
256
+ *
257
+ * @throws \Twig_Error_Loader
258
+ * Twig engine instance object.
259
+ */
260
+ public function getTwigInstance () {
261
+ static $ twig_engine ;
262
+
263
+ if (!is_object ($ twig_engine )) {
264
+ // Setup twig environment.
265
+ // @TODO: Properly libraryize this.
266
+ require_once DRUPAL_ROOT . '/sites/all/libraries/Twig/Autoloader.php ' ;
267
+ Twig_Autoloader::register ();
268
+
269
+ $ loader = new Twig_Loader_Filesystem ();
270
+
271
+ $ metadata = $ this ->getRawMetadata ();
272
+ foreach ($ metadata as $ module_name => $ module ) {
273
+ if (!empty ($ module ->filename )) {
274
+ $ templatesDirectory = DRUPAL_ROOT . DIRECTORY_SEPARATOR . dirname (
275
+ $ module ->filename
276
+ );
277
+ $ loader ->addPath ($ templatesDirectory );
278
+ }
279
+ }
280
+
281
+ $ twig_engine = new Twig_Environment (
282
+ $ loader ,
283
+ array (
284
+ 'autorender ' => (bool ) variable_get ('pktwig_auto_render ' , TRUE ),
285
+ 'autoescape ' => (bool ) variable_get ('pktwig_auto_escape ' , FALSE ),
286
+ 'auto_reload ' => (bool ) variable_get ('pktwig_auto_reload ' , FALSE ),
287
+ 'cache ' => variable_get ('pktwig_template_cache_path ' , '/tmp/twig_compilation_cache ' ),
288
+ 'debug ' => (bool ) variable_get ('pktwig_debug ' , FALSE ),
289
+ )
290
+ );
291
+ }
292
+
293
+ return $ twig_engine ;
294
+ }
295
+
296
+ /**
297
+ * Renders a twig template on demand.
298
+ *
299
+ * @param string $template
300
+ * Template filename.
301
+ * @param array $variables
302
+ * Variables to be assigned to template.
303
+ *
304
+ * @return string
305
+ * Rendered template.
306
+ */
307
+ public function renderTwigTemplate ($ template , array $ variables = array ()) {
308
+
309
+ $ content = '' ;
310
+ if (file_exists ($ template )) {
311
+ try {
312
+ $ twig = $ this ->getTwigInstance ();
313
+ $ template = $ twig ->loadTemplate (basename ($ template ));
314
+ $ content = $ template ->render ($ variables );
315
+ }
316
+ catch (Exception $ e ) {
317
+ $ content = t ('Twig error "!error" ' , array ('!error ' => $ e ->getMessage ()));
318
+ watchdog (
319
+ 'patternkit ' ,
320
+ 'Twig engine failure: @msg ' ,
321
+ array (
322
+ '@msg ' => $ e ->getMessage (),
323
+ ),
324
+ WATCHDOG_ERROR
325
+ );
326
+ }
327
+ }
328
+ else {
329
+ $ content = t (
330
+ 'Template (!template) not found ' ,
331
+ array (
332
+ '!template ' => $ template ,
333
+ )
334
+ );
335
+ watchdog (
336
+ 'patternkit ' ,
337
+ 'Twig template not found: @msg ' ,
338
+ array (
339
+ '@msg ' => $ template ,
340
+ ),
341
+ WATCHDOG_ERROR
342
+ );
343
+ }
344
+
345
+ $ content .= "poop " ;
346
+ return $ content ;
206
347
}
207
348
208
349
}
0 commit comments