Track Pattern Usage in Content Layouts

Created on 14 June 2023, over 1 year ago
Updated 12 January 2024, 9 months ago

Problem/Motivation

When maintaining content across a site using Patternkit patterns and a design system through it, it can be helpful to know where a pattern is used within content. Sometimes this may be to identify patterns that aren't being used frequently, or to determine how broad the impact of changes to a pattern might be.

Currently, there is no way to easily identify where a pattern is used throughout a site either administratively or programmatically. Even when attempting to update all Patternkit blocks to use the latest version of a pattern through the drush pklu command, every layout and block has to be loaded and iterated through to identify Patternkit blocks and apply changes to them. Having a system to identify and track usage of patterns throughout content could be helpful for both administrators, pattern library maintainers, and eventually related functionality within the module suite.

Proposed resolution

  • Implement new tracking functionality as an experimental submodule to avoid requirement and installation on all sites
  • Implement a new entity type for tracking individual pattern usages
  • Implement a service for identifying nested pattern usages within the content of a pattern
  • Implement entity hooks to record and update detected usages within an entity layout on creation, update, and deletion
  • Build batch processing solution on top of work from 🐛 Bulk Pattern Updates Fail on Large Databases Active to scan and record usages
  • Expose pattern usage records via Views and the new entity type

Install and configuration instructions

See submodule README.md file.

Usage and testing instructions

  1. Create pattern content on Nodes with overridden layouts
  2. Enable the patternkit_usage_tracking module
  3. Run the usage scan Drush command: drush patternkit:usage:scan
  4. As an administrator, view the usage reports at /admin/reports/pattern-usage.
  5. Confirm expected results in listings (see details below).
  6. Edit an existing page to add or remove blocks and expect this change to be reflected in the usage report without rescanning via the drush command.
  7. Create a new page and set block content on the layout. Expect the new results to be reflected in the usage report without rescanning via the drush command.

Expected behaviors

After running a scan with the Drush command and existing patternkit content, an entry for each patternkit block on each page should be listed on the admin reports page at /admin/reports/pattern-usage

Each entry should display the following:

  • The page title
  • A link to the page
  • The name of the used pattern
  • A path to the pattern within the layout
  • The language of the revision containing the pattern entry
  • The node ID of the node layout
  • The revision ID of the node revision

All layout paths should use the following format with the parts defined below:

<section index>.<block uuid>:<top-level pattern name>=><nested pattern name>

  • <section index>: A zero-based index of the top-level sections in the layout. If only one section exists, like a single-column layout, this should be 0.
  • <block uuid>: This is the internal UUID of the patternkit block containing the pattern usage.
    • Ex. 52c818e0-29fa-419a-a221-932b7d9e35aa
  • <top-level pattern name>: This is the asset name of the top-level block's pattern.
    • Ex. @patternkit/atoms/example_ref/src/example_ref
  • <nested pattern name>: The name of a pattern discovered within references inside the content of a top-level pattern. This token is optional, and if not present the preceding => separator will be excluded as well. This should only be listed for entries referencing nested pattern usages.

Patterns containing references to other nested patterns may be displayed as unique usage entries.

  • A nested pattern usage specifically includes the => separator in the layout path
  • A nested pattern usage should only be recorded if it is used within the content of the block

Remaining tasks

  • Code review
  • Testing and feedback

User interface changes

  • New experimental module to enable for usage tracking: Patternkit Usage Tracking
  • New searchable report listing tracked pattern usages for users with the "View site reports" permission
  • New settings page from dependency module: Entity Track Settings
  • New Drush command for scanning all existing content: drush patternkit:usage:scan
  • New "Media Wrapper" example pattern added in the Patternkit Example module demonstrating use of anyOf within a schema to select from multiple sub-patterns

API changes

Patternkit module

These changes are included in the Patternkit module itself, and take effect regardless whether the new patternkit_usage_tracking module is enabled.

  • The Pattern entity's isBundled() method result may not always be trusted since a cached schema may be loaded from the database already bundled. This results in the entity reporting the entity as unbundled despite the schema being bundled. This is not a new change from this issue, but rather a discovery during implementation that's already been present.
  • New PatternkitBlock entity method: getData() which loads a decoded version of the data string value or NULL if no value is set.
  • SchemaRefObserver has a new resetReferences() method which empties the array of detected references from a previous usage.
  • SchemaRefObserver now returns a multi-dimensional string array of content paths for discovery patterns keyed by the pattern asset name.
  • SchemaRefObserver may now be used for schema processing outside of an import context to identify pattern references used within a pattern's content. Note: The new PatternDetector service is the preferred method for accomplishing this instead of using the observer directly.
  • A new PatternDetector service (patternkit.pattern.detector) has been introduces for detecting pattern references within a pattern's content.
  • LayoutHelper::getPatternComponentsFromLayout() now expects a SectionListInterface argument instead of a SectionStorageInterface argument to support more generalized usage.

Patternkit Usage Tracking submodule

These changes are encapsulated within a new experimental submodule: Patternkit Usage Tracking. They will only take effect if this submodule is enabled.

  • A new PatternUsage entity (pattern_usage) is introduced to capture detected pattern usages.
  • A new PatternUsageManager service (pattern_usage.manager) service is introduced to assist as an interface for maintaining pattern usage records.
  • Views integration for the PatternUsage entity and Node references has been implemented.
  • A new batch manager service (pattern_usage.layout_batch_manager) and related plugins have been added to support batch processing on top of the work from 🐛 Bulk Pattern Updates Fail on Large Databases Active

Data model changes

  • New PatternUsage entity type tracking detected pattern usages within layout content
Feature request
Status

Fixed

Version

9.1

Component

Module Core

Created by

🇺🇸United States slucero Arkansas

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Production build 0.71.5 2024