Skip to content

Commit a2e8cf8

Browse files
committed
Adds logging to library parsing
feat(patternkit.services.yml::logger)
1 parent f2d0db9 commit a2e8cf8

11 files changed

+163
-63
lines changed

patternkit.services.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
services:
2+
logger.channel.patternkit:
3+
parent: logger.channel_base
4+
arguments: ['patternkit']
25
patternkit.library.discovery:
36
class: Drupal\patternkit\PatternkitLibraryDiscovery
47
arguments: ['@patternkit.library.discovery.collector']
@@ -18,6 +21,6 @@ services:
1821
# We use '.' instead of '@app.root' as the path for non-namespaced template
1922
# files so that they match the relative paths of templates loaded via the
2023
# theme registry or via Twig namespaces.
21-
arguments: ['.', '@patternkit.library.discovery.collector']
24+
arguments: ['.', '@logger.channel.patternkit', '@patternkit.library.discovery.collector']
2225
tags:
2326
- { name: twig.loader, priority: 100 }

src/Controller/PatternkitController.php

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Drupal\Core\Link;
1010
use Drupal\Core\Url;
1111
use Drupal\patternkit\Pattern;
12+
use Exception;
1213
use Symfony\Component\DependencyInjection\ContainerInterface;
1314
use Symfony\Component\HttpFoundation\JsonResponse;
1415
use Symfony\Component\HttpFoundation\Request;
@@ -30,7 +31,7 @@ class PatternkitController extends ControllerBase {
3031
*
3132
* @var \Drupal\patternkit\PatternkitLibraryDiscoveryInterface
3233
*/
33-
protected $patternLibraryDiscovery;
34+
protected $libraryDiscovery;
3435

3536
/**
3637
* The theme handler.
@@ -44,17 +45,17 @@ class PatternkitController extends ControllerBase {
4445
*
4546
* @param \Drupal\Core\Entity\EntityStorageInterface $patternkit_storage
4647
* The Patternkit storage.
47-
* @param \Drupal\Core\Asset\LibraryDiscoveryInterface $pattern_library_discovery
48+
* @param \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery
4849
* The Pattern Library Collector.
4950
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
5051
* The theme handler.
5152
*/
5253
public function __construct(
5354
EntityStorageInterface $patternkit_storage,
54-
LibraryDiscoveryInterface $pattern_library_discovery,
55+
LibraryDiscoveryInterface $library_discovery,
5556
ThemeHandlerInterface $theme_handler) {
5657
$this->patternkitStorage = $patternkit_storage;
57-
$this->patternLibraryDiscovery = $pattern_library_discovery;
58+
$this->libraryDiscovery = $library_discovery;
5859
$this->themeHandler = $theme_handler;
5960
}
6061

@@ -69,13 +70,13 @@ public function __construct(
6970
public static function create(ContainerInterface $container) {
7071
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */
7172
$entity_manager = $container->get('entity_type.manager');
72-
/** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $pattern_library_discovery */
73-
$pattern_library_discovery = $container->get('patternkit.library.discovery');
74-
/** @var ThemeHandlerInterface $theme_handler */
73+
/** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
74+
$library_discovery = $container->get('patternkit.library.discovery');
75+
/** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
7576
$theme_handler = $container->get('theme_handler');
7677
return new static(
7778
$entity_manager->getStorage('patternkit_block'),
78-
$pattern_library_discovery,
79+
$library_discovery,
7980
$theme_handler
8081
);
8182
}
@@ -88,15 +89,23 @@ public static function create(ContainerInterface $container) {
8889
* added.
8990
*/
9091
public function add(): array {
91-
$types = $this->patternLibraryDiscovery->getAssets();
92+
try {
93+
$types = $this->libraryDiscovery->getAssets();
94+
}
95+
catch (Exception $exception) {
96+
$this->getLogger('patternkit')->error('Error loading pattern library assets: ', ['@message' => $exception->getMessage()]);
97+
return [
98+
'#markup' => $this->t('Error loading pattern library assets - check the log or the format of your libraries.yml.'),
99+
];
100+
}
92101
if (count($types) === 0) {
93102
return [
94103
'#markup' => $this->t('Could not find any patterns to load. Did you add a theme or module that includes a patterns definition in the libraries.yml?'),
95104
];
96105
}
97106
$content['types'] = [];
98107
$query = \Drupal::request()->query->all();
99-
/** @var Pattern $type */
108+
/** @var \Drupal\patternkit\Pattern $type */
100109
foreach ($types as $type) {
101110
$id = $type->getId();
102111
$label = $type->getLabel();
@@ -133,9 +142,9 @@ public function addForm($pattern_id, Request $request): array {
133142
]);
134143
if (($theme = $request->query->get('theme'))
135144
&& array_key_exists($theme, $this->themeHandler->listInfo())) {
136-
// We have navigated to this page from the block library and will keep track
137-
// of the theme for redirecting the user to the configuration page for the
138-
// newly created block in the given theme.
145+
// We have navigated to this page from the block library and will keep
146+
// track of the theme for redirecting the user to the configuration page
147+
// for the newly created block in the given theme.
139148
$block->setTheme($theme);
140149
}
141150
return $this->entityFormBuilder()->getForm($block);
@@ -152,8 +161,14 @@ public function addForm($pattern_id, Request $request): array {
152161
* @return \Symfony\Component\HttpFoundation\JsonResponse
153162
* The schema response.
154163
*/
155-
public function ApiPatternSchema($library, $pattern): JsonResponse {
156-
return new JsonResponse($this->patternLibraryDiscovery->getLibraryAsset("$library.$pattern"));
164+
public function apiPatternSchema($library, $pattern): JsonResponse {
165+
try {
166+
$response = $this->libraryDiscovery->getLibraryAsset("$library.$pattern");
167+
}
168+
catch (Exception $exception) {
169+
$response = ['error' => $exception->getMessage()];
170+
}
171+
return new JsonResponse($response);
157172
}
158173

159174
/**

src/Form/PatternkitSettingsForm.php

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Drupal\Core\Form\ConfigFormBase;
77
use Drupal\Core\Form\FormStateInterface;
88
use Drupal\patternkit\PatternkitLibraryDiscoveryInterface;
9+
use Exception;
910
use Symfony\Component\DependencyInjection\ContainerInterface;
1011

1112
class PatternkitSettingsForm extends ConfigFormBase {
@@ -14,10 +15,10 @@ class PatternkitSettingsForm extends ConfigFormBase {
1415
public const SETTINGS = 'patternkit.settings';
1516

1617
/** @var \Drupal\patternkit\PatternkitLibraryDiscoveryInterface */
17-
protected $patternLibraryDiscovery;
18+
protected $libraryDiscovery;
1819

1920
public function __construct(ConfigFactoryInterface $config_factory, PatternkitLibraryDiscoveryInterface $pattern_discovery) {
20-
$this->patternLibraryDiscovery = $pattern_discovery;
21+
$this->libraryDiscovery = $pattern_discovery;
2122
parent::__construct($config_factory);
2223
}
2324

@@ -34,7 +35,16 @@ public static function create(ContainerInterface $container) {
3435
*/
3536
public function buildForm(array $form, FormStateInterface $form_state) :array {
3637
$config = $this->config(static::SETTINGS);
37-
$libraries = $this->patternLibraryDiscovery->getLibraries();
38+
try {
39+
$libraries = $this->libraryDiscovery->getLibraries();
40+
}
41+
catch (Exception $exception) {
42+
$this->getLogger('patternkit')->error('Unable to load Patternkit libraries list: @message', ['@message' => $exception->getMessage()]);
43+
\Drupal::messenger()->addMessage(t('Unable to load Patternkit libraries list. Check the logs for more information.'), 'error');
44+
return [
45+
'#markup' => $this->t('Settings are unavailable when Pattern libraries fail to load to prevent config errors.'),
46+
];
47+
}
3848
$library_options = array();
3949
$library_values = array();
4050
foreach ($libraries as $lib_title => $library) {
@@ -98,13 +108,11 @@ public function submitForm(array &$form, FormStateInterface $form_state): void {
98108
$config = $this->config(static::SETTINGS);
99109
if ($form_state['values']['patternkit_cache_enabled']
100110
&& !$config->get('patternkit_cache_enabled')) {
101-
$libraries = $this->patternLibraryDiscovery->getLibraries();
102-
foreach ($libraries as $library) {
103-
$library->getCachedMetadata(NULL, TRUE);
104-
}
111+
$this->libraryDiscovery->clearCachedDefinitions();
105112
}
106-
107-
$this->messenger()->addStatus($this->t('Rebuilt Patternkit Library Cache.'));
113+
$libraries = $this->libraryDiscovery->getLibraries();
114+
$count = count($libraries);
115+
$this->messenger()->addStatus($this->t('Rebuilt Patternkit Library Cache with @count libraries.', ['@count' => $count]));
108116
parent::submitForm($form, $form_state);
109117
}
110118

src/Loader/PatternLibraryLoader.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
namespace Drupal\patternkit\Loader;
44

5-
use Drupal\Component\Plugin\Exception\PluginException;
5+
use Drupal\Core\Logger\LoggerChannelInterface;
66
use Drupal\patternkit\PatternLibraryCollector;
7+
use Exception;
78

89
/**
910
* Functionality for parsing Twig pattern libraries.
@@ -15,19 +16,23 @@ class PatternLibraryLoader extends \Twig_Loader_Filesystem {
1516
*
1617
* @param string|array $paths
1718
* Paths to pass to the Filesystem loader.
19+
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger
20+
* Logs to the patternkit channel.
1821
* @param \Drupal\patternkit\PatternLibraryCollector $pattern_collector
1922
* Provides library names and paths.
23+
*
24+
* @throws \Twig\Error\LoaderError
2025
*/
2126
public function __construct($paths,
27+
LoggerChannelInterface $logger,
2228
PatternLibraryCollector $pattern_collector) {
2329
parent::__construct($paths);
2430
$libraries = [];
2531
try {
2632
$libraries = $pattern_collector->getLibraryDefinitions();
2733
}
28-
catch (PluginException $exception) {
29-
// Do not block rendering if libraries do not load.
30-
// @todo Add logging service and log.
34+
catch (Exception $exception) {
35+
$logger->error('Error loading pattern libraries: @message', ['@message' => $exception->getMessage()]);
3136
}
3237
foreach ($libraries as $namespace => $library) {
3338
$path = $library['data'];

src/PatternLibraryCollector.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,17 @@ public static function create(ContainerInterface $container): self {
146146
*/
147147
public function getLibraryDefinitions(): array {
148148
$config = $this->configFactory->get(PatternkitSettingsForm::SETTINGS);
149-
$patternkit_cache_enabled = $config->get('patternkit_cache_enabled');
149+
$cache_enabled = $config->get('patternkit_cache_enabled');
150150
// If cache is enabled, attempt to load from cache.
151-
if ($patternkit_cache_enabled
151+
if ($cache_enabled
152152
&& ($cache = $this->cache->get(static::PERSISTENT_CACHE_ID))) {
153153
$cached_metadata = $cache->data;
154154
}
155155
else {
156156
$cached_metadata = $this->getLibraryMetadata();
157157
// Cache the data so that we don't have to build it again.
158158
// (if cache enabled, otherwise just a slow, redundant memcache set).
159-
if ($patternkit_cache_enabled === TRUE) {
159+
if ($cache_enabled === TRUE) {
160160
// Explicit copy of the data into cache_set to avoid implicit copy.
161161
$this->cache->set(static::PERSISTENT_CACHE_ID,
162162
$cached_metadata);
@@ -294,10 +294,13 @@ public function buildByExtension($extension_type, $extension): array {
294294

295295
/**
296296
* Returns a specific library by name, collected from all extensions.
297+
*
297298
* @param string $name
298299
* The name of the library, registered by libraries.yml.
300+
*
299301
* @return array|null
300302
* The pattern library metadata.
303+
*
301304
* @throws \Drupal\Component\Plugin\Exception\PluginException
302305
*/
303306
public function getLibraryByName($name): ?array {
@@ -394,6 +397,8 @@ protected function applyLibrariesOverride($libraries, $extension): array {
394397
* When a circular reference is detected.
395398
* @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
396399
* When the service is not defined.
400+
* @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
401+
* Thrown if an invalid library path was passed to the parser.
397402
*/
398403
protected function getLibraryMetadata(): array {
399404
$container = \Drupal::getContainer();

src/PatternLibraryParser/TwigPatternLibraryParser.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
namespace Drupal\patternkit\PatternLibraryParser;
44

55
use Drupal\Component\Serialization\SerializationInterface;
6+
use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
67
use Drupal\Core\Extension\ModuleHandlerInterface;
78
use Drupal\Core\Theme\ThemeManagerInterface;
89
use Drupal\patternkit\Pattern;
910
use Drupal\patternkit\PatternEditorConfig;
1011
use Drupal\patternkit\PatternLibraryParserBase;
12+
use function dump;
13+
use function file_exists;
14+
use function get_call_stack;
15+
use function kint_trace;
1116
use function strlen;
1217
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
1318

@@ -115,16 +120,19 @@ public function fetchPatternAssets(Pattern $pattern,
115120
* An array of parsed library data.
116121
*
117122
* @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
118-
* Thrown when a parser exception got thrown.
123+
* Thrown when a parser exception was thrown.
119124
*/
120125
public function parseLibraryInfo($library, $path, array $library_data = []): array {
121-
$it = new RecursiveDirectoryIterator($path, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO);
126+
if (!file_exists($path)) {
127+
throw new InvalidLibraryFileException("Path $path does not exist.");
128+
}
129+
$rdit = new RecursiveDirectoryIterator($path, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO);
122130
$filter = ['json', 'twig'];
123131
$metadata = [];
124132
$components = [];
125133

126134
/** @var \SplFileInfo $file */
127-
foreach (new \RecursiveIteratorIterator($it) as $file) {
135+
foreach (new \RecursiveIteratorIterator($rdit) as $file) {
128136
// Skip directories and non-files.
129137
if (!$file->isFile()) {
130138
continue;
@@ -153,7 +161,7 @@ public function parseLibraryInfo($library, $path, array $library_data = []): arr
153161
foreach ($components as $name => $data) {
154162
// If the component has a json file, create the pattern from it.
155163
if (!empty($data['json']) && $file_contents = file_get_contents($data['json'])) {
156-
$pattern = $this->createPattern($name, $this->serializer::decode($file_contents) + $library_data);
164+
$pattern = $this->createPattern($name, (array) $this->serializer::decode($file_contents) + $library_data);
157165
$pattern->name = $name;
158166
// URL is redundant for the twig based components, so we use it to
159167
// store namespace.
@@ -164,7 +172,7 @@ public function parseLibraryInfo($library, $path, array $library_data = []): arr
164172
else {
165173
// Create the pattern from defaults.
166174
$pattern = $this->createPattern($name,
167-
(object) [
175+
[
168176
'$schema' => 'http =>//json-schema.org/draft-04/schema#',
169177
'category' => 'atom',
170178
'title' => $name,

src/PatternkitLibraryDiscovery.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
use Drupal\Core\Asset\LibraryDiscovery;
66

77
/**
8-
* The PatternkitLibraryDiscovery is meant to be an enhancement to Drupal Core
8+
* Enhances core library handling.
9+
*
10+
* PatternkitLibraryDiscovery is meant to be an enhancement to Drupal Core
911
* Library handling that allows for arbitrary libraries and loading via plugins.
1012
*
1113
* The existing library infrastructure is likely overcomplicated and could be
@@ -22,7 +24,11 @@
2224
*/
2325
class PatternkitLibraryDiscovery extends LibraryDiscovery implements PatternkitLibraryDiscoveryInterface {
2426

25-
/** @var \Drupal\patternkit\PatternLibraryCollector */
27+
/**
28+
* Collects libraries in a cache-able manner and is destructible.
29+
*
30+
* @var \Drupal\patternkit\PatternLibraryCollector
31+
*/
2632
protected $collector;
2733

2834
/**

src/PatternkitLibraryDiscoveryInterface.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@
44

55
use Drupal\Core\Asset\LibraryDiscoveryInterface;
66

7+
/**
8+
* Allows for implementations of a Pattern Library Discovery service.
9+
*/
710
interface PatternkitLibraryDiscoveryInterface extends LibraryDiscoveryInterface {
811

912
/**
1013
* Returns an array of library assets keyed by library and file.
1114
*
12-
* @return array
15+
* @return \Drupal\patternkit\Pattern[]
1316
* An array of library assets.
17+
*
18+
* @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
19+
* @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
1420
*/
1521
public function getAssets(): array;
1622

@@ -23,12 +29,20 @@ public function getAssets(): array;
2329
* @param string $key
2430
* The asset key.
2531
*
26-
* @return mixed
32+
* @return mixed|null
33+
* The specific asset requested or NULL if not found.
34+
*
35+
* @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
36+
* @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
2737
*/
2838
public function getLibraryAsset($key);
2939

3040
/**
31-
* @return \Drupal\patternkit\Pattern[]
41+
* Returns an array of all libraries.
42+
*
43+
* @return array
44+
* All libraries as definitions, keyed by library name.
3245
*/
3346
public function getLibraries(): array;
47+
3448
}

0 commit comments

Comments
 (0)