@@ -279,4 +279,92 @@ protected static function loadComponentDefinitionFromFs(string $component_name):
279279 );
280280 }
281281
282+ /**
283+ * Loads all component definitions from the civictheme components folder.
284+ *
285+ * @return array<int, array<mixed>>
286+ * An array of component definitions.
287+ */
288+ public static function loadAllComponentDefinitionsFromCivicTheme (): array {
289+ $ components_dir = dirname (__DIR__ , 6 ) . '/themes/contrib/civictheme/components ' ;
290+ $ definitions = [];
291+ if (!is_dir ($ components_dir )) {
292+ return $ definitions ;
293+ }
294+ foreach (new \DirectoryIterator ($ components_dir ) as $ fileinfo ) {
295+ if ($ fileinfo ->isDot () || !$ fileinfo ->isDir ()) {
296+ continue ;
297+ }
298+ $ subdir = $ fileinfo ->getPathname ();
299+ foreach (new \DirectoryIterator ($ subdir ) as $ subfileinfo ) {
300+ if ($ subfileinfo ->isDot () || !$ subfileinfo ->isDir ()) {
301+ continue ;
302+ }
303+ $ component_file = $ subfileinfo ->getPathname () . '/ ' . $ subfileinfo ->getFilename () . '.component.yml ' ;
304+ if (file_exists ($ component_file )) {
305+ try {
306+ $ definition = Yaml::parseFile ($ component_file );
307+ // Merge with additional required keys.
308+ $ component_name = $ subfileinfo ->getFilename ();
309+ $ definition = array_merge (
310+ $ definition ,
311+ [
312+ 'machineName ' => $ component_name ,
313+ 'extension_type ' => 'theme ' ,
314+ 'id ' => 'civictheme: ' . $ component_name ,
315+ 'library ' => ['css ' => ['component ' => ['foo.css ' => []]]],
316+ 'path ' => '' ,
317+ 'provider ' => 'civictheme ' ,
318+ 'template ' => $ component_name . '.twig ' ,
319+ 'group ' => 'civictheme-group ' ,
320+ 'description ' => 'CivicTheme component ' ,
321+ ]
322+ );
323+ $ definitions [] = $ definition ;
324+ }
325+ catch (\Exception ) {
326+ // Ignore invalid YAML files for this loader.
327+ continue ;
328+ }
329+ }
330+ }
331+ }
332+ return $ definitions ;
333+ }
334+
335+ /**
336+ * Tests that all CivicTheme component definitions don't cause errors.
337+ *
338+ * @dataProvider dataProviderValidateAllCivicThemeDefinitionsValid
339+ *
340+ * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
341+ */
342+ public function testValidateAllCivicThemeDefinitionsValid (array $ definition ): void {
343+ $ component_validator = new ComponentValidator ();
344+ $ component_validator ->setValidator ();
345+ $ this ->assertTrue (
346+ $ component_validator ->validateDefinition ($ definition , TRUE ),
347+ sprintf (
348+ 'The CivicTheme component definition "%s" did not pass validation. ' ,
349+ $ definition ['machineName ' ] ?? '[unknown] '
350+ )
351+ );
352+ }
353+
354+ /**
355+ * Data provider with all CivicTheme component definitions.
356+ *
357+ * @return array<int, array<int, array<mixed>>>
358+ * The data.
359+ */
360+ public static function dataProviderValidateAllCivicThemeDefinitionsValid (): array {
361+ $ definitions = static ::loadAllComponentDefinitionsFromCivicTheme ();
362+ $ result = [];
363+ foreach ($ definitions as $ definition ) {
364+ $ key = $ definition ['machineName ' ] ?? uniqid ('component_ ' , TRUE );
365+ $ result [$ key ] = [$ definition ];
366+ }
367+ return $ result ;
368+ }
369+
282370}
0 commit comments