Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Design Engine Laravel Package

ibexa/design-engine

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Ibexa DXP: Follow the official installation guide to set up Ibexa DXP, which includes this package.
  2. Configure Fallback Rules: Define fallback orders for templates and assets in your Ibexa configuration. Use the design_engine section in config/ibexa/settings.yaml:
    ibexa:
        system:
            default:
                design_engine:
                    template_fallback_order: [custom, system]
                    asset_fallback_order: [region_specific, global]
    
  3. First Use Case: Create a custom template for a content type and set its fallback to a system template. For example:
    // In a custom bundle's DependencyInjection/Configuration.php
    $builder->appendNode('template_fallback_order')
        ->arrayPrototype()
        ->beforeNormalization()
        ->ifString()
        ->then(function ($value) { return [$value]; });
    

Where to Look First

  • Core Classes: Focus on Ibexa\DesignEngine\TemplatePathRegistry and Ibexa\DesignEngine\AssetFallbackResolver for template and asset resolution logic.
  • Configuration: Review config/ibexa/settings.yaml for default fallback orders and override them as needed.
  • Twig Integration: Check Ibexa\DesignEngine\Twig\Extension\DesignEngineExtension for Twig template path resolution hooks.

Implementation Patterns

Usage Patterns

  1. Template Fallback Chains:

    • Define a priority order for templates (e.g., customsystemfallback).
    • Use in Twig templates with {% extends %} or {% include %}:
      {% extends 'custom:template.html.twig' with {'fallback': ['system:template.html.twig', 'fallback:template.html.twig']} %}
      
    • Leverage the TemplatePathRegistry service to dynamically resolve paths:
      $templatePath = $templatePathRegistry->getTemplatePath(
          'custom:template',
          ['fallback' => ['system:template', 'fallback:template']]
      );
      
  2. Asset Fallback for Media:

    • Configure asset fallback orders in settings.yaml:
      ibexa:
          system:
              default:
                  design_engine:
                      asset_fallback_order: [localized, default]
      
    • Use the AssetFallbackResolver to resolve assets with fallbacks:
      $asset = $assetFallbackResolver->resolve(
          $content->getField('image')->getValue(),
          ['localized', 'default']
      );
      
  3. Dynamic Fallback Logic:

    • Extend the TemplatePathRegistry or AssetFallbackResolver to add custom fallback logic (e.g., language-based fallbacks):
      // Custom resolver for language-specific assets
      $resolver = new CustomAssetFallbackResolver(
          $originalResolver,
          $languageService
      );
      
  4. Integration with Content Types:

    • Attach fallback rules to content types via ContentType configuration:
      # config/contenttypes/my_content_type.yaml
      fields:
        image:
          fallback_assets: [eu_logo, us_logo]
      

Workflows

  1. Local Development:

    • Override fallback orders in config/packages/dev/ibexa.yaml for testing:
      ibexa:
          system:
              default:
                  design_engine:
                      template_fallback_order: [debug, custom, system]
      
    • Use the debug prefix to log fallback resolutions during development.
  2. Deployment:

    • Set environment-specific fallback orders (e.g., staging vs. production):
      # config/packages/prod/ibexa.yaml
      ibexa:
          system:
              default:
                  design_engine:
                      asset_fallback_order: [cdn, local]
      
  3. CI/CD:

    • Validate fallback configurations in pipelines using PHPUnit tests:
      public function testTemplateFallbackOrder()
      {
          $registry = $this->createMock(TemplatePathRegistry::class);
          $registry->expects($this->once())
              ->method('getTemplatePath')
              ->with('custom:template', ['fallback' => ['system:template']])
              ->willReturn('/path/to/template.html.twig');
      
          $this->assertTrue(true); // Add assertions for fallback logic
      }
      

