Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ codebase now uses PHP 8.4-only syntax where it improves readability.

`drush emulsify [theme_name]`

`drush emulsify_tools:repair-favicon-config`

`drush emulsify_tools:repair-favicon-config [theme_machine_name]`

### Twig Namespaces

Emulsify themes can register Symfony-style Twig namespaces in their `.info.yml`
Expand Down Expand Up @@ -140,6 +144,47 @@ This adds the ability to do a `switch/case` function from within Twig templates.

Note that the `switch`, `endswitch`, and `case` tags are required and the `default` is optional.

## Updating 6.x to 7.x

Upgrading from Emulsify 6.x to 7.x introduces a new generated favicon workflow.
Instead of relying only on legacy theme-level favicon settings, Emulsify 7.x
stores a portable SVG source and generated package metadata in theme settings so
favicon packages can be regenerated consistently across environments.

### What changes

- Active theme settings gain new favicon keys such as `favicon_source_svg`,
`favicon_source_filename`, platform-specific color and padding settings, and
generated package metadata fields like `favicon_package_hash`,
`favicon_package_path`, and `favicon_package_generated_at`.
- Installed Emulsify-based themes can be migrated in place by running Drupal
database updates. This module provides a post update that backfills missing
favicon keys in active `<theme>.settings` config and, when possible, stores a
sanitized portable SVG source from the existing managed favicon file.
- Older generated child themes may still be missing the source files that define
those settings for fresh installs and future config exports.

### Child Theme Source Repair

Run the repair command in the Drupal site root to update older Emulsify-based
child theme codebases:

`drush emulsify_tools:repair-favicon-config`

To target a single child theme:

`drush emulsify_tools:repair-favicon-config my_child_theme`

The command scans Emulsify-based child themes in the current codebase and
backfills missing favicon entries in:

- `config/install/<theme>.settings.yml`
- `config/schema/<theme>.schema.yml`

Existing values are preserved. Only missing or `NULL` favicon keys and schema
definitions are filled in. Review and commit those child theme source-file
changes after running the command.

## Development

---
Expand Down
22 changes: 22 additions & 0 deletions emulsify_tools.post_update.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

use Drupal\emulsify_tools\Favicon\FaviconThemeSettingsBackfill;

/**
* Backfills favicon theme settings for installed Emulsify-based themes.
*/
function emulsify_tools_post_update_backfill_emulsify_favicon_settings(array &$sandbox = []): string {
/** @var \Drupal\emulsify_tools\Favicon\FaviconThemeSettingsBackfill $backfill */
$backfill = \Drupal::service(FaviconThemeSettingsBackfill::class);
$result = $backfill->backfill();

return (string) t(
'Backfilled favicon settings for @updated of @affected installed Emulsify-based themes. This migrates only the active <theme>.settings config on the current site; older generated child themes still need their own default config and schema files updated in source so fresh installs and future exports include the new keys.',
[
'@updated' => (string) $result['updated_count'],
'@affected' => (string) $result['affected_count'],
],
);
}
11 changes: 11 additions & 0 deletions emulsify_tools.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ services:
emulsify_tools.subtheme_generator:
class: Drupal\emulsify_tools\SubThemeGenerator
arguments: ['@emulsify_tools.filesystem']
Drupal\emulsify_tools\Favicon\FaviconSourceSanitizerInterface:
alias: emulsify_tools.favicon_source_sanitizer
emulsify_tools.favicon_source_sanitizer:
class: Drupal\emulsify_tools\Favicon\EmulsifyFaviconSourceSanitizer
autowire: true
Drupal\emulsify_tools\Favicon\ChildThemeFaviconConfigRepairer:
class: Drupal\emulsify_tools\Favicon\ChildThemeFaviconConfigRepairer
autowire: true
Drupal\emulsify_tools\Favicon\FaviconThemeSettingsBackfill:
class: Drupal\emulsify_tools\Favicon\FaviconThemeSettingsBackfill
autowire: true
emulsify_tools.twig.switch:
class: Drupal\emulsify_tools\SwitchExtension
tags:
Expand Down
51 changes: 51 additions & 0 deletions src/Drush/Commands/SubThemeCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Archiver\ArchiverManager;
use Drupal\Core\Extension\ThemeExtensionList;
use Drupal\emulsify_tools\Favicon\ChildThemeFaviconConfigRepairer;
use Drupal\emulsify_tools\SubThemeGenerator;
use Drush\Attributes as CLI;
use Drush\Commands\AutowireTrait;
Expand Down Expand Up @@ -39,6 +40,7 @@ public function __construct(
private readonly ArchiverManager $archiverManager,
private readonly SubThemeGenerator $subThemeGenerator,
private readonly Filesystem $filesystem,
private readonly ChildThemeFaviconConfigRepairer $childThemeFaviconConfigRepairer,
) {
parent::__construct();
}
Expand Down Expand Up @@ -69,6 +71,55 @@ public function generateSubTheme(string $name): CollectionBuilder {
return $builder;
}

/**
* Repairs child theme favicon install and schema files for Emulsify 7.x.
*/
#[CLI\Command(name: 'emulsify_tools:repair-favicon-config')]
#[CLI\Argument(name: 'theme', description: 'Optional Emulsify-based child theme machine name.')]
#[CLI\Usage(name: 'emulsify_tools:repair-favicon-config')]
#[CLI\Usage(name: 'emulsify_tools:repair-favicon-config my_child_theme')]
public function repairFaviconConfig(?string $theme = NULL): int {
try {
$result = $this->childThemeFaviconConfigRepairer->repair($theme);
}
catch (\InvalidArgumentException $exception) {
$this->logger()->error($exception->getMessage());
return 1;
}
catch (\Throwable $exception) {
$this->logger()->error($exception->getMessage());
return 1;
}

foreach ($result['updated_themes'] as $themeName => $themeResult) {
$this->logger()->notice(sprintf(
'Updated %s (%s): install=%s, schema=%s.',
$themeName,
$themeResult['path'],
$themeResult['install'],
$themeResult['schema'],
));
}

foreach ($result['errors'] as $themeName => $message) {
$this->logger()->error(sprintf('Unable to repair %s: %s', $themeName, $message));
}

if ($result['updated_count'] === 0 && $result['errors'] === []) {
$this->logger()->notice('No Emulsify child theme favicon source files needed repair.');
}

$this->logger()->notice(sprintf(
'Inspected %d Emulsify-based child themes: %d updated, %d unchanged, %d errors.',
$result['inspected_count'],
$result['updated_count'],
$result['unchanged_count'],
count($result['errors']),
));

return $result['errors'] === [] ? 0 : 1;
}

/**
* Convert label to machine name.
*
Expand Down
Loading
Loading