diff --git a/config/install/patternkit.settings.yml b/config/install/patternkit.settings.yml
index 70b58c5..accf773 100644
--- a/config/install/patternkit.settings.yml
+++ b/config/install/patternkit.settings.yml
@@ -6,3 +6,4 @@ patternkit_json_editor_js: ""
patternkit_json_editor_theme: bootstrap4
patternkit_libraries: []
patternkit_render_cache: true
+patternkit_pl_host: https://demo.patternlab.io/api
diff --git a/patternkit.links.task.yml b/patternkit.links.task.yml
index 43d50c5..3630f5b 100644
--- a/patternkit.links.task.yml
+++ b/patternkit.links.task.yml
@@ -22,3 +22,7 @@ patternkit.settings.json_settings:
title: 'JSON Pattern Library Settings'
route_name: patternkit.settings.json_settings
base_route: patternkit.settings
+patternkit.settings.rest_settings:
+ title: 'REST Pattern Library Settings'
+ route_name: patternkit.settings.rest_settings
+ base_route: patternkit.settings
diff --git a/patternkit.routing.yml b/patternkit.routing.yml
index b9f1814..0625840 100644
--- a/patternkit.routing.yml
+++ b/patternkit.routing.yml
@@ -55,3 +55,13 @@ patternkit.settings.json_settings:
_admin_route: TRUE
requirements:
_permission: 'access administration pages'
+patternkit.settings.rest_settings:
+ path: '/admin/config/user-interface/patternkit/rest'
+ defaults:
+ _form: '\Drupal\patternkit\Form\PatternLibraryRESTForm'
+ _title: 'Patternkit REST Library settings'
+ _description: 'Configure Patternkit REST Pattern Library Support.'
+ options:
+ _admin_route: TRUE
+ requirements:
+ _permission: 'access administration pages'
diff --git a/patternkit.services.yml b/patternkit.services.yml
index 3b56a04..2d64c16 100644
--- a/patternkit.services.yml
+++ b/patternkit.services.yml
@@ -20,6 +20,9 @@ services:
patternkit.library.discovery.parser.json:
class: Drupal\patternkit\PatternLibraryParser\JSONPatternLibraryParser
arguments: ['@serialization.json', '@app.root', '@module_handler', '@theme.manager']
+ patternkit.library.discovery.parser.rest:
+ class: Drupal\patternkit\PatternLibraryParser\RESTPatternLibraryParser
+ arguments: ['@cache.default', '@http_client', '@config.factory', '@file_system', '@logger.channel.patternkit', '@serialization.json', '@stream_wrapper_manager']
patternkit.library.discovery.parser.twig:
class: Drupal\patternkit\PatternLibraryParser\TwigPatternLibraryParser
arguments: ['@serialization.json', '@app.root', '@module_handler', '@theme.manager']
diff --git a/src/Form/PatternLibraryJSONForm.php b/src/Form/PatternLibraryJSONForm.php
index a6b1aac..015d48b 100644
--- a/src/Form/PatternLibraryJSONForm.php
+++ b/src/Form/PatternLibraryJSONForm.php
@@ -133,4 +133,17 @@ public function getFormId() :string {
return 'patternkit_json_editor_config';
}
+ /**
+ * {@inheritDoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state): void {
+ $this->config(static::SETTINGS)
+ ->set('patternkit_json_editor_theme', $form_state->getValue('patternkit_json_editor_theme'))
+ ->set('patternkit_json_editor_icons', $form_state->getValue('patternkit_json_editor_icons'))
+ ->set('patternkit_json_editor_css', $form_state->getValue('patternkit_json_editor_css'))
+ ->set('patternkit_json_editor_js', $form_state->getValue('patternkit_json_editor_js'))
+ ->save();
+ parent::submitForm($form, $form_state);
+ }
+
}
diff --git a/src/Form/PatternLibraryRESTForm.php b/src/Form/PatternLibraryRESTForm.php
new file mode 100644
index 0000000..f4cb0c2
--- /dev/null
+++ b/src/Form/PatternLibraryRESTForm.php
@@ -0,0 +1,62 @@
+config(static::SETTINGS);
+
+ $form['patternkit_pl_host'] = array(
+ '#type' => 'textfield',
+ '#title' => t('PatternLab Host Web Address'),
+ '#description' => t('Enter the website address of the PatternLab host REST endpoint.'),
+ '#default_value' => $config->get('patternkit_pl_host'),
+ );
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getEditableConfigNames() :array {
+ return [static::SETTINGS];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getFormId() :string {
+ return 'patternkit_rest_editor_config';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state): void {
+ $this->config(static::SETTINGS)
+ ->set('patternkit_pl_host', $form_state->getValue('patternkit_pl_host'))
+ ->save();
+ parent::submitForm($form, $form_state);
+ }
+
+}
diff --git a/src/Form/PatternkitSettingsForm.php b/src/Form/PatternkitSettingsForm.php
index 3d9e683..4fdf879 100644
--- a/src/Form/PatternkitSettingsForm.php
+++ b/src/Form/PatternkitSettingsForm.php
@@ -2,6 +2,7 @@
namespace Drupal\patternkit\Form;
+use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
@@ -130,8 +131,7 @@ public function getFormId() :string {
* {@inheritDoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
- $config = $this->config(static::SETTINGS);
- $config
+ $config = $this->config(static::SETTINGS)
->set('patternkit_libraries', $form_state->getValue('patternkit_libraries'))
->set('patternkit_cache_enabled', $form_state->getValue('patternkit_cache_enabled'))
->set('patternkit_render_cache', $form_state->getValue('patternkit_render_cache'))
diff --git a/src/Loader/PatternLibraryLoader.php b/src/Loader/PatternLibraryLoader.php
index 4641538..f5b01c6 100644
--- a/src/Loader/PatternLibraryLoader.php
+++ b/src/Loader/PatternLibraryLoader.php
@@ -2,13 +2,16 @@
namespace Drupal\patternkit\Loader;
+use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\patternkit\PatternLibraryCollector;
+use Twig\Error\LoaderError;
+use Twig_LoaderInterface;
/**
* Functionality for parsing Twig pattern libraries.
*/
-class PatternLibraryLoader extends \Twig_Loader_Filesystem {
+class PatternLibraryLoader extends \Twig_Loader_Filesystem implements Twig_LoaderInterface {
/**
* Overrides to add paths from pattern libraries.
@@ -21,6 +24,7 @@ class PatternLibraryLoader extends \Twig_Loader_Filesystem {
* Provides library names and paths.
*
* @throws \Twig\Error\LoaderError
+ * Thrown when encountering a cascaded loader error.
*/
public function __construct($paths,
LoggerChannelInterface $logger,
@@ -30,8 +34,10 @@ public function __construct($paths,
try {
$libraries = $pattern_collector->getLibraryDefinitions();
}
- catch (\Exception $exception) {
- $logger->error('Error loading pattern libraries: @message', ['@message' => $exception->getMessage()]);
+ catch (PluginException $exception) {
+ $message = $exception->getMessage();
+ $logger->error('Error loading pattern libraries: @message', ['@message' => $message]);
+ throw new LoaderError($message);
}
foreach ($libraries as $namespace => $library) {
$path = $library['data'];
diff --git a/src/PatternLibraryCollector.php b/src/PatternLibraryCollector.php
index c053a13..28cdd77 100644
--- a/src/PatternLibraryCollector.php
+++ b/src/PatternLibraryCollector.php
@@ -20,6 +20,7 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Cache\CacheCollector;
use Drupal\Core\Lock\LockBackendInterface;
+use function is_array;
/**
* The PatternLibraryCollector caches library information and performs retrieval
@@ -129,7 +130,7 @@ public static function create(ContainerInterface $container): self {
/** @var \Drupal\Core\Lock\LockBackendInterface $lock */
$lock = $container->get('lock');
/** @var \Drupal\Core\Logger\LoggerChannelInterface $logger */
- $logger = $container->get('@logger.channel.default');
+ $logger = $container->get('logger.channel.patternkit');
/** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
$module_handler = $container->get('module_handler');
/** @var string $root */
@@ -210,7 +211,7 @@ public function buildByExtension($extension_type, $extension): array {
$libraries = $this->applyLibrariesOverride($libraries, $extension);
foreach ($libraries as $id => &$library) {
- if (!isset($library['patterns'])) {
+ if (!isset($library['patterns']) || !is_array($library['patterns'])) {
unset($libraries[$id]);
continue;
}
diff --git a/src/PatternLibraryParser/FilePatternLibraryParser.php b/src/PatternLibraryParser/FilePatternLibraryParser.php
index 6dd73bf..93a0156 100644
--- a/src/PatternLibraryParser/FilePatternLibraryParser.php
+++ b/src/PatternLibraryParser/FilePatternLibraryParser.php
@@ -10,6 +10,7 @@
use Drupal\patternkit\PatternEditorConfig;
use Drupal\patternkit\PatternLibraryJSONParserTrait;
use Drupal\patternkit\PatternLibraryParserBase;
+use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
/**
* Parses a File pattern library collection into usable metadata.
@@ -39,6 +40,50 @@ public function __construct(
parent::__construct($root, $module_handler, $theme_manager);
}
+ /**
+ * Returns an array of file components grouped by file basename and extension.
+ *
+ * @param string $path
+ * The fully-qualified path to discover component files.
+ * @param array $filter
+ * An optional filter of file extensions to search for.
+ *
+ * @return array
+ * Array of file components.
+ * [basename][extension] = filename.
+ */
+ public static function discoverComponents($path, array $filter = []): array {
+ $components = [];
+ $rdit = new RecursiveDirectoryIterator($path, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO);
+ /** @var \SplFileInfo $file */
+ foreach (new \RecursiveIteratorIterator($rdit) as $file) {
+ // Skip directories and non-files.
+ if (!$file->isFile()) {
+ continue;
+ }
+ $file_path = $file->getPath();
+
+ // Skip tests folders.
+ if (strpos($file_path, '/tests') !== FALSE) {
+ continue;
+ }
+
+ // Get the file extension for the file.
+ $file_ext = $file->getExtension();
+ if (!in_array(strtolower($file_ext), $filter, TRUE)) {
+ continue;
+ }
+
+ // We use file_basename as a unique key, it is required that the
+ // JSON and twig file share this basename.
+ $file_basename = $file->getBasename('.' . $file_ext);
+
+ // Build an array of all the filenames of interest, keyed by name.
+ $components[$file_basename][$file_ext] = "$file_path/$file_basename.$file_ext";
+ }
+ return $components;
+ }
+
/**
* Fetches all assets for a pattern.
*
diff --git a/src/PatternLibraryParser/RESTPatternLibraryParser.php b/src/PatternLibraryParser/RESTPatternLibraryParser.php
index d864cb3..4d6aa83 100644
--- a/src/PatternLibraryParser/RESTPatternLibraryParser.php
+++ b/src/PatternLibraryParser/RESTPatternLibraryParser.php
@@ -1,40 +1,78 @@
cache = $cache;
$this->client = $client;
+ $this->config = $config_factory->get('patternkit');
$this->fs = $fs;
+ $this->logger = $logger;
+ $this->serializer = $serializer;
+ $this->wrapperManager = $wrapperManager;
}
/**
@@ -53,29 +91,29 @@ public function __construct(ConfigFactoryInterface $config_factory,
public function fetchPatternAssets(Pattern $pattern,
PatternEditorConfig $config) :Pattern {
- $patternkit_host = $this->configFactory->get('patternkit_pl_host');
+ $patternkit_host = $this->config->get('patternkit_pl_host');
$url = $patternkit_host . '/api/render/json';
$result = $this->client->request(
'GET',
$url,
- array(
- 'headers' => array('Content-Type' => 'application/json'),
+ [
+ 'headers' => ['Content-Type' => 'application/json'],
'data' => $config->rawJSON,
'timeout' => 10,
'method' => 'POST',
- )
+ ]
);
// @TODO: Request failure handling.
$body = $result->getBody();
$response = $body->read($body->getSize());
$pk_obj = $this->serializer->deserialize($response, 'object', 'json');
- $subtype = $pattern->subtype;
- $dir = "public://patternkit/$subtype/{$config->instance_id}";
+ $category = $pattern->category;
+ $dir = "public://patternkit/$category/{$config->instance_id}";
if (!$this->fs->prepareDirectory($dir)) {
// @TODO: Failure handling.
- _patternkit_show_error(
+ $this->logger->error(
"Unable to create folder ($dir) to contain the pklugins artifacts."
);
}
@@ -90,12 +128,12 @@ public function fetchPatternAssets(Pattern $pattern,
if ($save_result === FALSE) {
// @TODO: Failure handling.
- _patternkit_show_error(
- "Unable to create static archive of the JSON pklugins artifact for $subtype."
+ $this->logger->error(
+ "Unable to create static archive of the JSON pklugins artifact for $category."
);
}
- $assets = array();
+ $assets = [];
// Normalize the object for easier processing.
if (!empty($pk_obj->assets)) {
@@ -108,7 +146,7 @@ public function fetchPatternAssets(Pattern $pattern,
$pk_obj->assets->js->early = $pk_obj->global_assets->js;
$pk_obj->assets->js->deferred = $pk_obj->global_assets->footer_js;
$pk_obj->assets->css->list = $pk_obj->global_assets->css;
- $pk_obj->assets->css->shared = array();
+ $pk_obj->assets->css->shared = [];
}
if (!empty($pk_obj->assets)) {
@@ -142,8 +180,45 @@ public function fetchPatternAssets(Pattern $pattern,
continue;
}
- $save_result = _patternkit_fetch_single_asset($dir, $pk_obj->path, $asset_url);
- $pk_obj->raw_assets[$asset_url] = $save_result;
+ // Leading double slashes eliminated above, leaving only relatives.
+ $path = "$dir/" . dirname(trim($asset_url, '.'));
+ $filename = basename(trim($asset_url, '.'));
+
+ if (!$this->fs->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY)) {
+ $this->logger->error(
+ "Unable to create folder ($path) to contain the pklugins artifacts."
+ );
+ }
+
+ // Generate the full path to the source asset.
+ $full_asset_url = $patternkit_host . preg_replace('/^\\.\\//', $pattern->path . '/', $asset_url);
+
+ // What follows is for store/cache model.
+ $asset_src = $this->client->request('GET', $full_asset_url);
+ // May consider some way of doing this
+ // $dest_path = "$dir/" . md5($asset_src->data) . ".$asset_type";.
+ $dest_path = $path . $filename;
+
+ $save_result = $this->fs->saveData(
+ $asset_src->getBody()->getContents(),
+ $dest_path,
+ FileSystemInterface::EXISTS_REPLACE
+ );
+
+ if ($save_result === FALSE) {
+ // @todo: handle failure.
+ continue;
+ }
+
+ // Convert stream wrapper to relative path, if appropriate.
+ $scheme = StreamWrapperManagerInterface::getScheme($save_result);
+ if ($scheme && $this->wrapperManager->isValidScheme($scheme)) {
+ $wrapper = $this->wrapperManager->getViaScheme($scheme);
+ $save_result = $wrapper->getDirectoryPath() . "/" . StreamWrapperManagerInterface::getTarget(
+ $save_result
+ );
+ }
+ $pattern->raw_assets[$asset_url] = $save_result;
}
}
@@ -151,11 +226,220 @@ public function fetchPatternAssets(Pattern $pattern,
// differently.
switch ($config->presentation_style) {
case 'webcomponent':
- _patternkit_fetch_webcomponent_assets($subtype, $config, $pk_obj);
+ $url = $patternkit_host . '/api/render/webcomponent';
+ $result = $this->client->request(
+ 'GET',
+ $url,
+ [
+ 'headers' => ['Content-Type' => 'application/json'],
+ 'jsondata' => $config->rawJSON,
+ // 'timeout' => 10,
+ 'method' => 'POST',
+ ]
+ );
+
+ // @todo: Request failure handling.
+
+ // Create the stub object.
+ $pk_obj = (object) [
+ 'PatternkitPattern' => $category,
+ 'attachments' => [],
+ 'body' => 'fragment.html',
+ ];
+
+ $dir = "public://patternkit/$category/{$config->instance_id}";
+ if (!$this->fs->prepareDirectory($dir, $this->fs::CREATE_DIRECTORY)) {
+ \Drupal::messenger()->addMessage(
+ t(
+ 'Unable to create folder or save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ ),
+ \Drupal::messenger()::TYPE_ERROR
+ );
+ $this->logger->error(
+ 'Unable to create folder or save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ );
+ }
+
+ // Fetch the body html artifact.
+ $save_result = $this->fs->saveData(
+ $result->getBody()->getContents(),
+ "$dir/body.html",
+ $this->fs::EXISTS_REPLACE
+ );
+
+ // Convert stream wrapper to relative path, if appropriate.
+ $scheme = $this->wrapperManager::getScheme($save_result);
+ if ($scheme && $this->wrapperManager->isValidScheme($scheme)) {
+ $wrapper = $this->wrapperManager->getViaScheme($scheme);
+ $save_result = $wrapper->getDirectoryPath() . "/" . $this->wrapperManager::getTarget(
+ $save_result
+ );
+ }
+
+ $pk_obj->body = $save_result;
+
+ $pk_obj->attachments['js']['https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.24/webcomponents.min.js'] = [
+ 'type' => 'external',
+ 'scope' => 'header',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+
+ // Add the header link rel import.
+ $pk_obj->attachments['drupal_add_html_head_link'][] = [
+ [
+ 'rel' => 'import',
+ 'href' => $pk_obj->body,
+ ]
+ ];
+
+ if ($save_result === FALSE) {
+ \Drupal::messenger()->addMessage(
+ t(
+ 'Unable to save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ ),
+ \Drupal::messenger()::TYPE_ERROR
+ );
+ \Drupal::logger('patternkit')->error(
+ 'Unable to save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ );
+ // @todo: Do something.
+ }
break;
case 'html':
- _patternkit_fetch_fragment_assets($subtype, $config, $pk_obj);
+ $url = $patternkit_host . '/api/render/html';
+ $result = $this->client->request(
+ 'GET',
+ $url,
+ [
+ 'headers' => ['Content-Type' => 'application/json'],
+ 'data' => $config->rawJSON,
+ // 'timeout' => 10,.
+ 'method' => 'POST',
+ ]
+ );
+
+ // @todo: Request failure handling.
+
+ $pk_obj->pattern = $category;
+
+ $dir = "public://patternkit/$category/{$config->instance_id}";
+ if (!$this->fs->prepareDirectory($dir, $this->fs::CREATE_DIRECTORY)) {
+ \Drupal::messenger()->addMessage(
+ t(
+ 'Unable to create folder or save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ ),
+ \Drupal::messenger()::TYPE_ERROR
+ );
+ \Drupal::logger('patternkit')->error(
+ 'Unable to create folder or save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ );
+ }
+
+ // Fetch the body html artifact.
+ $save_result = $this->fs->saveData(
+ $result->getBody()->getContents(),
+ "$dir/body.html",
+ $this->fs::EXISTS_REPLACE
+ );
+
+ // Convert stream wrapper to relative path, if appropriate.
+ $scheme = $this->wrapperManager::getScheme($save_result);
+ if ($scheme && $this->wrapperManager->isValidScheme($scheme)) {
+ $wrapper = $this->wrapperManager->getViaScheme($scheme);
+ $save_result = $wrapper->getDirectoryPath() . "/" . $this->wrapperManager::getTarget(
+ $save_result
+ );
+ }
+
+ $pk_obj->body = $save_result;
+
+ if ($save_result === FALSE) {
+ \Drupal::messenger()->addMessage(
+ t(
+ 'Unable to save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ ),
+ \Drupal::messenger()::TYPE_ERROR
+ );
+ \Drupal::logger('patternkit')->error(
+ 'Unable to save metadata/assets for plugin @plugin',
+ ['@plugin' => $category]
+ );
+ // @todo: Do something.
+ }
+
+ foreach (['early', 'deferred'] as $stage) {
+ foreach ($pk_obj->assets->js->{$stage} as $asset_fragment) {
+ $path = $pk_obj->raw_assets[$asset_fragment];
+
+ if (strpos($path, 'public://patternkit/') === 0) {
+ $pk_obj->attachments['js'][$path] = [
+ 'type' => 'file',
+ 'scope' => $stage === 'early' ? 'header' : 'footer',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ else {
+ $pk_obj->attachments['js'][$path] = [
+ 'type' => 'external',
+ 'scope' => $stage === 'early' ? 'header' : 'footer',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ }
+ }
+
+ foreach ($pk_obj->assets->css->list as $asset_fragment) {
+ $path = $pk_obj->raw_assets[$asset_fragment];
+
+ if (strpos($path, 'public://patternkit/') === 0) {
+ $pk_obj->attachments['css'][$path] = [
+ 'type' => 'file',
+ 'scope' => 'header',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ else {
+ $pk_obj->attachments['css'][$path] = [
+ 'type' => 'external',
+ 'scope' => 'header',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ }
+
+ foreach ($pk_obj->assets->css->shared as $asset_fragment) {
+ $path = $pk_obj->raw_assets[$asset_fragment->src];
+
+ if (strpos($path, 'public://patternkit/') === 0) {
+ $pk_obj->attachments['css'][$path] = [
+ 'type' => 'file',
+ 'scope' => 'header',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ else {
+ $pk_obj->attachments['css'][$path] = [
+ 'type' => 'external',
+ 'scope' => 'header',
+ 'group' => JS_DEFAULT,
+ 'weight' => 0,
+ ];
+ }
+ }
break;
case 'json':
@@ -199,13 +483,13 @@ public function getTitle() :string {
* The renderable pattern editor.
*/
public function getEditor($subtype = NULL, PatternEditorConfig $config = NULL) {
- $patternkit_host = $this->configFactory->get('patternkit_pl_host');
+ $patternkit_host = $this->config->get('patternkit_pl_host');
$url = $patternkit_host . '/schema/editor/' . substr($subtype, 3);
if ($config !== NULL) {
$url .= !empty($config->lzstring) ? '?data=' . $config->lzstring : '';
}
- // @todo Move to external phptemplate.
+ // @todo Move to external template.
$markup = <<< HTML
+HTML;
+
+ return $markup;
}
/**
* {@inheritDoc}
*/
- public function getMetadata($extension, $path): array {
- // @todo Implement getMetadata() method.
- return [];
+ public function getMetadata($extension, $library, $path): array {
+ $patternkit_host = $this->configFactory->get('patternkit')->get('patternkit_pl_host') ?: 'http://localhost:9001';
+
+ $patterns = \Drupal::httpClient()->request(
+ 'GET',
+ $patternkit_host . '/api/patterns',
+ [
+ 'headers' => array('Content-Type' => 'application/json'),
+ 'timeout' => 10,
+ ]
+ );
+ if ($patterns === NULL
+ || !empty($patterns->error)
+ || (int) $patterns->code !== 200) {
+ \Drupal::logger('patternkit')->error(
+ 'Patternkit failed to load metadata from service (%service_uri): %error',
+ [
+ '%service_uri' => $patternkit_host . '/api/patterns',
+ '%error' => !empty($patterns->error) ? $patterns->error : $patterns->code,
+ ]
+ );
+ return [];
+ }
+ $metadata = (array) $this->serializer::decode($patterns->data);
+ foreach ($metadata as $subtype => $pattern) {
+ $pattern->library = &$this;
+ $metadata[$subtype] = $pattern;
+ }
+ return $metadata;
}
/**