From 09057aff446c7d71fb0d79f87d594b3feca1f0d5 Mon Sep 17 00:00:00 2001
From: Antonio De Marco <antonio@nuvole.org>
Date: Sun, 9 Apr 2017 14:56:22 +0200
Subject: [PATCH] Initial work on #91

---
 .../UiPatterns/Pattern/LibraryPattern.php     | 124 +++++++++++-
 src/UiPatternBase.php                         |  96 +++++++++-
 src/UiPatternInterface.php                    |  21 ++
 src/UiPatternsManager.php                     | 181 ++----------------
 src/UiPatternsManagerInterface.php            |  27 +--
 tests/features/overview.feature               |   1 -
 tests/src/Kernel/UiPatternBaseTest.php        |  39 +++-
 tests/src/Unit/UiPatternsManagerTest.php      |  35 ----
 ui_patterns.module                            |  30 ++-
 ui_patterns.services.yml                      |   2 +-
 10 files changed, 318 insertions(+), 238 deletions(-)
 delete mode 100644 tests/src/Unit/UiPatternsManagerTest.php

diff --git a/modules/ui_patterns_library/src/Plugin/UiPatterns/Pattern/LibraryPattern.php b/modules/ui_patterns_library/src/Plugin/UiPatterns/Pattern/LibraryPattern.php
index 87aff7204..90bd12369 100644
--- a/modules/ui_patterns_library/src/Plugin/UiPatterns/Pattern/LibraryPattern.php
+++ b/modules/ui_patterns_library/src/Plugin/UiPatterns/Pattern/LibraryPattern.php
@@ -2,8 +2,11 @@
 
 namespace Drupal\ui_patterns_library\Plugin\UiPatterns\Pattern;
 
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Core\TypedData\TypedDataManager;
 use Drupal\ui_patterns\UiPatternBase;
-use Drupal\ui_patterns\UiPatternInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * The UI Pattern plugin.
@@ -17,6 +20,123 @@ use Drupal\ui_patterns\UiPatternInterface;
  *   deriver = "\Drupal\ui_patterns_library\Plugin\Deriver\LibraryDeriver"
  * )
  */
-class LibraryPattern extends UiPatternBase implements UiPatternInterface {
+class LibraryPattern extends UiPatternBase {
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * UiPatternsManager constructor.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, $root, TypedDataManager $typed_data_manager, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $root, $typed_data_manager);
+    $this->moduleHandler = $module_handler;
+    $this->themeHandler = $theme_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('app.root'),
+      $container->get('typed_data_manager'),
+      $container->get('module_handler'),
+      $container->get('theme_handler')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getThemeImplementation() {
+    $item = [];
+    $definition = $this->getPluginDefinition();
+
+    foreach ($definition['fields'] as $field) {
+      $item['variables'][$field['name']] = NULL;
+    }
+    $item['variables']['attributes'] = [];
+    $item['variables']['context'] = [];
+    $item['variables']['use'] = '';
+
+    $item += $this->processUseProperty($definition);
+    $item += $this->processCustomThemeHookProperty($definition);
+    $item += $this->processTemplateProperty($definition);
+
+    return [
+      $definition['theme hook'] => $item,
+    ];
+  }
+
+  /**
+   * Process 'custom hook theme' definition property.
+   *
+   * @param array $definition
+   *    Pattern definition array.
+   *
+   * @return array
+   *    Processed hook definition portion.
+   */
+  protected function processCustomThemeHookProperty(array $definition) {
+    /** @var \Drupal\Core\Extension\Extension $module */
+    $return = [];
+    if (!$definition['custom theme hook'] && $this->moduleHandler->moduleExists($definition['provider'])) {
+      $module = $this->moduleHandler->getModule($definition['provider']);
+      $return['path'] = $module->getPath() . '/templates';
+    }
+    return $return;
+  }
+
+  /**
+   * Process 'template' definition property.
+   *
+   * @param array $definition
+   *    Pattern definition array.
+   *
+   * @return array
+   *    Processed hook definition portion.
+   */
+  protected function processTemplateProperty(array $definition) {
+    $return = [];
+    if (isset($definition['template'])) {
+      $return = ['template' => $definition['template']];
+    }
+    return $return;
+  }
+
+  /**
+   * Process 'use' definition property.
+   *
+   * @param array $definition
+   *    Pattern definition array.
+   *
+   * @return array
+   *    Processed hook definition portion.
+   */
+  protected function processUseProperty(array $definition) {
+    $return = [];
+    if (!empty($definition['use'])) {
+      $return = [
+        'path' => $this->moduleHandler->getModule('ui_patterns')->getPath() . '/templates',
+        'template' => 'patterns-use-wrapper',
+      ];
+    }
+    return $return;
+  }
 
 }
