Home > Enterprise >  InvalidConfigurationException with custom bundle in Symfony6.2
InvalidConfigurationException with custom bundle in Symfony6.2

Time:12-08

I'm trying to migrate my custom bundle from symfony 3 to symfony 6.2 support, but are stuck with a InvalidConfigurationException.

I was following this and this documentation, but I appear to be missing a vital part.

src/SchoenefHtmlToPdfBundle.php:

<?php

namespace Schoenef\HtmlToPdfBundle;

use Symfony\Component\HttpKernel\Bundle\AbstractBundle;

class SchoenefHtmlToPdfBundle extends AbstractBundle
{

}

src/DependencyInjection/SchoenefHtmlToPdfExtension.php:

namespace Schoenef\HtmlToPdfBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class SchoenefHtmlToPdfExtension extends Extension
{

    /**
     * {@inheritdoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
        $loader->load('services.yml');
    }

}

src/DependencyInjection/Configuration.php

<?php
namespace Schoenef\HtmlToPdfBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * This is the class that validates and merges configuration from your app/config files
 * this is testing the configuration in the following manner:
 * html2pdf:
 *   provider: defualt pdfrocket
 *   timeout: default 20
 *   apikey: required
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{

    const pageSizes = ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B0', 'B1', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'C5E', 'Comm10E', 'DLE', 'Executive', 'Folio', 'Ledger', 'Legal', 'Letter', 'Tabloid'];
    const PROVIDER_PDF_ROCKET = 'pdfrocket';

    const KEY_PROVIDER = 'provider';
    const KEY_TIMEOUT = 'timeout';
    const KEY_APIKEY = 'apikey';
    const KEY_DEFAULT_OPTIONS = 'default_options';

    const OPTION_DPI = 'dpi';
    const OPTION_SHRINKING = 'shrinking';
    const OPTION_IMAGE_QUALITY = 'image_quality';
    const OPTION_PAGE_SIZE = 'page_size';
    const OPTION_ZOOM = 'zoom';
    const OPTION_JS_DELAY = 'js_delay';

    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder('schoenef_html_to_pdf');

        $treeBuilder->getRootNode()
            ->children()
                ->enumNode(self::KEY_PROVIDER)->values([self::PROVIDER_PDF_ROCKET])->defaultValue(self::PROVIDER_PDF_ROCKET)->end()
                ->integerNode(self::KEY_TIMEOUT)->defaultValue(20)->end()
                ->scalarNode(self::KEY_APIKEY)->isRequired()->end()
                ->arrayNode(self::KEY_DEFAULT_OPTIONS)
                    ->children()
                        ->integerNode(self::OPTION_DPI)->end()
                        ->floatNode(self::OPTION_ZOOM)->end()
                        ->integerNode(self::OPTION_JS_DELAY)->end()
                        ->booleanNode(self::OPTION_SHRINKING)->defaultTrue()->end()
                        ->integerNode(self::OPTION_IMAGE_QUALITY)->end()
                        ->enumNode(self::OPTION_PAGE_SIZE)->values(self::pageSizes)->end()
                    ->end()
                ->end()
            ->end();
        return $treeBuilder;
    }
}

Anybody can see the probably very obvious mistake? I only get:

Unrecognized options "provider, timeout, apikey, default_options" under "schoenef_html_to_pdf". Available options are "".

Thx a lot!

CodePudding user response:

Symfony 6.1 introduced a new AbstractBundle class. With AbstractBundle you no longer need individual Extension and Configuration classes. What I had not realized until seeing this question is that AbstractBundle is incompatible with the older Bundle class.

So the short answer to this question is to extend the original Bundle class and everything should work as before. The Bundle class itself is not going anywhere.

use Symfony\Component\HttpKernel\Bundle\Bundle;

class SchoenefHtmlToPdfBundle extends Bundle

A somewhat longer answer would be to go ahead and take advantage of the AbstractBundle's capability. Something like:

class CeradMyBundle extends AbstractBundle
{
  const pageSizes = ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B0', 'B1', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'C5E', 'Comm10E', 'DLE', 'Executive', 'Folio', 'Ledger', 'Legal', 'Letter', 'Tabloid'];
  const PROVIDER_PDF_ROCKET = 'pdfrocket';

  const KEY_PROVIDER = 'provider';
  const KEY_TIMEOUT = 'timeout';
  const KEY_APIKEY = 'apikey';
  const KEY_DEFAULT_OPTIONS = 'default_options';

  const OPTION_DPI = 'dpi';
  const OPTION_SHRINKING = 'shrinking';
  const OPTION_IMAGE_QUALITY = 'image_quality';
  const OPTION_PAGE_SIZE = 'page_size';
  const OPTION_ZOOM = 'zoom';
  const OPTION_JS_DELAY = 'js_delay';

  public function configure(DefinitionConfigurator $definition): void
  {
    $definition->rootNode()
      ->children()
        ->enumNode(self::KEY_PROVIDER)->values([self::PROVIDER_PDF_ROCKET])->defaultValue(self::PROVIDER_PDF_ROCKET)->end()
        ->integerNode(self::KEY_TIMEOUT)->defaultValue(20)->end()
        ->scalarNode(self::KEY_APIKEY)->isRequired()->end()
        ->arrayNode(self::KEY_DEFAULT_OPTIONS)
            ->children()
                ->integerNode(self::OPTION_DPI)->end()
                ->floatNode(self::OPTION_ZOOM)->end()
                ->integerNode(self::OPTION_JS_DELAY)->end()
                ->booleanNode(self::OPTION_SHRINKING)->defaultTrue()->end()
                ->integerNode(self::OPTION_IMAGE_QUALITY)->end()
                ->enumNode(self::OPTION_PAGE_SIZE)->values(self::pageSizes)->end()
            ->end()
        ->end()
    ->end();
  }
  public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
  {
    $container->import('../config/services.yaml');
  }
}

You might also consider moving the configuration stuff into it's own config/definition.php file.

  • Related