Problem/Motivation
The Drush command patternkit:libUpdate updates existing patterns when their schema and/or template changes. We need to be able to run this updater outside of Drush (e.g., in hook_update_N()).
Proposed resolution
Split the main logic of Patternkit's patternkit:libUpdate Drush command into a Drupal service, so that other systems can call them.
Release notes snippet
patternkit:devUpdate Drush Command Removed
The existing drush patternkit:devUpdate command has been removed since it is no longer relevant to active updates of the module and should no longer be in use.
patternkit:libUpdate Drush Command Filtering Now Available
The functionality of the existing drush patternkit:libUpdate command has been split into a pair of new services for improved accessibility to other use within a Drupal site. The commands options have also been revised to offer improved filtering options. Previously, the command excepted a library name intended to filter what patterns might be updated, but unfortunately this value was ignored. Now the command optionally accepts and uses a library name for filtering which patterns should be updated, but it also accepts a new --filter option allowing for limitation of what entity types, bundles, and display modes should be iterated through and updated.
❯ drush help patternkit:libUpdate
Update all patterns in a library.
Examples:
drush pklu @patternkit Update all @patternkit library patterns in all blocks and layouts.
drush pklu --filter=node.article Update all patterns on the Node Article content type and overrides.
Arguments:
[library_name] (optional) The name of a library to limit updates to.
Options:
--filter=FILTER A string concatenation of entity type, bundle, and display mode for updates to be limited to.
Example: 'node.article.default'. Fewer items may also be provided to filter. For example, only an
entity and a bundle may be provided ('node.article') or just an entity type ('node').
Aliases: pklu, patternkit-lib-update
New Service: patternkit.helper.update
A new UpdateHelper service has been added encapsulating much of the functionality that was baked into the previous iteration of the patternkit:libUpdate command. The functionality of the previous iteration of the command has been broken down and implemented on this service as a handful of public methods intended to be versatile and helpful for working with and updating Patternkit components. This service also serves as the entryway to automating the update process for pattern components throughout a site from an update hook, for example.
/**
* Update all the patterns.
*/
function mymodule_update_9001(&$sandbox) {
/** @var \Drupal\patternkit\UpdateHelper $update_helper */
$update_helper = \Drupal::service('patternkit.helper.update');
[$blocks, $layouts] = $update_helper->updateAllPatternComponents();
return t('Updated @blocks blocks and @layouts layouts', ['@blocks' => $blocks, '@layouts' => $layouts]);
}
It's also worth noting, the updateAllPatternComponents() method accepts a $filter argument allowing programmatic usage of all the same filter options exposed by the Drush command. An example update hook to only update patternkit patterns on the Article content type might look like this:
/**
* Update @patternkit patterns on Article Nodes.
*/
function mymodule_update_9001(&$sandbox) {
/** @var \Drupal\patternkit\UpdateHelper $update_helper */
$update_helper = \Drupal::service('patternkit.helper.update');
$filter = [
'library' => 'patternkit',
'entity_type' => 'node',
'bundle' => 'article',
];
[$blocks, $layouts] = $update_helper->updateAllPatternComponents($filter);
return t('Updated @blocks blocks and @layouts layouts', ['@blocks' => $blocks, '@layouts' => $layouts]);
}
New Service: patternkit.helper.layout
A new LayoutHelper service has also been added to assist with management of Patternkit components placed within layout configurations. Much like the methods on the UpdateHelper service, the methods on the LayoutHelper service are intended to be flexible for usage by other code.
By default, the updateAllPatternComponents() method on the UpdateHelper service will automatically use the LayoutHelper service to also update Layout Builder components if Layout Builder is enabled, so no additional usage of the service is required for that scenario. If, however, one needs to retrieve all of the Patternkit components within a layout or apply a callback function to all the components within a layout, there are helpful methods available on the service to do those tasks.
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | extract-libUpdate-to-a-service-3284744-4.patch | 24 KB | krisahil |
Issue fork patternkit-3284744
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
krisahil commentedClosing this issue, because we can already call the Drush command from an update hook. See this example from
patternkit_update_8001():Comment #3
sluceroLet's reopen this issue for follow-up rather than planning to run commands from a Drush context in update hooks.
Comment #4
krisahil commentedHere's a patch that refactors the
patternkit:libUpdatecommand into a service. I think next step would be moving thepatternkit:devUpdatecommand into a service (or removing it if it's no longer necessary).Comment #5
sluceroComment #6
sluceroI just uploaded a new branch with some work I've done locally for breaking up the Drush operations into a pair of new services: 3284744-refactor-drush-update-commands. The aim here is to make these operations accessible outside of just Drush, and ideally provide access to some reusable methods that might prove helpful for different scenarios.
This still needs further testing and automated tests written for it, but I'm getting it off of my local so others can see it and offer feedback as well.
Comment #8
krisahil commented@slucero, I left a few code-level comments on the MR, but looks good overall. Also, reading this code helped me understand the pattern updater Drush command a lot more than the previous code.
I functionally tested by first running
drush pklu, which ran as expected.Second, I added an update hook to manually run the update helper service, which also worked as expected (BTW, is this the expected way to run this code?) :
Thanks for your work on this!
Comment #9
slucero@krisahil, thank you for the testing and feedback!
Did these get saved? I'm not seeing them on the MR at all.
Thanks for letting me know! I too had a lot of trouble following what the original code was doing, so hearing that it's actually easier to understand now is great validation and much appreciated!
Your example update hook looks good to me and will be good to include in documentation for the update. The only other element not represented there would be the use of optional filters if only patterns in a specific library should be updated or only layouts on a specific entity type/bundle/display should be targeted.
Comment #10
sluceroThanks for getting those comments posted, @krisahil. I've gone through and added some replies to each.
For when I continue work on this issue, I had another question for the issue overall:
* Is the `drush patternkit:devUpdate` command still needed at all?
Comment #11
sluceroI've posted some additional changes to add unit tests covering the new services and removing the
drush patternkit:devUdpatecommand since it seems to be outdated and unlikely to still be used. The alternative to removing it would be to refactor it into the same pattern as the libUpdate command has been changed into, but some of the changes (like the example below) seem outdated and no longer relevant for maintenance.With the test coverage added, I've opened up the MR for review and testing. I'm also updating the issue description to capture the changes more clearly.
Comment #12
jordanpagewhite commentedI believe that "excepted" should be "accepted" here, right?
Comment #14
sluceroComment #16
sluceroMerged for release in beta 6.