diff --git a/src/UiPatternBase.php b/src/UiPatternBase.php
index c4e585910..f9dc9a36a 100644
--- a/src/UiPatternBase.php
+++ b/src/UiPatternBase.php
@@ -3,19 +3,58 @@
 namespace Drupal\ui_patterns;
 
 use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\TypedData\TypedDataManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Class UiPatternBase.
  *
  * @package Drupal\ui_patterns
  */
-abstract class UiPatternBase extends PluginBase implements UiPatternInterface {
+abstract class UiPatternBase extends PluginBase implements UiPatternInterface, ContainerFactoryPluginInterface {
 
   /**
    * Prefix for locally defined libraries.
    */
   const LIBRARY_PREFIX = 'ui_patterns';
 
+  /**
+   * The app root.
+   *
+   * @var string
+   */
+  protected $root;
+
+  /**
+   * Typed data manager service.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManager
+   */
+  protected $typedDataManager;
+
+  /**
+   * UiPatternsManager constructor.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, $root, TypedDataManager $typed_data_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->root = $root;
+    $this->typedDataManager = $typed_data_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('app.root'),
+      $container->get('typed_data_manager')
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -151,4 +190,59 @@ abstract class UiPatternBase extends PluginBase implements UiPatternInterface {
     return $value;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLibraryDefinitions() {
+    // @codingStandardsIgnoreStart
+    $libraries = [];
+    $definition = $this->getPluginDefinition();
+
+    // Get only locally defined libraries.
+    $items = array_filter($definition['libraries'], function ($library) {
+      return is_array($library);
+    });
+
+    // Attach pattern base path to assets.
+    if (!empty($definition['base path'])) {
+      $base_path = str_replace($this->root, '', $definition['base path']);
+      $this->processLibraries($items, $base_path);
+    }
+
+    // Produce final libraries array.
+    $id = $definition['id'];
+    array_walk($items, function ($value) use (&$libraries, $id) {
+      $libraries[$id . '.' . key($value)] = reset($value);
+    });
+
+    // @codingStandardsIgnoreEnd
+    return $libraries;
+  }
+
+  /**
+   * Process libraries.
+   *
+   * @param array $libraries
+   *    Libraries array.
+   * @param string $base_path
+   *    Pattern base path.
+   * @param string $parent
+   *    Item parent set in previous recursive iteration, if any.
+   */
+  protected function processLibraries(array &$libraries, $base_path, $parent = '') {
+    $parents = ['js', 'base', 'layout', 'component', 'state', 'theme'];
+    $_libraries = $libraries;
+    foreach ($_libraries as $name => $values) {
+      $is_asset = in_array($parent, $parents, TRUE);
+      $is_external = isset($values['type']) && $values['type'] == 'external';
+      if ($is_asset && !$is_external) {
+        $libraries[$base_path . DIRECTORY_SEPARATOR . $name] = $values;
+        unset($libraries[$name]);
+      }
+      elseif (!$is_asset) {
+        $this->processLibraries($libraries[$name], $base_path, $name);
+      }
+    }
+  }
+
 }
diff --git a/src/UiPatternInterface.php b/src/UiPatternInterface.php
index 0839b8293..db4ea8c97 100644
--- a/src/UiPatternInterface.php
+++ b/src/UiPatternInterface.php
@@ -136,4 +136,25 @@ interface UiPatternInterface {
    */
   public function getUse();
 
+  /**
+   * Build and return Drupal theme implementation for current pattern.
+   *
+   * @return array
+   *    Theme implementation.
+   *
+   * @see ui_patterns_theme()
+   */
+  public function getThemeImplementation();
+
+  /**
+   * Get library definitions for current pattern.
+   *
+   * @return array
+   *   List of library definitions.
+   *
+   * @see hook_library_info_build()
+   * @see ui_patterns_library_info_build()
+   */
+  public function getLibraryDefinitions();
+
 }
diff --git a/src/UiPatternsManager.php b/src/UiPatternsManager.php
index 40b7168f9..593e9a82b 100644
--- a/src/UiPatternsManager.php
+++ b/src/UiPatternsManager.php
@@ -7,7 +7,6 @@ use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
-use Drupal\Core\TypedData\TypedDataManager;
 
 /**
  * Provides the default ui_patterns manager.
@@ -16,13 +15,6 @@ class UiPatternsManager extends DefaultPluginManager implements UiPatternsManage
 
   use StringTranslationTrait;
 
-  /**
-   * The app root.
-   *
-   * @var string
-   */
-  protected $root;
-
   /**
    * The theme handler.
    *
@@ -30,36 +22,23 @@ class UiPatternsManager extends DefaultPluginManager implements UiPatternsManage
    */
   protected $themeHandler;
 
-  /**
-   * Typed data manager service.
-   *
-   * @var \Drupal\Core\TypedData\TypedDataManager
-   */
-  protected $typedDataManager;
-
   /**
    * UiPatternsManager constructor.
    *
    * @param \Traversable $namespaces
    *   An object that implements \Traversable which contains the root paths
    *   keyed by the corresponding namespace to look for plugin implementations.
-   * @param string $root
-   *    Application root directory.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *    Module handler service.
    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
    *    Theme handler service.
-   * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager
-   *    Typed data manager service.
    * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
    *    Cache backend service.
    */
-  public function __construct(\Traversable $namespaces, $root, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, TypedDataManager $typed_data_manager, CacheBackendInterface $cache_backend) {
+  public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend) {
     parent::__construct('Plugin/UiPatterns/Pattern', $namespaces, $module_handler, 'Drupal\ui_patterns\UiPatternInterface', 'Drupal\ui_patterns\Annotation\UiPattern');
-    $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->themeHandler = $theme_handler;
-    $this->typedDataManager = $typed_data_manager;
     $this->alterInfo('ui_patterns_info');
     $this->setCacheBackend($cache_backend, 'ui_patterns', ['ui_patterns']);
   }
@@ -68,10 +47,22 @@ class UiPatternsManager extends DefaultPluginManager implements UiPatternsManage
    * {@inheritdoc}
    */
   public function getPattern($id) {
-    // @todo should we cache pattern object instances?
+    // @todo should we statically cache this?
     return $this->getFactory()->createInstance($id);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getPatterns() {
+    // @todo should we statically cache this?
+    $patterns = [];
+    foreach ($this->getDefinitions() as $definition) {
+      $patterns[] = $this->getPattern($definition['id']);
+    }
+    return $patterns;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -99,62 +90,6 @@ class UiPatternsManager extends DefaultPluginManager implements UiPatternsManage
     }, $this->getDefinitions());
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function hookTheme() {
-    $items = [];
-
-    foreach ($this->getDefinitions() as $definition) {
-      $item = [];
-      $hook = $definition['theme hook'];
-
-      foreach ($definition['fields'] as $field) {
-        $item['variables'][$field['name']] = NULL;
-      }
-      $item['variables']['attributes'] = [];
-      $item['variables']['context'] = [];
-      $item['variables']['use'] = '';
-
-      $item += $this->processUseProperty($definition);
-      $item += $this->processCustomThemeHookProperty($definition);
-      $item += $this->processTemplateProperty($definition);
-      $items[$hook] = $item;
-    }
-
-    return $items;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hookLibraryInfoBuild() {
-    // @codingStandardsIgnoreStart
-    $libraries = [];
-    foreach ($this->getDefinitions() as $definition) {
-
-      // Get only locally defined libraries.
-      $items = array_filter($definition['libraries'], function ($library) {
-        return is_array($library);
-      });
-
-      // Attach pattern base path to assets.
-      if (!empty($definition['base path'])) {
-        $base_path = str_replace($this->root, '', $definition['base path']);
-        $this->processLibraries($items, $base_path);
-      }
-
-      // Produce final libraries array.
-      $id = $definition['id'];
-      array_walk($items, function ($value) use (&$libraries, $id) {
-        $libraries[$id . '.' . key($value)] = reset($value);
-      });
-    }
-
-    // @codingStandardsIgnoreEnd
-    return $libraries;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -165,94 +100,6 @@ class UiPatternsManager extends DefaultPluginManager implements UiPatternsManage
     return !empty($definitions);
   }
 
-  /**
-   * Process libraries.
-   *
-   * @param array $libraries
-   *    Libraries array.
-   * @param string $base_path
-   *    Pattern base path.
-   * @param string $parent
-   *    Item parent set in previous recursive iteration, if any.
-   */
-  protected function processLibraries(array &$libraries, $base_path, $parent = '') {
-    $parents = ['js', 'base', 'layout', 'component', 'state', 'theme'];
-    $_libraries = $libraries;
-    foreach ($_libraries as $name => $values) {
-      $is_asset = in_array($parent, $parents, TRUE);
-      $is_external = isset($values['type']) && $values['type'] == 'external';
-      if ($is_asset && !$is_external) {
-        $libraries[$base_path . DIRECTORY_SEPARATOR . $name] = $values;
-        unset($libraries[$name]);
-      }
-      elseif (!$is_asset) {
-        $this->processLibraries($libraries[$name], $base_path, $name);
-      }
-    }
-  }
-
-  /**
-   * Process 'custom hook theme' definition property.
-   *
-   * @param array $definition
-   *    Pattern definition array.
-   *
-   * @return array
-   *    Processed hook definition portion.
-   *
-   * @see UiPatternsManager::hookTheme()
-   */
-  protected function processCustomThemeHookProperty(array $definition) {
-    /** @var \Drupal\Core\Extension\Extension $module */
-    $return = [];
-    if (!$definition['custom theme hook'] && $this->moduleHandler->moduleExists($definition['provider'])) {
-      $module = $this->moduleHandler->getModule($definition['provider']);
-      $return['path'] = $module->getPath() . '/templates';
-    }
-    return $return;
-  }
-
-  /**
-   * Process 'template' definition property.
-   *
-   * @param array $definition
-   *    Pattern definition array.
-   *
-   * @return array
-   *    Processed hook definition portion.
-   *
-   * @see UiPatternsManager::hookTheme()
-   */
-  protected function processTemplateProperty(array $definition) {
-    $return = [];
-    if (isset($definition['template'])) {
-      $return = ['template' => $definition['template']];
-    }
-    return $return;
-  }
-
-  /**
-   * Process 'use' definition property.
-   *
-   * @param array $definition
-   *    Pattern definition array.
-   *
-   * @return array
-   *    Processed hook definition portion.
-   *
-   * @see UiPatternsManager::hookTheme()
-   */
-  protected function processUseProperty(array $definition) {
-    $return = [];
-    if (!empty($definition['use'])) {
-      $return = [
-        'path' => $this->moduleHandler->getModule('ui_patterns')->getPath() . '/templates',
-        'template' => 'patterns-use-wrapper',
-      ];
-    }
-    return $return;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/UiPatternsManagerInterface.php b/src/UiPatternsManagerInterface.php
index c95ab5517..d23235608 100644
--- a/src/UiPatternsManagerInterface.php
+++ b/src/UiPatternsManagerInterface.php
@@ -21,33 +21,20 @@ interface UiPatternsManagerInterface extends PluginManagerInterface {
   public function getPattern($id);
 
   /**
-   * Return list of available patterns to be used as select options.
-   *
-   * @return array
-   *    List of available patterns.
-   */
-  public function getPatternsOptions();
-
-  /**
-   * Build and return pattern theme definitions.
-   *
-   * @return array
-   *    Theme definitions.
+   * Get a fully instantiated list of pattern objects.
    *
-   * @see ui_patterns_theme()
+   * @return \Drupal\ui_patterns\UiPatternInterface[]
+   *    List of pattern object instances.
    */
-  public function hookTheme();
+  public function getPatterns();
 
   /**
-   * Get patterns library info.
+   * Return list of available patterns to be used as select options.
    *
    * @return array
-   *   Array of libraries as expected by hook_library_info_build().
-   *
-   * @see hook_library_info_build()
-   * @see ui_patterns_library_info_build()
+   *    List of available patterns.
    */
-  public function hookLibraryInfoBuild();
+  public function getPatternsOptions();
 
   /**
    * Check whereas the given theme hook is an actual pattern hook.
diff --git a/tests/features/overview.feature b/tests/features/overview.feature
index 57413d4a6..d3f803128 100644
--- a/tests/features/overview.feature
+++ b/tests/features/overview.feature
@@ -65,7 +65,6 @@ Feature: Overview
 
     Given I am logged in as a user with the "access patterns page" permission
     And I am on "/patterns/media"
-
     Then the response should contain "/ui_patterns_test_theme/templates/patterns/media/css/media1.css"
     And the response should contain "/ui_patterns_test_theme/templates/patterns/media/css/media2.css"
     And the response should contain "/ui_patterns_test_theme/templates/patterns/media/js/media1.js"
diff --git a/tests/src/Kernel/UiPatternBaseTest.php b/tests/src/Kernel/UiPatternBaseTest.php
index 945aa009b..8091b3d2d 100644
--- a/tests/src/Kernel/UiPatternBaseTest.php
+++ b/tests/src/Kernel/UiPatternBaseTest.php
@@ -5,6 +5,7 @@ namespace Drupal\Tests\ui_patterns\Kernel;
 use function bovigo\assert\assert;
 use function bovigo\assert\predicate\isTrue;
 use function bovigo\assert\predicate\equals;
+use Drupal\Component\Serialization\Yaml;
 use Drupal\ui_patterns\UiPatternBase;
 
 /**
@@ -34,8 +35,7 @@ class UiPatternBaseTest extends AbstractUiPatternsTest {
 
     foreach ($definitions as $definition) {
       /** @var \Drupal\ui_patterns\UiPatternBase $pattern */
-      $arguments = [[], 'plugin_id', $definition];
-      $pattern = $this->getMockForAbstractClass(UiPatternBase::class, $arguments);
+      $pattern = $this->getUiPatternBaseMock($definition);
 
       assert($pattern->getId(), equals($definition['id']));
       assert($pattern->getLabel(), equals($definition['label']));
@@ -55,4 +55,39 @@ class UiPatternBaseTest extends AbstractUiPatternsTest {
     }
   }
 
+  /**
+   * Test hookLibraryInfoBuild.
+   *
+   * @covers ::hookLibraryInfoBuild
+   */
+  public function testHookLibraryInfoBuild() {
+    $items = Yaml::decode(file_get_contents(dirname(__FILE__) . '/../fixtures/libraries.yml'));
+
+    foreach ($items as $item) {
+      $pattern = $this->getUiPatternBaseMock($item['actual']);
+
+      /** @var \Drupal\ui_patterns\UiPatternBase $pattern */
+      $libraries = $pattern->getLibraryDefinitions();
+      assert($libraries, equals($item['expected']));
+    }
+  }
+
+  /**
+   * Get UiPatternBase mock.
+   *
+   * @param array $configuration
+   *    Plugin configuration.
+   * @param array $methods
+   *    List of methods to mock.
+   *
+   * @return \PHPUnit_Framework_MockObject_MockObject
+   *    Mock object.
+   */
+  protected function getUiPatternBaseMock(array $configuration = [], array $methods = []) {
+    $root = \Drupal::service('app.root');
+    $typed_data_manager = \Drupal::service('typed_data_manager');
+    $arguments = [[], 'plugin_id', $configuration, $root, $typed_data_manager];
+    return $this->getMockForAbstractClass(UiPatternBase::class, $arguments, '', TRUE, TRUE, TRUE, $methods);
+  }
+
 }
diff --git a/tests/src/Unit/UiPatternsManagerTest.php b/tests/src/Unit/UiPatternsManagerTest.php
deleted file mode 100644
index 086569360..000000000
--- a/tests/src/Unit/UiPatternsManagerTest.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-namespace Drupal\Tests\ui_patterns\Unit;
-
-use function bovigo\assert\assert;
-use function bovigo\assert\predicate\equals;
-use Drupal\Component\Serialization\Yaml;
-use Drupal\ui_patterns\UiPatternsManager;
-
-/**
- * @coversDefaultClass \Drupal\ui_patterns\UiPatternsManager
- *
- * @group ui_patterns
- */
-class UiPatternsManagerTest extends AbstractUiPatternsTest {
-
-  /**
-   * Test hookLibraryInfoBuild.
-   *
-   * @covers ::hookLibraryInfoBuild
-   */
-  public function testHookLibraryInfoBuild() {
-    $items = Yaml::decode(file_get_contents(dirname(__FILE__) . '/../fixtures/libraries.yml'));
-
-    foreach ($items as $item) {
-      $manager = $this->createPartialMock(UiPatternsManager::class, ['getDefinitions']);
-      $manager->method('getDefinitions')->willReturn([$item['actual']]);
-
-      /** @var \Drupal\ui_patterns\UiPatternsManager $manager */
-      $libraries = $manager->hookLibraryInfoBuild();
-      assert($libraries, equals($item['expected']));
-    }
-  }
-
-}
diff --git a/ui_patterns.module b/ui_patterns.module
index 7c04f1ae0..98e88e727 100644
--- a/ui_patterns.module
+++ b/ui_patterns.module
@@ -11,14 +11,33 @@ use Drupal\ui_patterns\UiPatterns;
  * Implements hook_theme().
  */
 function ui_patterns_theme() {
-  return [
+  /** @var \Drupal\ui_patterns\UiPatternInterface $pattern */
+  $items = [
     'patterns_destination' => [
       'variables' => ['sources' => NULL, 'context' => NULL],
     ],
     'patterns_use_wrapper' => [
       'variables' => ['use' => NULL],
     ],
-  ] + UiPatterns::getManager()->hookTheme();
+  ];
+
+  foreach (UiPatterns::getManager()->getPatterns() as $pattern) {
+    $items += $pattern->getThemeImplementation();
+  }
+  return $items;
+}
+
+/**
+ * Implements hook_library_info_build()
+ */
+function ui_patterns_library_info_build() {
+  /** @var \Drupal\ui_patterns\UiPatternInterface $pattern */
+
+  $definitions = [];
+  foreach (UiPatterns::getManager()->getPatterns() as $pattern) {
+    $definitions += $pattern->getLibraryDefinitions();
+  }
+  return $definitions;
 }
 
 /**
@@ -34,10 +53,3 @@ function ui_patterns_theme_suggestions_alter(array &$suggestions, array $variabl
     \Drupal::moduleHandler()->alter('ui_patterns_destination_suggestions', $suggestions, $variables, $variables['context']);
   }
 }
-
-/**
- * Implements hook_library_info_build()
- */
-function ui_patterns_library_info_build() {
-  return UiPatterns::getManager()->hookLibraryInfoBuild();
-}
diff --git a/ui_patterns.services.yml b/ui_patterns.services.yml
index 1b73bbde4..eee75f4cd 100644
--- a/ui_patterns.services.yml
+++ b/ui_patterns.services.yml
@@ -1,7 +1,7 @@
 services:
   plugin.manager.ui_patterns:
     class: Drupal\ui_patterns\UiPatternsManager
-    arguments: ['@container.namespaces', '@app.root', '@module_handler', '@theme_handler', '@typed_data_manager', '@cache.discovery']
+    arguments: ['@container.namespaces', '@module_handler', '@theme_handler', '@cache.discovery']
   plugin.manager.ui_patterns_source:
     class: Drupal\ui_patterns\Plugin\UiPatternsSourceManager
     parent: default_plugin_manager
-- 
GitLab