Integration Tips

  1. Symfony Dependency Injection:

    • Autowire the TemplatePathRegistry and AssetFallbackResolver in controllers/services:
      public function __construct(
          private TemplatePathRegistry $templatePathRegistry,
          private AssetFallbackResolver $assetFallbackResolver
      ) {}
      
  2. Twig Extensions:

    • Create a custom Twig extension to expose fallback logic:
      class CustomDesignEngineExtension extends \Twig\Extension\AbstractExtension
      {
          public function getFunctions()
          {
              return [
                  new \Twig\TwigFunction('resolve_template', [$this->templatePathRegistry, 'getTemplatePath']),
              ];
          }
      }
      
    • Use in Twig:
      {% set templatePath = resolve_template('custom:template', ['fallback': ['system:template']]) %}
      
  3. Event Listeners:

    • Hook into Ibexa\DesignEngine\Event\TemplateFallbackEvent to modify fallback behavior dynamically:
      public function onTemplateFallback(TemplateFallbackEvent $event)
      {
          if ($event->getTemplateName() === 'custom:template') {
              $event->addFallback('admin:template');
          }
      }
      

Gotchas and Tips

Pitfalls

  1. Circular Fallbacks:

    • Avoid defining fallback chains that loop (e.g., A → B → A). The TemplatePathRegistry throws a CircularReferenceException if detected.
    • Debug Tip: Enable debug mode to log fallback chains:
      ibexa:
          system:
              default:
                  design_engine:
                      debug: true
      
  2. Missing Assets/Templates:

    • If a fallback chain exhausts all options, the system throws a ResourceNotFoundException. Handle gracefully in your code:
      try {
          $asset = $assetFallbackResolver->resolve($assetId, ['localized', 'default']);
      } catch (ResourceNotFoundException $e) {
          $asset = $this->getDefaultAsset();
      }
      
  3. Configuration Overrides:

    • Fallback orders defined in settings.yaml can be overridden by environment-specific configs. Ensure consistency across environments:
      # Validate configs in CI
      php bin/console ibexa:validate-config
      
  4. Caching:

    • Fallback resolutions are cached by default. Clear the cache when updating fallback orders:
      php bin/console cache:clear
      

Debugging

  1. Log Fallback Resolutions:

    • Enable debug logging in config/packages/dev/monolog.yaml:
      handlers:
          ibexa_design_engine:
              type: stream
              path: "%kernel.logs_dir%/design_engine.log"
              channels: ["ibexa_design_engine"]
      
    • Log fallback events in a subscriber:
      public function onTemplateFallback(TemplateFallbackEvent $event)
      {
          $this->logger->debug(
              'Resolving template {template}. Fallbacks: {fallbacks}',
              ['template' => $event->getTemplateName(), 'fallbacks' => $event->getFallbacks()]
          );
      }
      
  2. Common Issues:

    • Template Not Found: Verify the template exists in the expected location (e.g., templates/custom/template.html.twig).
    • Asset Permissions: Ensure fallback assets are accessible (check ContentService permissions).
    • Symfony Version Mismatch: Ibexa Design Engine v5 requires Symfony 7+. Downgrade if using older Symfony versions.

Tips

  1. Performance Optimization:

    • Prioritize fallbacks by likelihood of success (e.g., localized before default for assets).
    • Use AssetFallbackResolver::resolveWithCache() to reduce redundant resolutions.
  2. Testing:

    • Mock the TemplatePathRegistry and AssetFallbackResolver in unit tests:
      $registry = $this->createMock(TemplatePathRegistry::class);
      $registry->method('getTemplatePath')
          ->willReturnMap([
              ['custom:template', ['fallback' => ['system:template']], '/path/to/custom.html.twig'],
              ['system:template', [], '/path/to/system.html.twig'],
          ]);
      
  3. Extending Functionality:

    • Create custom resolvers by extending AbstractFallbackResolver:
      class LanguageAwareAssetFallbackResolver extends AbstractFallbackResolver
      {
          public function __construct(
              private LanguageService $languageService,
              iterable $fallbackResolvers
          ) {
              parent::__construct($fallbackResolvers);
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor