vendor/pimcore/pimcore/bundles/CoreBundle/DependencyInjection/Configuration.php line 174

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Bundle\CoreBundle\DependencyInjection;
  15. use Pimcore\Bundle\CoreBundle\DependencyInjection\Config\Processor\PlaceholderProcessor;
  16. use Pimcore\Targeting\Storage\CookieStorage;
  17. use Pimcore\Targeting\Storage\TargetingStorageInterface;
  18. use Pimcore\Workflow\EventSubscriber\ChangePublishedStateSubscriber;
  19. use Pimcore\Workflow\EventSubscriber\NotificationSubscriber;
  20. use Pimcore\Workflow\Notification\NotificationEmailService;
  21. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  22. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  23. use Symfony\Component\Config\Definition\ConfigurationInterface;
  24. /**
  25.  * @internal
  26.  */
  27. final class Configuration implements ConfigurationInterface
  28. {
  29.     /**
  30.      * @var PlaceholderProcessor
  31.      */
  32.     private PlaceholderProcessor $placeholderProcessor;
  33.     /**
  34.      * @var array
  35.      */
  36.     private array $placeholders = [];
  37.     public function __construct()
  38.     {
  39.         $this->placeholderProcessor = new PlaceholderProcessor();
  40.         $this->placeholders = [];
  41.     }
  42.     /**
  43.      * {@inheritdoc}
  44.      */
  45.     public function getConfigTreeBuilder(): TreeBuilder
  46.     {
  47.         $treeBuilder = new TreeBuilder('pimcore');
  48.         /** @var ArrayNodeDefinition $rootNode */
  49.         $rootNode $treeBuilder->getRootNode();
  50.         $rootNode->addDefaultsIfNotSet();
  51.         $rootNode
  52.             ->children()
  53.                 ->arrayNode('error_handling')
  54.                     ->addDefaultsIfNotSet()
  55.                     ->children()
  56.                         ->booleanNode('render_error_document')
  57.                             ->info('Render error document in case of an error instead of showing Symfony\'s error page')
  58.                             ->defaultTrue()
  59.                             ->beforeNormalization()
  60.                                 ->ifString()
  61.                                 ->then(function ($v) {
  62.                                     return (bool)$v;
  63.                                 })
  64.                             ->end()
  65.                         ->end()
  66.                     ->end()
  67.                     ->setDeprecated(
  68.                         'pimcore/pimcore',
  69.                         '10.1',
  70.                         'The "%node%" option is deprecated since Pimcore 10.1, it will be removed in Pimcore 11.'
  71.                     )
  72.                 ->end()
  73.                 ->arrayNode('bundles')
  74.                     ->addDefaultsIfNotSet()
  75.                     ->children()
  76.                         ->arrayNode('search_paths')
  77.                             ->prototype('scalar')->end()
  78.                         ->end()
  79.                         ->booleanNode('handle_composer')
  80.                             ->defaultTrue()
  81.                         ->end()
  82.                     ->end()
  83.                 ->end()
  84.                 ->arrayNode('flags')
  85.                     ->info('Generic map for feature flags')
  86.                     ->prototype('scalar')->end()
  87.                 ->end()
  88.                 ->arrayNode('translations')
  89.                     ->addDefaultsIfNotSet()
  90.                     ->children()
  91.                         ->arrayNode('admin_translation_mapping')
  92.                             ->useAttributeAsKey('locale')
  93.                             ->prototype('scalar')->end()
  94.                         ->end()
  95.                         ->arrayNode('debugging')
  96.                             ->info('If debugging is enabled, the translator will return the plain translation key instead of the translated message.')
  97.                             ->addDefaultsIfNotSet()
  98.                             ->canBeDisabled()
  99.                             ->children()
  100.                                 ->scalarNode('parameter')
  101.                                     ->defaultValue('pimcore_debug_translations')
  102.                                 ->end()
  103.                             ->end()
  104.                         ->end()
  105.                         ->arrayNode('data_object')
  106.                             ->addDefaultsIfNotSet()
  107.                             ->children()
  108.                                 ->arrayNode('translation_extractor')
  109.                                     ->children()
  110.                                         ->arrayNode('attributes')
  111.                                             ->info('Can be used to restrict the extracted localized fields (e.g. used by XLIFF exporter in the Pimcore backend)')
  112.                                             ->prototype('array')
  113.                                                 ->prototype('scalar')->end()
  114.                                             ->end()
  115.                                             ->example(
  116.                                                 [
  117.                                                     'Product' => ['name''description'],
  118.                                                     'Brand' => ['name'],
  119.                                                 ]
  120.                                             )
  121.                                         ->end()
  122.                                     ->end()
  123.                                 ->end()
  124.                             ->end()
  125.                         ->end()
  126.                     ->end()
  127.                 ->end()
  128.                 ->arrayNode('maps')
  129.                     ->addDefaultsIfNotSet()
  130.                     ->children()
  131.                         ->scalarNode('tile_layer_url_template')
  132.                             ->defaultValue('https://a.tile.openstreetmap.org/{z}/{x}/{y}.png')
  133.                         ->end()
  134.                         ->scalarNode('geocoding_url_template')
  135.                             ->defaultValue('https://nominatim.openstreetmap.org/search?q={q}&addressdetails=1&format=json&limit=1')
  136.                         ->end()
  137.                         ->scalarNode('reverse_geocoding_url_template')
  138.                             ->defaultValue('https://nominatim.openstreetmap.org/reverse?format=json&lat={lat}&lon={lon}&addressdetails=1')
  139.                         ->end()
  140.                     ->end()
  141.                 ->end()
  142.             ->end();
  143.         $this->addGeneralNode($rootNode);
  144.         $this->addMaintenanceNode($rootNode);
  145.         $this->addServicesNode($rootNode);
  146.         $this->addObjectsNode($rootNode);
  147.         $this->addAssetNode($rootNode);
  148.         $this->addDocumentsNode($rootNode);
  149.         $this->addEncryptionNode($rootNode);
  150.         $this->addModelsNode($rootNode);
  151.         $this->addRoutingNode($rootNode);
  152.         $this->addCacheNode($rootNode);
  153.         $this->addContextNode($rootNode);
  154.         $this->addAdminNode($rootNode);
  155.         $this->addWebProfilerNode($rootNode);
  156.         $this->addSecurityNode($rootNode);
  157.         $this->addEmailNode($rootNode);
  158.         $this->addNewsletterNode($rootNode);
  159.         $this->addCustomReportsNode($rootNode);
  160.         $this->addTargetingNode($rootNode);
  161.         $this->addSitemapsNode($rootNode);
  162.         $this->addWorkflowNode($rootNode);
  163.         $this->addHttpClientNode($rootNode);
  164.         $this->addApplicationLogNode($rootNode);
  165.         $this->addPredefinedPropertiesNode($rootNode);
  166.         $this->addStaticRoutesNode($rootNode);
  167.         $this->addPerspectivesNode($rootNode);
  168.         $this->addCustomViewsNode($rootNode);
  169.         $this->buildRedirectsStatusCodes($rootNode);
  170.         return $treeBuilder;
  171.     }
  172.     /**
  173.      * Add maintenance config
  174.      *
  175.      * @param ArrayNodeDefinition $rootNode
  176.      */
  177.     private function addMaintenanceNode(ArrayNodeDefinition $rootNode)
  178.     {
  179.         $rootNode
  180.             ->children()
  181.             ->arrayNode('maintenance')
  182.             ->addDefaultsIfNotSet()
  183.             ->children()
  184.                 ->arrayNode('housekeeping')
  185.                 ->addDefaultsIfNotSet()
  186.                 ->children()
  187.                     ->integerNode('cleanup_tmp_files_atime_older_than')
  188.                         ->defaultValue(7776000// 90 days
  189.                     ->end()
  190.                     ->integerNode('cleanup_profiler_files_atime_older_than')
  191.                         ->defaultValue(1800)
  192.                     ->end()
  193.         ;
  194.     }
  195.     /**
  196.      * @param ArrayNodeDefinition $rootNode
  197.      */
  198.     private function buildRedirectsStatusCodes(ArrayNodeDefinition $rootNode)
  199.     {
  200.         $rootNode
  201.             ->children()
  202.             ->arrayNode('redirects')
  203.                 ->addDefaultsIfNotSet()
  204.                 ->children()
  205.                     ->arrayNode('status_codes')
  206.                         ->info('List all redirect status codes.')
  207.                         ->prototype('scalar')
  208.                     ->end()
  209.                 ->end()
  210.             ->end();
  211.     }
  212.     /**
  213.      * Add general config
  214.      *
  215.      * @param ArrayNodeDefinition $rootNode
  216.      */
  217.     private function addGeneralNode(ArrayNodeDefinition $rootNode)
  218.     {
  219.         $rootNode
  220.             ->children()
  221.             ->arrayNode('general')
  222.             ->addDefaultsIfNotSet()
  223.             ->children()
  224.                 ->scalarNode('timezone')
  225.                     ->defaultValue('')
  226.                 ->end()
  227.                 ->scalarNode('path_variable')
  228.                     ->info('Additional $PATH variable (: separated) (/x/y:/foo/bar):')
  229.                     ->defaultNull()
  230.                 ->end()
  231.                 ->scalarNode('domain')
  232.                     ->defaultValue('')
  233.                 ->end()
  234.                 ->booleanNode('redirect_to_maindomain')
  235.                     ->beforeNormalization()
  236.                         ->ifString()
  237.                         ->then(function ($v) {
  238.                             return (bool)$v;
  239.                         })
  240.                     ->end()
  241.                     ->defaultFalse()
  242.                 ->end()
  243.                 ->scalarNode('language')
  244.                     ->defaultValue('en')
  245.                 ->end()
  246.                 ->scalarNode('valid_languages')
  247.                     ->defaultValue('en')
  248.                 ->end()
  249.                 ->arrayNode('fallback_languages')
  250.                     ->performNoDeepMerging()
  251.                     ->beforeNormalization()
  252.                     ->ifArray()
  253.                         ->then(function ($v) {
  254.                             return $v;
  255.                         })
  256.                     ->end()
  257.                     ->prototype('scalar')
  258.                     ->end()
  259.                 ->end()
  260.                 ->scalarNode('default_language')
  261.                     ->defaultValue('en')
  262.                 ->end()
  263.                 ->booleanNode('disable_usage_statistics')
  264.                     ->beforeNormalization()
  265.                         ->ifString()
  266.                         ->then(function ($v) {
  267.                             return (bool)$v;
  268.                         })
  269.                     ->end()
  270.                     ->defaultFalse()
  271.                 ->end()
  272.                 ->booleanNode('debug_admin_translations')
  273.                     ->info('Debug Admin-Translations (displayed wrapped in +)')
  274.                     ->beforeNormalization()
  275.                         ->ifString()
  276.                         ->then(function ($v) {
  277.                             return (bool)$v;
  278.                         })
  279.                     ->end()
  280.                     ->defaultFalse()
  281.                 ->end()
  282.                 ->scalarNode('instance_identifier')
  283.                     ->defaultNull()
  284.                     ->info('UUID instance identifier. Has to be unique throughout multiple Pimcore instances. UUID generation will be automatically enabled if a Instance identifier is provided (do not change the instance identifier afterwards - this will cause invalid UUIDs)')
  285.                     ->end()
  286.                 ->end()
  287.             ->end();
  288.     }
  289.     /**
  290.      * @param ArrayNodeDefinition $rootNode
  291.      */
  292.     private function addServicesNode(ArrayNodeDefinition $rootNode)
  293.     {
  294.         $rootNode
  295.             ->children()
  296.             ->arrayNode('services')
  297.                 ->addDefaultsIfNotSet()
  298.                 ->children()
  299.                     ->arrayNode('google')
  300.                     ->addDefaultsIfNotSet()
  301.                     ->children()
  302.                         ->scalarNode('client_id')
  303.                             ->info('This is required for the Google API integrations. Only use a `Service Account´ from the Google Cloud Console.')
  304.                             ->defaultNull()
  305.                         ->end()
  306.                         ->scalarNode('email')
  307.                             ->info('Email address of the Google service account')
  308.                             ->defaultNull()
  309.                         ->end()
  310.                         ->scalarNode('simple_api_key')
  311.                             ->info('Server API key')
  312.                             ->defaultNull()
  313.                         ->end()
  314.                         ->scalarNode('browser_api_key')
  315.                             ->info('Browser API key')
  316.                             ->defaultNull()
  317.                         ->end()
  318.                     ->end()
  319.                     ->end()
  320.                 ->end()
  321.             ->end();
  322.     }
  323.     /**
  324.      * @param ArrayNodeDefinition $rootNode
  325.      */
  326.     private function addModelsNode(ArrayNodeDefinition $rootNode)
  327.     {
  328.         $rootNode
  329.             ->children()
  330.                 ->arrayNode('models')
  331.                     ->addDefaultsIfNotSet()
  332.                     ->children()
  333.                         ->arrayNode('class_overrides')
  334.                             ->useAttributeAsKey('name')
  335.                             ->prototype('scalar');
  336.     }
  337.     /**
  338.      * @param ArrayNodeDefinition $rootNode
  339.      */
  340.     private function addHttpClientNode(ArrayNodeDefinition $rootNode)
  341.     {
  342.         $rootNode
  343.             ->children()
  344.                 ->arrayNode('httpclient')
  345.                 ->addDefaultsIfNotSet()
  346.                     ->children()
  347.                         ->scalarNode('adapter')
  348.                             ->info('Set to `Proxy` if proxy server should be used')
  349.                             ->defaultValue('Socket')
  350.                         ->end()
  351.                         ->scalarNode('proxy_host')
  352.                             ->defaultNull()
  353.                         ->end()
  354.                         ->scalarNode('proxy_port')
  355.                             ->defaultNull()
  356.                         ->end()
  357.                         ->scalarNode('proxy_user')
  358.                             ->defaultNull()
  359.                         ->end()
  360.                         ->scalarNode('proxy_pass')
  361.                             ->defaultNull()
  362.                         ->end()
  363.                     ->end()
  364.                 ->end()
  365.             ->end();
  366.     }
  367.     /**
  368.      * @param ArrayNodeDefinition $rootNode
  369.      */
  370.     private function addApplicationLogNode(ArrayNodeDefinition $rootNode)
  371.     {
  372.         $rootNode
  373.             ->children()
  374.                 ->arrayNode('applicationlog')
  375.                 ->addDefaultsIfNotSet()
  376.                     ->children()
  377.                         ->arrayNode('mail_notification')
  378.                             ->children()
  379.                                 ->booleanNode('send_log_summary')
  380.                                     ->info('Send log summary via email')
  381.                                     ->beforeNormalization()
  382.                                         ->ifString()
  383.                                         ->then(function ($v) {
  384.                                             return (bool)$v;
  385.                                         })
  386.                                     ->end()
  387.                                     ->defaultFalse()
  388.                                 ->end()
  389.                                 ->scalarNode('filter_priority')
  390.                                     ->info('Filter threshold for email summary, choose one of: 7 (debug), 6 (info), 5 (notice), 4 (warning), 3 (error), 2 (critical), 1 (alert) ,0 (emerg)')
  391.                                     ->defaultNull()
  392.                                 ->end()
  393.                                 ->scalarNode('mail_receiver')
  394.                                 ->info('Log summary receivers. Separate multiple email receivers by using ;')
  395.                                 ->end()
  396.                             ->end()
  397.                         ->end()
  398.                         ->scalarNode('archive_treshold')
  399.                             ->info('Archive threshold in days')
  400.                             ->defaultValue(30)
  401.                         ->end()
  402.                         ->scalarNode('archive_alternative_database')
  403.                             ->info('Archive database name (optional). Tables will get archived to a different database, recommended when huge amounts of logs will be generated')
  404.                             ->defaultValue('')
  405.                         ->end()
  406.                         ->scalarNode('delete_archive_threshold')
  407.                             ->info('Threshold for deleting application log archive tables (in months)')
  408.                             ->defaultValue('6')
  409.                         ->end()
  410.                     ->end()
  411.             ->end();
  412.     }
  413.     /**
  414.      * Add asset specific extension config
  415.      *
  416.      * @param ArrayNodeDefinition $rootNode
  417.      */
  418.     private function addAssetNode(ArrayNodeDefinition $rootNode)
  419.     {
  420.         $assetsNode $rootNode
  421.             ->children()
  422.                 ->arrayNode('assets')
  423.                 ->addDefaultsIfNotSet()
  424.                 ->children()
  425.                     ->arrayNode('frontend_prefixes')
  426.                         ->addDefaultsIfNotSet()
  427.                         ->children()
  428.                             ->scalarNode('source')
  429.                                 ->defaultValue('')
  430.                                 ->end()
  431.                             ->scalarNode('thumbnail')
  432.                                 ->defaultValue('')
  433.                                 ->end()
  434.                             ->scalarNode('thumbnail_deferred')
  435.                                 ->defaultValue('')
  436.                                 ->end()
  437.                         ->end()
  438.                     ->end()
  439.                     ->scalarNode('preview_image_thumbnail')
  440.                         ->defaultNull()
  441.                         ->end()
  442.                     ->scalarNode('default_upload_path')
  443.                         ->defaultValue('_default_upload_bucket')
  444.                         ->end()
  445.                     ->integerNode('tree_paging_limit')
  446.                         ->defaultValue(100)
  447.                         ->end()
  448.                     ->arrayNode('image')
  449.                         ->addDefaultsIfNotSet()
  450.                         ->children()
  451.                             ->integerNode('max_pixels')
  452.                                 ->defaultValue(40000000)
  453.                             ->end()
  454.                             ->arrayNode('low_quality_image_preview')
  455.                                 ->addDefaultsIfNotSet()
  456.                                 ->canBeDisabled()
  457.                             ->end()
  458.                             ->arrayNode('focal_point_detection')
  459.                                 ->addDefaultsIfNotSet()
  460.                                 ->canBeDisabled()
  461.                             ->end()
  462.                             ->arrayNode('thumbnails')
  463.                                 ->addDefaultsIfNotSet()
  464.                                 ->children()
  465.                                     ->arrayNode('definitions')
  466.                                         ->normalizeKeys(false)
  467.                                         ->prototype('array')
  468.                                             ->children()
  469.                                                 ->scalarNode('id')->end()
  470.                                                 ->scalarNode('name')->end()
  471.                                                 ->scalarNode('description')->end()
  472.                                                 ->scalarNode('group')->end()
  473.                                                 ->scalarNode('format')->end()
  474.                                                 ->scalarNode('quality')->end()
  475.                                                 ->scalarNode('highResolution')->end()
  476.                                                 ->booleanNode('preserveColor')->end()
  477.                                                 ->booleanNode('preserveMetaData')->end()
  478.                                                 ->booleanNode('rasterizeSVG')->end()
  479.                                                 ->booleanNode('downloadable')->end()
  480.                                                 ->integerNode('modificationDate')->end()
  481.                                                 ->integerNode('creationDate')->end()
  482.                                                 ->booleanNode('preserveAnimation')->end()
  483.                                                 ->arrayNode('items')
  484.                                                     ->prototype('array')
  485.                                                         ->children()
  486.                                                             ->scalarNode('method')->end()
  487.                                                             ->arrayNode('arguments')
  488.                                                                 ->prototype('variable')->end()
  489.                                                             ->end()
  490.                                                         ->end()
  491.                                                     ->end()
  492.                                                 ->end()
  493.                                                 ->arrayNode('medias')
  494.                                                     ->normalizeKeys(false)
  495.                                                     ->prototype('array')
  496.                                                         ->arrayProtoType()
  497.                                                             ->children()
  498.                                                                 ->scalarNode('method')->end()
  499.                                                                 ->arrayNode('arguments')
  500.                                                                     ->prototype('variable')->end()
  501.                                                                 ->end()
  502.                                                             ->end()
  503.                                                         ->end()
  504.                                                     ->end()
  505.                                                 ->end()
  506.                                             ->end()
  507.                                         ->end()
  508.                                     ->end()
  509.                                     ->booleanNode('clip_auto_support')
  510.                                         ->beforeNormalization()
  511.                                             ->ifString()
  512.                                             ->then(function ($v) {
  513.                                                 return (bool)$v;
  514.                                             })
  515.                                         ->end()
  516.                                         ->defaultTrue()
  517.                                     ->end()
  518.                                     ->arrayNode('image_optimizers')
  519.                                         ->addDefaultsIfNotSet()
  520.                                         ->canBeDisabled()
  521.                                     ->end()
  522.                                     ->arrayNode('auto_formats')
  523.                                         ->prototype('array')
  524.                                             ->canBeDisabled()
  525.                                             ->children()
  526.                                                 ->scalarNode('quality')->end()
  527.                                             ->end()
  528.                                         ->end()
  529.                                         ->defaultValue([
  530.                                             'avif' => [
  531.                                                 'enabled' => true,
  532.                                                 'quality' => 15,
  533.                                             ],
  534.                                             'webp' => [
  535.                                                 'enabled' => true,
  536.                                                 'quality' => null,
  537.                                             ],
  538.                                         ])
  539.                                     ->end()
  540.                                     ->booleanNode('status_cache')
  541.                                         ->defaultTrue()
  542.                                     ->end()
  543.                                     ->booleanNode('auto_clear_temp_files')
  544.                                         ->beforeNormalization()
  545.                                             ->ifString()
  546.                                             ->then(function ($v) {
  547.                                                 return (bool)$v;
  548.                                             })
  549.                                         ->end()
  550.                                         ->defaultTrue()
  551.                                     ->end()
  552.                                 ->end()
  553.                             ->end()
  554.                         ->end()
  555.                     ->end()
  556.                     ->arrayNode('video')
  557.                         ->addDefaultsIfNotSet()
  558.                         ->children()
  559.                             ->arrayNode('thumbnails')
  560.                                 ->addDefaultsIfNotSet()
  561.                                 ->children()
  562.                                     ->arrayNode('definitions')
  563.                                         ->normalizeKeys(false)
  564.                                         ->prototype('array')
  565.                                             ->children()
  566.                                                 ->scalarNode('id')->end()
  567.                                                 ->scalarNode('name')->end()
  568.                                                 ->scalarNode('description')->end()
  569.                                                 ->scalarNode('group')->end()
  570.                                                 ->scalarNode('videoBitrate')->end()
  571.                                                 ->scalarNode('audioBitrate')->end()
  572.                                                 ->scalarNode('quality')->end()
  573.                                                 ->integerNode('modificationDate')->end()
  574.                                                 ->integerNode('creationDate')->end()
  575.                                                 ->arrayNode('items')
  576.                                                     ->prototype('array')
  577.                                                         ->children()
  578.                                                             ->scalarNode('method')->end()
  579.                                                             ->arrayNode('arguments')
  580.                                                                 ->prototype('variable')->end()
  581.                                                             ->end()
  582.                                                         ->end()
  583.                                                     ->end()
  584.                                                 ->end()
  585.                                                 ->arrayNode('medias')
  586.                                                     ->normalizeKeys(false)
  587.                                                     ->prototype('array')
  588.                                                         ->arrayProtoType()
  589.                                                             ->children()
  590.                                                                 ->scalarNode('method')->end()
  591.                                                                 ->arrayNode('arguments')
  592.                                                                     ->prototype('variable')->end()
  593.                                                                 ->end()
  594.                                                             ->end()
  595.                                                         ->end()
  596.                                                     ->end()
  597.                                                 ->end()
  598.                                             ->end()
  599.                                         ->end()
  600.                                     ->end()
  601.                                     ->booleanNode('auto_clear_temp_files')
  602.                                     ->defaultTrue()
  603.                                     ->end()
  604.                                 ->end()
  605.                             ->end()
  606.                         ->end()
  607.                     ->end()
  608.                     ->arrayNode('versions')
  609.                         ->addDefaultsIfNotSet()
  610.                         ->children()
  611.                             ->scalarNode('days')
  612.                                 ->defaultNull()
  613.                             ->end()
  614.                             ->scalarNode('steps')
  615.                                 ->defaultNull()
  616.                             ->end()
  617.                             ->booleanNode('use_hardlinks')
  618.                                 ->beforeNormalization()
  619.                                     ->ifString()
  620.                                     ->then(function ($v) {
  621.                                         return (bool)$v;
  622.                                     })
  623.                                 ->end()
  624.                                 ->defaultTrue()
  625.                             ->end()
  626.                             ->booleanNode('disable_stack_trace')
  627.                                 ->beforeNormalization()
  628.                                     ->ifString()
  629.                                     ->then(function ($v) {
  630.                                         return (bool)$v;
  631.                                     })
  632.                                 ->end()
  633.                                 ->defaultFalse()
  634.                             ->end()
  635.                         ->end()
  636.                     ->end()
  637.                     ->scalarNode('icc_rgb_profile')
  638.                         ->info('Absolute path to default ICC RGB profile (if no embedded profile is given)')
  639.                         ->defaultNull()
  640.                     ->end()
  641.                     ->scalarNode('icc_cmyk_profile')
  642.                         ->info('Absolute path to default ICC CMYK profile (if no embedded profile is given)')
  643.                         ->defaultNull()
  644.                     ->end()
  645.                     ->booleanNode('hide_edit_image')
  646.                         ->defaultFalse()
  647.                     ->end()
  648.                     ->booleanNode('disable_tree_preview')
  649.                         ->defaultTrue()
  650.                     ->end()
  651.                 ->end();
  652.         $assetsNode
  653.             ->children()
  654.                 ->arrayNode('metadata')
  655.                 ->addDefaultsIfNotSet()
  656.                     ->children()
  657.                         ->arrayNode('predefined')
  658.                             ->addDefaultsIfNotSet()
  659.                             ->children()
  660.                                 ->arrayNode('definitions')
  661.                                 ->normalizeKeys(false)
  662.                                     ->prototype('array')
  663.                                         ->children()
  664.                                             ->scalarNode('name')->end()
  665.                                             ->scalarNode('description')->end()
  666.                                             ->scalarNode('group')->end()
  667.                                             ->scalarNode('language')->end()
  668.                                             ->scalarNode('type')->end()
  669.                                             ->scalarNode('data')->end()
  670.                                             ->scalarNode('targetSubtype')->end()
  671.                                             ->scalarNode('config')->end()
  672.                                             ->booleanNode('inheritable')
  673.                                                 ->beforeNormalization()
  674.                                                 ->ifString()
  675.                                                 ->then(function ($v) {
  676.                                                     return (bool)$v;
  677.                                                 })
  678.                                                 ->end()
  679.                                             ->end()
  680.                                             ->integerNode('creationDate')->end()
  681.                                             ->integerNode('modificationDate')->end()
  682.                                         ->end()
  683.                                     ->end()
  684.                                 ->end()
  685.                             ->end()
  686.                         ->end()
  687.                         ->arrayNode('class_definitions')
  688.                             ->children()
  689.                                 ->arrayNode('data')
  690.                                     ->children()
  691.                                         ->arrayNode('map')
  692.                                             ->useAttributeAsKey('name')
  693.                                             ->prototype('scalar')->end()
  694.                                         ->end()
  695.                                         ->arrayNode('prefixes')
  696.                                             ->prototype('scalar')->end()
  697.                                         ->end()
  698.                                     ->end()
  699.                                 ->end()
  700.                             ->end()
  701.                         ->end();
  702.     }
  703.     /**
  704.      * Add object specific extension config
  705.      *
  706.      * @param ArrayNodeDefinition $rootNode
  707.      */
  708.     private function addObjectsNode(ArrayNodeDefinition $rootNode)
  709.     {
  710.         $objectsNode $rootNode
  711.             ->children()
  712.                 ->arrayNode('objects')
  713.                     ->ignoreExtraKeys()
  714.                     ->addDefaultsIfNotSet()
  715.                     ->children()
  716.                         ->booleanNode('ignore_localized_query_fallback')
  717.                             ->beforeNormalization()
  718.                             ->ifString()
  719.                                 ->then(function ($v) {
  720.                                     return (bool)$v;
  721.                                 })
  722.                                 ->end()
  723.                             ->defaultFalse()
  724.                         ->end()
  725.                         ->integerNode('tree_paging_limit')
  726.                             ->defaultValue(30)
  727.                         ->end()
  728.                         ->integerNode('auto_save_interval')
  729.                             ->defaultValue(60)
  730.                         ->end()
  731.                         ->arrayNode('versions')
  732.                             ->children()
  733.                                 ->scalarNode('days')->defaultNull()->end()
  734.                                 ->scalarNode('steps')->defaultNull()->end()
  735.                                 ->booleanNode('disable_stack_trace')
  736.                                     ->beforeNormalization()
  737.                                     ->ifString()
  738.                                         ->then(function ($v) {
  739.                                             return (bool)$v;
  740.                                         })
  741.                                     ->end()
  742.                                     ->defaultFalse()
  743.                                 ->end()
  744.                             ->end()
  745.                         ->end()
  746.                     ->end();
  747.         $classDefinitionsNode $objectsNode
  748.             ->children()
  749.                 ->arrayNode('class_definitions')
  750.                     ->addDefaultsIfNotSet();
  751.         $this->addImplementationLoaderNode($classDefinitionsNode'data');
  752.         $this->addImplementationLoaderNode($classDefinitionsNode'layout');
  753.     }
  754.     /**
  755.      * Add encryption specific extension config
  756.      *
  757.      * @param ArrayNodeDefinition $rootNode
  758.      */
  759.     private function addEncryptionNode(ArrayNodeDefinition $rootNode)
  760.     {
  761.         $encryptionNode $rootNode
  762.             ->children()
  763.             ->arrayNode('encryption')->addDefaultsIfNotSet();
  764.         $encryptionNode
  765.             ->children()
  766.             ->scalarNode('secret')->defaultNull();
  767.     }
  768.     /**
  769.      * Add document specific extension config
  770.      *
  771.      * @param ArrayNodeDefinition $rootNode
  772.      */
  773.     private function addDocumentsNode(ArrayNodeDefinition $rootNode)
  774.     {
  775.         $documentsNode $rootNode
  776.             ->children()
  777.                 ->arrayNode('documents')
  778.                     ->ignoreExtraKeys()
  779.                     ->addDefaultsIfNotSet();
  780.         $documentsNode
  781.             ->children()
  782.                  ->arrayNode('doc_types')
  783.                     ->addDefaultsIfNotSet()
  784.                     ->children()
  785.                         ->arrayNode('definitions')
  786.                         ->normalizeKeys(false)
  787.                             ->prototype('array')
  788.                                 ->children()
  789.                                     ->scalarNode('name')->end()
  790.                                     ->scalarNode('group')->end()
  791.                                     ->scalarNode('module')->end()
  792.                                     ->scalarNode('controller')->end()
  793.                                     ->scalarNode('template')->end()
  794.                                     ->scalarNode('type')->end()
  795.                                     ->integerNode('priority')->end()
  796.                                     ->integerNode('creationDate')->end()
  797.                                     ->integerNode('modificationDate')->end()
  798.                                     ->scalarNode('staticGeneratorEnabled')->end()
  799.                                 ->end()
  800.                             ->end()
  801.                         ->end()
  802.                     ->end()
  803.                 ->end()
  804.                 ->arrayNode('versions')
  805.                     ->children()
  806.                         ->scalarNode('days')
  807.                             ->defaultNull()
  808.                         ->end()
  809.                         ->scalarNode('steps')
  810.                             ->defaultNull()
  811.                         ->end()
  812.                         ->booleanNode('disable_stack_trace')
  813.                             ->beforeNormalization()
  814.                             ->ifString()
  815.                                 ->then(function ($v) {
  816.                                     return (bool)$v;
  817.                                 })
  818.                             ->end()
  819.                             ->defaultFalse()
  820.                         ->end()
  821.                     ->end()
  822.                 ->end()
  823.                 ->scalarNode('default_controller')
  824.                     ->defaultValue('App\\Controller\\DefaultController::defaultAction')
  825.                 ->end()
  826.                 ->arrayNode('error_pages')
  827.                     ->children()
  828.                         ->scalarNode('default')
  829.                             ->defaultNull()
  830.                         ->end()
  831.                         ->arrayNode('localized')
  832.                             ->performNoDeepMerging()
  833.                             ->beforeNormalization()
  834.                                 ->ifArray()
  835.                                     ->then(function ($v) {
  836.                                         return $v;
  837.                                     })
  838.                             ->end()
  839.                             ->prototype('scalar')
  840.                             ->end()
  841.                         ->end()
  842.                     ->end()
  843.                 ->end()
  844.                 ->scalarNode('allow_trailing_slash')
  845.                     ->defaultValue('no')
  846.                 ->end()
  847.                 ->booleanNode('generate_preview')
  848.                     ->beforeNormalization()
  849.                         ->ifString()
  850.                         ->then(function ($v) {
  851.                             return (bool)$v;
  852.                         })
  853.                     ->end()
  854.                     ->defaultFalse()
  855.                 ->end()
  856.                 ->scalarNode('preview_url_prefix')
  857.                     ->defaultValue('')
  858.                 ->end()
  859.                 ->integerNode('tree_paging_limit')
  860.                     ->defaultValue(50)
  861.                 ->end()
  862.                 ->arrayNode('editables')
  863.                     ->addDefaultsIfNotSet()
  864.                     ->children()
  865.                         ->arrayNode('map')
  866.                             ->useAttributeAsKey('name')
  867.                             ->prototype('scalar')->end()
  868.                         ->end()
  869.                         ->arrayNode('prefixes')
  870.                             ->prototype('scalar')->end()
  871.                         ->end()
  872.                     ->end()
  873.                 ->end()
  874.                 ->arrayNode('types')
  875.                     ->info('list of supported document types')
  876.                     ->scalarPrototype()->end()
  877.                 ->end()
  878.                 ->arrayNode('valid_tables')
  879.                     ->info('list of supported documents_* tables')
  880.                     ->scalarPrototype()->end()
  881.                 ->end()
  882.                 ->arrayNode('areas')
  883.                     ->addDefaultsIfNotSet()
  884.                     ->children()
  885.                         ->booleanNode('autoload')
  886.                             ->beforeNormalization()
  887.                                 ->ifString()
  888.                                 ->then(function ($v) {
  889.                                     return (bool)$v;
  890.                                 })
  891.                             ->end()
  892.                             ->defaultTrue()
  893.                         ->end()
  894.                     ->end()
  895.                 ->end()
  896.                 ->arrayNode('newsletter')
  897.                     ->addDefaultsIfNotSet()
  898.                     ->children()
  899.                         ->scalarNode('defaultUrlPrefix')
  900.                             ->defaultNull()
  901.                         ->end()
  902.                     ->end()
  903.                 ->end()
  904.                 ->arrayNode('web_to_print')
  905.                     ->addDefaultsIfNotSet()
  906.                         ->children()
  907.                             ->scalarNode('pdf_creation_php_memory_limit')
  908.                                 ->defaultValue('2048M')
  909.                             ->end()
  910.                             ->scalarNode('default_controller_print_page')
  911.                                 ->defaultValue('App\\Controller\\Web2printController::defaultAction')
  912.                             ->end()
  913.                             ->scalarNode('default_controller_print_container')
  914.                                 ->defaultValue('App\\Controller\\Web2printController::containerAction')
  915.                             ->end()
  916.                             ->booleanNode('enableInDefaultView')
  917.                                 ->defaultValue(false)
  918.                             ->end()
  919.                             ->scalarNode('generalTool')
  920.                                 ->defaultValue('')
  921.                             ->end()
  922.                             ->scalarNode('generalDocumentSaveMode')->end()
  923.                             ->scalarNode('pdfreactorVersion')->end()
  924.                             ->scalarNode('pdfreactorProtocol')->end()
  925.                             ->scalarNode('pdfreactorServer')->end()
  926.                             ->scalarNode('pdfreactorServerPort')->end()
  927.                             ->scalarNode('pdfreactorBaseUrl')->end()
  928.                             ->scalarNode('pdfreactorApiKey')->end()
  929.                             ->scalarNode('pdfreactorLicence')->end()
  930.                             ->booleanNode('pdfreactorEnableLenientHttpsMode')->end()
  931.                             ->booleanNode('pdfreactorEnableDebugMode')->end()
  932.                             ->scalarNode('wkhtmltopdfBin')->end()
  933.                             ->variableNode('wkhtml2pdfOptions')->end()
  934.                             ->scalarNode('wkhtml2pdfHostname')->end()
  935.                             ->scalarNode('headlessChromeSettings')->end()
  936.                         ->end()
  937.                 ->end()
  938.                 ->integerNode('auto_save_interval')
  939.                     ->defaultValue(60)
  940.                 ->end()
  941.                 ->arrayNode('static_page_router')
  942.                     ->addDefaultsIfNotSet()
  943.                     ->children()
  944.                         ->booleanNode('enabled')
  945.                             ->defaultFalse()
  946.                             ->info('Enable Static Page router for document when using remote storage for generated pages')
  947.                         ->end()
  948.                         ->scalarNode('route_pattern')
  949.                             ->defaultNull()
  950.                             ->info('Optionally define route patterns to lookup static pages. Regular Expressions like: /^\/en\/Magazine/')
  951.                         ->end()
  952.                 ->end()
  953.             ->end();
  954.     }
  955.     /**
  956.      * Add implementation node config (map, prefixes)
  957.      *
  958.      * @param ArrayNodeDefinition $node
  959.      * @param string $name
  960.      */
  961.     private function addImplementationLoaderNode(ArrayNodeDefinition $node$name)
  962.     {
  963.         $node
  964.             ->children()
  965.                 ->arrayNode($name)
  966.                     ->addDefaultsIfNotSet()
  967.                     ->children()
  968.                         ->arrayNode('map')
  969.                             ->useAttributeAsKey('name')
  970.                             ->prototype('scalar')->end()
  971.                         ->end()
  972.                         ->arrayNode('prefixes')
  973.                             ->prototype('scalar')->end()
  974.                         ->end()
  975.                     ->end()
  976.                 ->end()
  977.             ->end();
  978.     }
  979.     private function addRoutingNode(ArrayNodeDefinition $rootNode)
  980.     {
  981.         $rootNode
  982.             ->children()
  983.                 ->arrayNode('routing')
  984.                     ->addDefaultsIfNotSet()
  985.                     ->children()
  986.                         ->booleanNode('allow_processing_unpublished_fallback_document')
  987.                             ->beforeNormalization()
  988.                                 ->ifString()
  989.                                 ->then(function ($v) {
  990.                                     return (bool)$v;
  991.                                 })
  992.                             ->end()
  993.                             ->defaultFalse()
  994.                             ->setDeprecated(
  995.                                 'pimcore/pimcore',
  996.                                 '10.1',
  997.                                 'The "%node%" option is deprecated since Pimcore 10.1, it will be removed in Pimcore 11.'
  998.                             )
  999.                         ->end()
  1000.                         ->arrayNode('direct_route_document_types')
  1001.                             ->scalarPrototype()->end()
  1002.                         ->end()
  1003.                         ->arrayNode('static')
  1004.                             ->addDefaultsIfNotSet()
  1005.                             ->children()
  1006.                                 ->arrayNode('locale_params')
  1007.                                     ->info('Route params from this list will be mapped to _locale if _locale is not set explicitely')
  1008.                                     ->prototype('scalar')
  1009.                                     ->defaultValue([])
  1010.                                 ->end()
  1011.                             ->end()
  1012.                         ->end()
  1013.                     ->end()
  1014.                 ->end();
  1015.     }
  1016.     /**
  1017.      * Add context config
  1018.      *
  1019.      * @param ArrayNodeDefinition $rootNode
  1020.      */
  1021.     private function addContextNode(ArrayNodeDefinition $rootNode)
  1022.     {
  1023.         $contextNode $rootNode->children()
  1024.             ->arrayNode('context')
  1025.             ->useAttributeAsKey('name');
  1026.         $prototype $contextNode->prototype('array');
  1027.         // define routes child on each context entry
  1028.         $this->addRoutesChild($prototype'routes');
  1029.     }
  1030.     /**
  1031.      * Add admin config
  1032.      *
  1033.      * @param ArrayNodeDefinition $rootNode
  1034.      */
  1035.     private function addAdminNode(ArrayNodeDefinition $rootNode)
  1036.     {
  1037.         $adminNode $rootNode->children()
  1038.             ->arrayNode('admin')
  1039.             ->ignoreExtraKeys()
  1040.             ->addDefaultsIfNotSet();
  1041.         // add session attribute bag config
  1042.         $this->addAdminSessionAttributeBags($adminNode);
  1043.         // unauthenticated routes won't be double checked for authentication in AdminControllerListener
  1044.         $this->addRoutesChild($adminNode'unauthenticated_routes');
  1045.         $adminNode
  1046.             ->children()
  1047.                 ->arrayNode('translations')
  1048.                     ->addDefaultsIfNotSet()
  1049.                     ->children()
  1050.                         ->scalarNode('path')->defaultNull()->end()
  1051.                     ->end()
  1052.                 ->end()
  1053.             ->end();
  1054.     }
  1055.     /**
  1056.      * @param ArrayNodeDefinition $adminNode
  1057.      */
  1058.     private function addAdminSessionAttributeBags(ArrayNodeDefinition $adminNode)
  1059.     {
  1060.         // Normalizes session bag config. Allows the following formats (all formats will be
  1061.         // normalized to the third format.
  1062.         //
  1063.         // attribute_bags:
  1064.         //      - foo
  1065.         //      - bar
  1066.         //
  1067.         // attribute_bags:
  1068.         //      foo: _foo
  1069.         //      bar: _bar
  1070.         //
  1071.         // attribute_bags:
  1072.         //      foo:
  1073.         //          storage_key: _foo
  1074.         //      bar:
  1075.         //          storage_key: _bar
  1076.         $normalizers = [
  1077.             'assoc' => function (array $array) {
  1078.                 $result = [];
  1079.                 foreach ($array as $name => $value) {
  1080.                     if (null === $value) {
  1081.                         $value = [
  1082.                             'storage_key' => '_' $name,
  1083.                         ];
  1084.                     }
  1085.                     if (is_string($value)) {
  1086.                         $value = [
  1087.                             'storage_key' => $value,
  1088.                         ];
  1089.                     }
  1090.                     $result[$name] = $value;
  1091.                 }
  1092.                 return $result;
  1093.             },
  1094.             'sequential' => function (array $array) {
  1095.                 $result = [];
  1096.                 foreach ($array as $name) {
  1097.                     $result[$name] = [
  1098.                         'storage_key' => '_' $name,
  1099.                     ];
  1100.                 }
  1101.                 return $result;
  1102.             },
  1103.         ];
  1104.         $adminNode
  1105.             ->children()
  1106.                 ->arrayNode('session')
  1107.                     ->addDefaultsIfNotSet()
  1108.                     ->children()
  1109.                         ->arrayNode('attribute_bags')
  1110.                             ->useAttributeAsKey('name')
  1111.                             ->beforeNormalization()
  1112.                                 ->ifArray()->then(function ($v) use ($normalizers) {
  1113.                                     if (isAssocArray($v)) {
  1114.                                         return $normalizers['assoc']($v);
  1115.                                     } else {
  1116.                                         return $normalizers['sequential']($v);
  1117.                                     }
  1118.                                 })
  1119.                             ->end()
  1120.                             ->example([
  1121.                                 ['foo''bar'],
  1122.                                 [
  1123.                                     'foo' => '_foo',
  1124.                                     'bar' => '_bar',
  1125.                                 ],
  1126.                                 [
  1127.                                     'foo' => [
  1128.                                         'storage_key' => '_foo',
  1129.                                     ],
  1130.                                     'bar' => [
  1131.                                         'storage_key' => '_bar',
  1132.                                     ],
  1133.                                 ],
  1134.                             ])
  1135.                             ->prototype('array')
  1136.                                 ->children()
  1137.                                     ->scalarNode('storage_key')
  1138.                                         ->defaultNull()
  1139.                                     ->end()
  1140.                                 ->end()
  1141.                             ->end()
  1142.                         ->end()
  1143.                     ->end()
  1144.                 ->end()
  1145.             ->end();
  1146.     }
  1147.     private function addSecurityNode(ArrayNodeDefinition $rootNode)
  1148.     {
  1149.         $rootNode
  1150.             ->children()
  1151.                 ->arrayNode('security')
  1152.                     ->addDefaultsIfNotSet()
  1153.                     ->children()
  1154.                         ->enumNode('factory_type')
  1155.                             ->values(['encoder''password_hasher'])
  1156.                             ->defaultValue('encoder')
  1157.                         ->end()
  1158.                         ->arrayNode('encoder_factories')
  1159.                             ->info('Encoder factories to use as className => factory service ID mapping')
  1160.                             ->example([
  1161.                                 'App\Model\DataObject\User1' => [
  1162.                                     'id' => 'website_demo.security.encoder_factory2',
  1163.                                 ],
  1164.                                 'App\Model\DataObject\User2' => 'website_demo.security.encoder_factory2',
  1165.                             ])
  1166.                             ->useAttributeAsKey('class')
  1167.                             ->prototype('array')
  1168.                             ->beforeNormalization()->ifString()->then(function ($v) {
  1169.                                 return ['id' => $v];
  1170.                             })->end()
  1171.                             ->children()
  1172.                                 ->scalarNode('id')->end()
  1173.                             ->end()
  1174.                             ->end()
  1175.                         ->end()
  1176.                         ->arrayNode('password_hasher_factories')
  1177.                             ->info('Password hasher factories to use as className => factory service ID mapping')
  1178.                             ->example([
  1179.                                 'App\Model\DataObject\User1' => [
  1180.                                     'id' => 'website_demo.security.encoder_factory2',
  1181.                                 ],
  1182.                                 'App\Model\DataObject\User2' => 'website_demo.security.encoder_factory2',
  1183.                             ])
  1184.                             ->useAttributeAsKey('class')
  1185.                             ->prototype('array')
  1186.                             ->beforeNormalization()->ifString()->then(function ($v) {
  1187.                                 return ['id' => $v];
  1188.                             })->end()
  1189.                             ->children()
  1190.                             ->scalarNode('id')->end()
  1191.                             ->end()
  1192.                         ->end()
  1193.                     ->end()
  1194.                 ->end()
  1195.             ->end();
  1196.     }
  1197.     /**
  1198.      * Configure exclude paths for web profiler toolbar
  1199.      *
  1200.      * @param ArrayNodeDefinition $rootNode
  1201.      */
  1202.     private function addWebProfilerNode(ArrayNodeDefinition $rootNode)
  1203.     {
  1204.         $webProfilerNode $rootNode->children()
  1205.             ->arrayNode('web_profiler')
  1206.                 ->example([
  1207.                     'toolbar' => [
  1208.                         'excluded_routes' => [
  1209.                             ['path' => '^/test/path'],
  1210.                         ],
  1211.                     ],
  1212.                 ])
  1213.                 ->addDefaultsIfNotSet();
  1214.         $toolbarNode $webProfilerNode->children()
  1215.             ->arrayNode('toolbar')
  1216.                 ->addDefaultsIfNotSet();
  1217.         $this->addRoutesChild($toolbarNode'excluded_routes');
  1218.     }
  1219.     /**
  1220.      * Add a route prototype child
  1221.      *
  1222.      * @param ArrayNodeDefinition $parent
  1223.      * @param string $name
  1224.      */
  1225.     private function addRoutesChild(ArrayNodeDefinition $parent$name)
  1226.     {
  1227.         $node $parent->children()->arrayNode($name);
  1228.         /** @var ArrayNodeDefinition $prototype */
  1229.         $prototype $node->prototype('array');
  1230.         $prototype
  1231.             ->beforeNormalization()
  1232.                 ->ifNull()->then(function () {
  1233.                     return [];
  1234.                 })
  1235.             ->end()
  1236.             ->children()
  1237.                 ->scalarNode('path')->defaultFalse()->end()
  1238.                 ->scalarNode('route')->defaultFalse()->end()
  1239.                 ->scalarNode('host')->defaultFalse()->end()
  1240.                 ->arrayNode('methods')
  1241.                     ->prototype('scalar')->end()
  1242.                 ->end()
  1243.             ->end();
  1244.     }
  1245.     /**
  1246.      * Add cache config
  1247.      *
  1248.      * @param ArrayNodeDefinition $rootNode
  1249.      */
  1250.     private function addCacheNode(ArrayNodeDefinition $rootNode)
  1251.     {
  1252.         $rootNode->children()
  1253.             ->arrayNode('full_page_cache')
  1254.                 ->ignoreExtraKeys()
  1255.                 ->canBeDisabled()
  1256.                 ->addDefaultsIfNotSet()
  1257.                 ->children()
  1258.                     ->scalarNode('lifetime')
  1259.                         ->info('Optional output-cache lifetime (in seconds) after the cache expires, if not defined the cache will be cleaned on every action inside the CMS, otherwise not (for high traffic sites)')
  1260.                         ->defaultNull()
  1261.                     ->end()
  1262.                     ->scalarNode('exclude_patterns')
  1263.                         ->info('Regular Expressions like: /^\/dir\/toexclude/')
  1264.                     ->end()
  1265.                     ->scalarNode('exclude_cookie')
  1266.                         ->info('Comma separated list of cookie names, that will automatically disable the full-page cache')
  1267.                     ->end()
  1268.                 ->end()
  1269.             ->end();
  1270.     }
  1271.     /**
  1272.      * Adds configuration for email source adapters
  1273.      *
  1274.      * @param ArrayNodeDefinition $rootNode
  1275.      */
  1276.     private function addEmailNode(ArrayNodeDefinition $rootNode)
  1277.     {
  1278.         $rootNode
  1279.             ->children()
  1280.                 ->arrayNode('email')
  1281.                 ->addDefaultsIfNotSet()
  1282.                     ->children()
  1283.                         ->arrayNode('sender')
  1284.                             ->addDefaultsIfNotSet()
  1285.                             ->children()
  1286.                                 ->scalarNode('name')
  1287.                                     ->defaultValue('')
  1288.                                 ->end()
  1289.                                 ->scalarNode('email')
  1290.                                     ->defaultValue('')
  1291.                                 ->end()
  1292.                             ->end()
  1293.                         ->end()
  1294.                         ->arrayNode('return')
  1295.                             ->addDefaultsIfNotSet()
  1296.                             ->children()
  1297.                                 ->scalarNode('name')
  1298.                                     ->defaultValue('')
  1299.                                 ->end()
  1300.                                 ->scalarNode('email')
  1301.                                     ->defaultValue('')
  1302.                                 ->end()
  1303.                             ->end()
  1304.                         ->end()
  1305.                         ->arrayNode('debug')
  1306.                             ->addDefaultsIfNotSet()
  1307.                             ->children()
  1308.                                 ->scalarNode('email_addresses')
  1309.                                     ->defaultValue('')
  1310.                                 ->end()
  1311.                             ->end()
  1312.                         ->end()
  1313.                         ->scalarNode('usespecific')
  1314.                             ->defaultFalse()
  1315.                         ->end()
  1316.                     ->end()
  1317.                 ->end()
  1318.             ->end();
  1319.     }
  1320.     /**
  1321.      * Adds configuration tree for newsletter source adapters
  1322.      *
  1323.      * @param ArrayNodeDefinition $rootNode
  1324.      */
  1325.     private function addNewsletterNode(ArrayNodeDefinition $rootNode)
  1326.     {
  1327.         $rootNode
  1328.             ->children()
  1329.                 ->arrayNode('newsletter')
  1330.                     ->addDefaultsIfNotSet()
  1331.                     ->children()
  1332.                         ->arrayNode('sender')
  1333.                             ->children()
  1334.                                 ->scalarNode('name')->end()
  1335.                                 ->scalarNode('email')->end()
  1336.                             ->end()
  1337.                         ->end()
  1338.                         ->arrayNode('return')
  1339.                             ->children()
  1340.                                 ->scalarNode('name')->end()
  1341.                                 ->scalarNode('email')->end()
  1342.                             ->end()
  1343.                         ->end()
  1344.                         ->scalarNode('method')
  1345.                             ->defaultNull()
  1346.                         ->end()
  1347.                         ->arrayNode('debug')
  1348.                             ->children()
  1349.                                 ->scalarNode('email_addresses')
  1350.                                     ->defaultValue('')
  1351.                                 ->end()
  1352.                             ->end()
  1353.                         ->end()
  1354.                         ->booleanNode('use_specific')
  1355.                             ->beforeNormalization()
  1356.                                 ->ifString()
  1357.                                 ->then(function ($v) {
  1358.                                     return (bool)$v;
  1359.                                 })
  1360.                             ->end()
  1361.                         ->end()
  1362.                         ->arrayNode('source_adapters')
  1363.                             ->useAttributeAsKey('name')
  1364.                                 ->prototype('scalar')
  1365.                             ->end()
  1366.                         ->end()
  1367.                     ->end()
  1368.                 ->end()
  1369.             ->end();
  1370.     }
  1371.     /**
  1372.      * Adds configuration tree for custom report adapters
  1373.      *
  1374.      * @param ArrayNodeDefinition $rootNode
  1375.      */
  1376.     private function addCustomReportsNode(ArrayNodeDefinition $rootNode)
  1377.     {
  1378.         $rootNode
  1379.             ->children()
  1380.                 ->arrayNode('custom_report')
  1381.                     ->addDefaultsIfNotSet()
  1382.                     ->children()
  1383.                         ->arrayNode('definitions')
  1384.                                 ->normalizeKeys(false)
  1385.                                 ->prototype('array')
  1386.                                     ->children()
  1387.                                         ->scalarNode('id')->end()
  1388.                                         ->scalarNode('name')->end()
  1389.                                         ->scalarNode('niceName')->end()
  1390.                                         ->scalarNode('sql')->end()
  1391.                                         ->scalarNode('group')->end()
  1392.                                         ->scalarNode('groupIconClass')->end()
  1393.                                         ->scalarNode('iconClass')->end()
  1394.                                         ->booleanNode('menuShortcut')->end()
  1395.                                         ->scalarNode('reportClass')->end()
  1396.                                         ->scalarNode('chartType')->end()
  1397.                                         ->scalarNode('pieColumn')->end()
  1398.                                         ->scalarNode('pieLabelColumn')->end()
  1399.                                         ->variableNode('xAxis')->end()
  1400.                                         ->variableNode('yAxis')->end()
  1401.                                         ->integerNode('modificationDate')->end()
  1402.                                         ->integerNode('creationDate')->end()
  1403.                                         ->booleanNode('shareGlobally')->end()
  1404.                                         ->variableNode('sharedUserNames')->end()
  1405.                                         ->variableNode('sharedRoleNames')->end()
  1406.                                         ->arrayNode('dataSourceConfig')
  1407.                                             ->prototype('variable')
  1408.                                             ->end()
  1409.                                         ->end()
  1410.                                         ->arrayNode('columnConfiguration')
  1411.                                             ->prototype('variable')
  1412.                                             ->end()
  1413.                                         ->end()
  1414.                                     ->end()
  1415.                                 ->end()
  1416.                         ->end()
  1417.                         ->arrayNode('adapters')
  1418.                             ->useAttributeAsKey('name')
  1419.                                 ->prototype('scalar')
  1420.                             ->end()
  1421.                         ->end()
  1422.                     ->end()
  1423.                 ->end()
  1424.             ->end();
  1425.     }
  1426.     private function addTargetingNode(ArrayNodeDefinition $rootNode)
  1427.     {
  1428.         $rootNode
  1429.             ->children()
  1430.                 ->arrayNode('targeting')
  1431.                     ->canBeDisabled()
  1432.                     ->addDefaultsIfNotSet()
  1433.                     ->children()
  1434.                         ->scalarNode('storage_id')
  1435.                             ->info('Service ID of the targeting storage which should be used. This ID will be aliased to ' TargetingStorageInterface::class)
  1436.                             ->defaultValue(CookieStorage::class)
  1437.                             ->cannotBeEmpty()
  1438.                         ->end()
  1439.                         ->arrayNode('session')
  1440.                             ->info('Enables HTTP session support by configuring session bags and the full page cache')
  1441.                             ->canBeEnabled()
  1442.                         ->end()
  1443.                         ->arrayNode('data_providers')
  1444.                             ->useAttributeAsKey('key')
  1445.                                 ->prototype('scalar')
  1446.                             ->end()
  1447.                         ->end()
  1448.                         ->arrayNode('conditions')
  1449.                             ->useAttributeAsKey('key')
  1450.                                 ->prototype('scalar')
  1451.                             ->end()
  1452.                         ->end()
  1453.                         ->arrayNode('action_handlers')
  1454.                             ->useAttributeAsKey('name')
  1455.                                 ->prototype('scalar')
  1456.                             ->end()
  1457.                         ->end()
  1458.                     ->end()
  1459.                 ->end()
  1460.             ->end();
  1461.     }
  1462.     private function addSitemapsNode(ArrayNodeDefinition $rootNode)
  1463.     {
  1464.         $rootNode
  1465.             ->children()
  1466.                 ->arrayNode('sitemaps')
  1467.                     ->addDefaultsIfNotSet()
  1468.                     ->children()
  1469.                         ->arrayNode('generators')
  1470.                             ->useAttributeAsKey('name')
  1471.                             ->prototype('array')
  1472.                                 ->beforeNormalization()
  1473.                                     ->ifString()
  1474.                                     ->then(function ($v) {
  1475.                                         return [
  1476.                                             'enabled' => true,
  1477.                                             'generator_id' => $v,
  1478.                                             'priority' => 0,
  1479.                                         ];
  1480.                                     })
  1481.                                 ->end()
  1482.                                 ->addDefaultsIfNotSet()
  1483.                                 ->canBeDisabled()
  1484.                                 ->children()
  1485.                                     ->scalarNode('generator_id')
  1486.                                         ->cannotBeEmpty()
  1487.                                     ->end()
  1488.                                     ->integerNode('priority')
  1489.                                         ->defaultValue(0)
  1490.                                     ->end()
  1491.                                 ->end()
  1492.                             ->end()
  1493.                         ->end()
  1494.                     ->end()
  1495.                 ->end()
  1496.             ->end()
  1497.         ->end();
  1498.     }
  1499.     private function addWorkflowNode(ArrayNodeDefinition $rootNode)
  1500.     {
  1501.         $rootNode
  1502.             ->children()
  1503.                  ->arrayNode('workflows')
  1504.                         ->useAttributeAsKey('name')
  1505.                         ->prototype('array')
  1506.                             ->children()
  1507.                                 ->arrayNode('placeholders')
  1508.                                     ->info('Placeholder values in this workflow configuration (locale: "%%locale%%") will be replaced by the given placeholder value (eg. "de_AT")')
  1509.                                     ->example([
  1510.                                         'placeholders' => [
  1511.                                             '%%locale%%' => 'de_AT',
  1512.                                         ],
  1513.                                     ])
  1514.                                     ->defaultValue([])
  1515.                                     ->beforeNormalization()
  1516.                                         ->castToArray()
  1517.                                         ->always()
  1518.                                         ->then(function ($placeholders) {
  1519.                                             $this->placeholders $placeholders;
  1520.                                             return $placeholders;
  1521.                                         })
  1522.                                     ->end()
  1523.                                     ->prototype('scalar')->end()
  1524.                                 ->end()
  1525.                                 ->arrayNode('custom_extensions')->ignoreExtraKeys(false)->info('Use this key to attach additional config information to a workflow, for example via bundles, etc.')->end()
  1526.                                 ->booleanNode('enabled')
  1527.                                     ->defaultTrue()
  1528.                                     ->info('Can be used to enable or disable the workflow.')
  1529.                                 ->end()
  1530.                                 ->integerNode('priority')
  1531.                                     ->defaultValue(0)
  1532.                                     ->info('When multiple custom view or permission settings from different places in different workflows are valid, the workflow with the highest priority will be used.')
  1533.                                 ->end()
  1534.                                 ->scalarNode('label')
  1535.                                     ->info('Will be used in the backend interface as nice name for the workflow. If not set the technical workflow name will be used as label too.')
  1536.                                 ->end()
  1537.                                 ->arrayNode('audit_trail')
  1538.                                     ->canBeEnabled()
  1539.                                     ->info('Enable default audit trail feature provided by Symfony. Take a look at the Symfony docs for more details.')
  1540.                                 ->end()
  1541.                                 ->enumNode('type')
  1542.                                     ->values(['workflow''state_machine'])
  1543.                                     ->info('A workflow with type "workflow" can handle multiple places at one time whereas a state_machine provides a finite state_machine (only one place at one time). Take a look at the Symfony docs for more details.')
  1544.                                 ->end()
  1545.                                 ->arrayNode('marking_store')
  1546.                                     ->fixXmlConfig('argument')
  1547.                                     ->children()
  1548.                                         ->enumNode('type')
  1549.                                             ->values(['multiple_state''single_state''state_table''data_object_multiple_state''data_object_splitted_state'])
  1550.                                         ->end()
  1551.                                         ->arrayNode('arguments')
  1552.                                             ->beforeNormalization()
  1553.                                                 ->always()
  1554.                                                 ->then(function ($arguments) {
  1555.                                                     if (is_string($arguments)) {
  1556.                                                         $arguments = [$arguments];
  1557.                                                     }
  1558.                                                     if (!empty($this->placeholders)) {
  1559.                                                         $arguments $this->placeholderProcessor->mergePlaceholders($arguments$this->placeholders);
  1560.                                                     }
  1561.                                                     return $arguments;
  1562.                                                 })
  1563.                                             ->end()
  1564.                                             ->requiresAtLeastOneElement()
  1565.                                             ->prototype('variable')
  1566.                                             ->end()
  1567.                                         ->end()
  1568.                                         ->scalarNode('service')
  1569.                                             ->cannotBeEmpty()
  1570.                                         ->end()
  1571.                                     ->end()
  1572.                                     ->info('Handles the way how the state/place is stored. If not defined "state_table" will be used as default. Take a look at @TODO for a description of the different types.')
  1573.                                     ->validate()
  1574.                                         ->ifTrue(function ($v) {
  1575.                                             return isset($v['type']) && isset($v['service']);
  1576.                                         })
  1577.                                         ->thenInvalid('"type" and "service" cannot be used together.')
  1578.                                     ->end()
  1579.                                     ->validate()
  1580.                                         ->ifTrue(function ($v) {
  1581.                                             return !empty($v['arguments']) && isset($v['service']);
  1582.                                         })
  1583.                                         ->thenInvalid('"arguments" and "service" cannot be used together.')
  1584.                                     ->end()
  1585.                                 ->end()
  1586.                                 ->arrayNode('supports')
  1587.                                     ->beforeNormalization()
  1588.                                         ->ifString()
  1589.                                         ->then(function ($v) {
  1590.                                             return [$v];
  1591.                                         })
  1592.                                     ->end()
  1593.                                     ->prototype('scalar')
  1594.                                         ->cannotBeEmpty()
  1595.                                     ->end()
  1596.                                     ->info('List of supported entity classes. Take a look at the Symfony docs for more details.')
  1597.                                     ->example(['\Pimcore\Model\DataObject\Product'])
  1598.                                 ->end()
  1599.                                 ->arrayNode('support_strategy')
  1600.                                     ->fixXmlConfig('argument')
  1601.                                     ->children()
  1602.                                         ->enumNode('type')
  1603.                                             ->values(['expression'])
  1604.                                             ->info('Type "expression": a symfony expression to define a criteria.')
  1605.                                         ->end()
  1606.                                         ->arrayNode('arguments')
  1607.                                             ->beforeNormalization()
  1608.                                                 ->ifString()
  1609.                                                 ->then(function ($v) {
  1610.                                                     return [$v];
  1611.                                                 })
  1612.                                             ->end()
  1613.                                             ->requiresAtLeastOneElement()
  1614.                                             ->prototype('variable')
  1615.                                             ->end()
  1616.                                         ->end()
  1617.                                         ->scalarNode('service')
  1618.                                             ->cannotBeEmpty()
  1619.                                             ->info('Define a custom service to handle the logic. Take a look at the Symfony docs for more details.')
  1620.                                         ->end()
  1621.                                     ->end()
  1622.                                     ->validate()
  1623.                                         ->ifTrue(function ($v) {
  1624.                                             return isset($v['type']) && isset($v['service']);
  1625.                                         })
  1626.                                         ->thenInvalid('"type" and "service" cannot be used together.')
  1627.                                     ->end()
  1628.                                     ->validate()
  1629.                                         ->ifTrue(function ($v) {
  1630.                                             return !empty($v['arguments']) && isset($v['service']);
  1631.                                         })
  1632.                                         ->thenInvalid('"arguments" and "service" cannot be used together.')
  1633.                                     ->end()
  1634.                                     ->info('Can be used to implement a special logic which subjects are supported by the workflow. For example only products matching certain criteria.')
  1635.                                     ->example([
  1636.                                         'type' => 'expression',
  1637.                                         'arguments' => [
  1638.                                             '\Pimcore\Model\DataObject\Product',
  1639.                                             'subject.getProductType() == "article" and is_fully_authenticated() and "ROLE_PIMCORE_ADMIN" in roles',
  1640.                                         ],
  1641.                                     ])
  1642.                                 ->end()
  1643.                                 ->arrayNode('initial_markings')
  1644.                                     ->info('Can be used to set the initial places (markings) for a workflow. Note that this option is Symfony 4.3+ only')
  1645.                                     ->beforeNormalization()
  1646.                                         ->ifString()
  1647.                                             ->then(function ($v) {
  1648.                                                 return [$v];
  1649.                                             })
  1650.                                         ->end()
  1651.                                         ->requiresAtLeastOneElement()
  1652.                                         ->prototype('scalar')
  1653.                                         ->cannotBeEmpty()
  1654.                                     ->end()
  1655.                                 ->end()
  1656.                                 ->arrayNode('places')
  1657.                                     ->prototype('array')
  1658.                                         ->children()
  1659.                                             ->scalarNode('label')->info('Nice name which will be used in the Pimcore backend.')->end()
  1660.                                             ->scalarNode('title')->info('Title/tooltip for this place when it is displayed in the header of the Pimcore element detail view in the backend.')->defaultValue('')->end()
  1661.                                             ->scalarNode('color')->info('Color of the place which will be used in the Pimcore backend.')->defaultValue('#bfdadc')->end()
  1662.                                             ->booleanNode('colorInverted')->info('If set to true the color will be used as border and font color otherwise as background color.')->defaultFalse()->end()
  1663.                                             ->booleanNode('visibleInHeader')->info('If set to false, the place will be hidden in the header of the Pimcore element detail view in the backend.')->defaultTrue()->end()
  1664.                                             ->arrayNode('permissions')
  1665.                                                 ->prototype('array')
  1666.                                                     ->children()
  1667.                                                         ->scalarNode('condition')->info('A symfony expression can be configured here. The first set of permissions which are matching the condition will be used.')->end()
  1668.                                                         ->booleanNode('save')->info('save permission as it can be configured in Pimcore workplaces')->end()
  1669.                                                         ->booleanNode('publish')->info('publish permission as it can be configured in Pimcore workplaces')->end()
  1670.                                                         ->booleanNode('unpublish')->info('unpublish permission as it can be configured in Pimcore workplaces')->end()
  1671.                                                         ->booleanNode('delete')->info('delete permission as it can be configured in Pimcore workplaces')->end()
  1672.                                                         ->booleanNode('rename')->info('rename permission as it can be configured in Pimcore workplaces')->end()
  1673.                                                         ->booleanNode('view')->info('view permission as it can be configured in Pimcore workplaces')->end()
  1674.                                                         ->booleanNode('settings')->info('settings permission as it can be configured in Pimcore workplaces')->end()
  1675.                                                         ->booleanNode('versions')->info('versions permission as it can be configured in Pimcore workplaces')->end()
  1676.                                                         ->booleanNode('properties')->info('properties permission as it can be configured in Pimcore workplaces')->end()
  1677.                                                         ->booleanNode('modify')->info('a short hand for save, publish, unpublish, delete + rename')->end()
  1678.                                                         ->scalarNode('objectLayout')->info('if set, the user will see the configured custom data object layout')->end()
  1679.                                                     ->end()
  1680.                                                 ->end()
  1681.                                             ->end()
  1682.                                         ->end()
  1683.                                     ->end()
  1684.                                     ->beforeNormalization()
  1685.                                         ->always()
  1686.                                         ->then(function ($places) {
  1687.                                             if (!empty($this->placeholders)) {
  1688.                                                 foreach ($places as $name => $place) {
  1689.                                                     $places[$name] = $this->placeholderProcessor->mergePlaceholders($place$this->placeholders);
  1690.                                                 }
  1691.                                             }
  1692.                                             return $places;
  1693.                                         })
  1694.                                     ->end()
  1695.                                     ->example([
  1696.                                         'places' => [
  1697.                                             'closed' => [
  1698.                                                 'label' => 'close product',
  1699.                                                 'permissions' => [
  1700.                                                     [
  1701.                                                         'condition' => "is_fully_authenticated() and 'ROLE_PIMCORE_ADMIN' in roles",
  1702.                                                         'modify' => false,
  1703.                                                     ],
  1704.                                                     [
  1705.                                                         'modify' => false,
  1706.                                                         'objectLayout' => 2,
  1707.                                                     ],
  1708.                                                 ],
  1709.                                             ],
  1710.                                         ],
  1711.                                     ])
  1712.                                 ->end()
  1713.                                 ->arrayNode('transitions')
  1714.                                     ->beforeNormalization()
  1715.                                         ->always()
  1716.                                         ->then(function ($transitions) {
  1717.                                             // It's an indexed array, we let the validation occurs
  1718.                                             if (isset($transitions[0])) {
  1719.                                                 return $transitions;
  1720.                                             }
  1721.                                             foreach ($transitions as $name => $transition) {
  1722.                                                 if (array_key_exists('name', (array) $transition)) {
  1723.                                                     continue;
  1724.                                                 }
  1725.                                                 $transition['name'] = $name;
  1726.                                                 $transitions[$name] = $transition;
  1727.                                             }
  1728.                                             return $transitions;
  1729.                                         })
  1730.                                     ->end()
  1731.                                     ->isRequired()
  1732.                                     ->requiresAtLeastOneElement()
  1733.                                     ->prototype('array')
  1734.                                         ->children()
  1735.                                             ->scalarNode('name')
  1736.                                                 ->isRequired()
  1737.                                                 ->cannotBeEmpty()
  1738.                                             ->end()
  1739.                                             ->scalarNode('guard')
  1740.                                                 ->cannotBeEmpty()
  1741.                                                 ->info('An expression to block the transition')
  1742.                                                 ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')
  1743.                                             ->end()
  1744.                                             ->arrayNode('from')
  1745.                                                 ->beforeNormalization()
  1746.                                                     ->ifString()
  1747.                                                     ->then(function ($v) {
  1748.                                                         return [$v];
  1749.                                                     })
  1750.                                                 ->end()
  1751.                                                 ->requiresAtLeastOneElement()
  1752.                                                 ->prototype('scalar')
  1753.                                                     ->cannotBeEmpty()
  1754.                                                 ->end()
  1755.                                             ->end()
  1756.                                             ->arrayNode('to')
  1757.                                                 ->beforeNormalization()
  1758.                                                     ->ifString()
  1759.                                                     ->then(function ($v) {
  1760.                                                         return [$v];
  1761.                                                     })
  1762.                                                 ->end()
  1763.                                                 ->requiresAtLeastOneElement()
  1764.                                                 ->prototype('scalar')
  1765.                                                     ->cannotBeEmpty()
  1766.                                                 ->end()
  1767.                                             ->end()
  1768.                                             ->arrayNode('options')
  1769.                                                 ->children()
  1770.                                                     ->scalarNode('label')->info('Nice name for the Pimcore backend.')->end()
  1771.                                                     ->arrayNode('notes')
  1772.                                                         ->children()
  1773.                                                             ->booleanNode('commentEnabled')->defaultFalse()->info('If enabled a detail window will open when the user executes the transition. In this detail view the user be asked to enter a "comment". This comment then will be used as comment for the notes/events feature.')->end()
  1774.                                                             ->booleanNode('commentRequired')->defaultFalse()->info('Set this to true if the comment should be a required field.')->end()
  1775.                                                             ->scalarNode('commentSetterFn')->info('Can be used for data objects. The comment will be saved to the data object additionally to the notes/events through this setter function.')->end()
  1776.                                                             ->scalarNode('commentGetterFn')->info('Can be used for data objects to prefill the comment field with data from the data object.')->end()
  1777.                                                             ->scalarNode('type')->defaultValue('Status update')->info('Set\'s the type string in the saved note.')->end()
  1778.                                                             ->scalarNode('title')->info('An optional alternative "title" for the note, if blank the actions transition result is used.')->end()
  1779.                                                             ->arrayNode('additionalFields')
  1780.                                                                 ->prototype('array')
  1781.                                                                     ->children()
  1782.                                                                         ->scalarNode('name')->isRequired()->info('The technical name used in the input form.')->end()
  1783.                                                                         ->enumNode('fieldType')
  1784.                                                                             ->isRequired()
  1785.                                                                             ->values(['input''numeric''textarea''select''datetime''date''user''checkbox'])
  1786.                                                                             ->info('The data component name/field type.')
  1787.                                                                         ->end()
  1788.                                                                         ->scalarNode('title')->info('The label used by the field')->end()
  1789.                                                                         ->booleanNode('required')->defaultFalse()->info('Whether or not the field is required.')->end()
  1790.                                                                         ->scalarNode('setterFn')->info('Optional setter function (available in the element, for example in the updated object), if not specified, data will be added to notes. The Workflow manager will call the function with the whole field data.')->end()
  1791.                                                                         ->arrayNode('fieldTypeSettings')
  1792.                                                                              ->prototype('variable')->end()
  1793.                                                                              ->info('Will be passed to the underlying Pimcore data object field type. Can be used to configure the options of a select box for example.')
  1794.                                                                         ->end()
  1795.                                                                     ->end()
  1796.                                                                 ->end()
  1797.                                                                 ->info('Add additional field to the transition detail window.')
  1798.                                                             ->end()
  1799.                                                             ->arrayNode('customHtml')
  1800.                                                                 ->children()
  1801.                                                                     ->enumNode('position')
  1802.                                                                         ->values(['top''center''bottom'])
  1803.                                                                         ->defaultValue('top')
  1804.                                                                         ->info('Set position of custom HTML inside modal (top, center, bottom).')
  1805.                                                                     ->end()
  1806.                                                                     ->scalarNode('service')
  1807.                                                                         ->cannotBeEmpty()
  1808.                                                                         ->info('Define a custom service for rendering custom HTML within the note modal.')
  1809.                                                                     ->end()
  1810.                                                                 ->end()
  1811.                                                             ->end()
  1812.                                                         ->end()
  1813.                                                     ->end()
  1814.                                                     ->scalarNode('iconClass')->info('Css class to define the icon which will be used in the actions button in the backend.')->end()
  1815.                                                     ->scalarNode('objectLayout')->defaultValue(false)->info('Forces an object layout after the transition was performed. This objectLayout setting overrules all objectLayout settings within the places configs.')->end()
  1816.                                                     ->arrayNode('notificationSettings')
  1817.                                                         ->prototype('array')
  1818.                                                             ->children()
  1819.                                                                 ->scalarNode('condition')->info('A symfony expression can be configured here. All sets of notification which are matching the condition will be used.')->end()
  1820.                                                                 ->arrayNode('notifyUsers')
  1821.                                                                     ->prototype('scalar')
  1822.                                                                         ->cannotBeEmpty()
  1823.                                                                     ->end()
  1824.                                                                     ->info('Send an email notification to a list of users (user names) when the transition get\'s applied')
  1825.                                                                 ->end()
  1826.                                                                 ->arrayNode('notifyRoles')
  1827.                                                                     ->prototype('scalar')
  1828.                                                                         ->cannotBeEmpty()
  1829.                                                                     ->end()
  1830.                                                                     ->info('Send an email notification to a list of user roles (role names) when the transition get\'s applied')
  1831.                                                                 ->end()
  1832.                                                                 ->arrayNode('channelType')
  1833.                                                                     ->requiresAtLeastOneElement()
  1834.                                                                     ->enumPrototype()
  1835.                                                                         ->values([NotificationSubscriber::NOTIFICATION_CHANNEL_MAILNotificationSubscriber::NOTIFICATION_CHANNEL_PIMCORE_NOTIFICATION])
  1836.                                                                         ->cannotBeEmpty()
  1837.                                                                         ->defaultValue(NotificationSubscriber::NOTIFICATION_CHANNEL_MAIL)
  1838.                                                                     ->end()
  1839.                                                                     ->info('Define which channel notification should be sent to, possible values "' NotificationSubscriber::NOTIFICATION_CHANNEL_MAIL '" and "' NotificationSubscriber::NOTIFICATION_CHANNEL_PIMCORE_NOTIFICATION '", default value is "' NotificationSubscriber::NOTIFICATION_CHANNEL_MAIL '".')
  1840.                                                                     ->addDefaultChildrenIfNoneSet()
  1841.                                                                 ->end()
  1842.                                                                 ->enumNode('mailType')
  1843.                                                                     ->values([NotificationSubscriber::MAIL_TYPE_TEMPLATENotificationSubscriber::MAIL_TYPE_DOCUMENT])
  1844.                                                                     ->defaultValue(NotificationSubscriber::MAIL_TYPE_TEMPLATE)
  1845.                                                                     ->info('Type of mail source.')
  1846.                                                                 ->end()
  1847.                                                                 ->scalarNode('mailPath')
  1848.                                                                     ->defaultValue(NotificationSubscriber::DEFAULT_MAIL_TEMPLATE_PATH)
  1849.                                                                     ->info('Path to mail source - either Symfony path to template or fullpath to Pimcore document. Optional use ' NotificationEmailService::MAIL_PATH_LANGUAGE_PLACEHOLDER ' as placeholder for language.')
  1850.                                                                 ->end()
  1851.                                                             ->end()
  1852.                                                         ->end()
  1853.                                                     ->end()
  1854.                                                     ->enumNode('changePublishedState')
  1855.                                                         ->values([ChangePublishedStateSubscriber::NO_CHANGEChangePublishedStateSubscriber::FORCE_UNPUBLISHEDChangePublishedStateSubscriber::FORCE_PUBLISHEDChangePublishedStateSubscriber::SAVE_VERSION])
  1856.                                                         ->defaultValue(ChangePublishedStateSubscriber::NO_CHANGE)
  1857.                                                         ->info('Change published state of element while transition (only available for documents and data objects).')
  1858.                                                     ->end()
  1859.                                                 ->end()
  1860.                                             ->end()
  1861.                                         ->end()
  1862.                                     ->end()
  1863.                                     ->example([
  1864.                                         'close_product' => [
  1865.                                             'from' => 'open',
  1866.                                             'to' => 'closed',
  1867.                                             'options' => [
  1868.                                                 'label' => 'close product',
  1869.                                                 'notes' => [
  1870.                                                     'commentEnabled' => true,
  1871.                                                     'commentRequired' => true,
  1872.                                                     'additionalFields' => [
  1873.                                                         [
  1874.                                                             'name' => 'accept',
  1875.                                                             'title' => 'accept terms',
  1876.                                                             'required' => true,
  1877.                                                             'fieldType' => 'checkbox',
  1878.                                                         ],
  1879.                                                         [
  1880.                                                             'name' => 'select',
  1881.                                                             'title' => 'please select a type',
  1882.                                                             'setterFn' => 'setSpecialWorkflowType',
  1883.                                                             'fieldType' => 'select',
  1884.                                                             'fieldTypeSettings' => [
  1885.                                                                 'options' => [
  1886.                                                                     ['key' => 'Option A''value' => 'a'],
  1887.                                                                     ['key' => 'Option B''value' => 'b'],
  1888.                                                                     ['key' => 'Option C''value' => 'c'],
  1889.                                                                 ],
  1890.                                                             ],
  1891.                                                         ],
  1892.                                                     ],
  1893.                                                 ],
  1894.                                             ],
  1895.                                         ],
  1896.                                     ])
  1897.                                 ->end()
  1898.                                 ->arrayNode('globalActions')
  1899.                                     ->prototype('array')
  1900.                                         ->children()
  1901.                                             ->scalarNode('label')->info('Nice name for the Pimcore backend.')->end()
  1902.                                             ->scalarNode('iconClass')->info('Css class to define the icon which will be used in the actions button in the backend.')->end()
  1903.                                             ->scalarNode('objectLayout')->defaultValue(false)->info('Forces an object layout after the global action was performed. This objectLayout setting overrules all objectLayout settings within the places configs.')->end()
  1904.                                             ->scalarNode('guard')
  1905.                                                 ->cannotBeEmpty()
  1906.                                                 ->info('An expression to block the action')
  1907.                                                 ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')
  1908.                                             ->end()
  1909.                                             ->arrayNode('to')
  1910.                                                 ->beforeNormalization()
  1911.                                                     ->ifString()
  1912.                                                     ->then(function ($v) {
  1913.                                                         return [$v];
  1914.                                                     })
  1915.                                                 ->end()
  1916.                                                 ->requiresAtLeastOneElement()
  1917.                                                 ->prototype('scalar')
  1918.                                                     ->cannotBeEmpty()
  1919.                                                 ->end()
  1920.                                                 ->info('Optionally set the current place of the workflow. Can be used for example to reset the workflow to the initial place.')
  1921.                                             ->end()
  1922.                                             ->arrayNode('notes')
  1923.                                                 ->children()
  1924.                                                     ->booleanNode('commentEnabled')->defaultFalse()->end()
  1925.                                                     ->booleanNode('commentRequired')->defaultFalse()->end()
  1926.                                                     ->scalarNode('commentSetterFn')->end()
  1927.                                                     ->scalarNode('commentGetterFn')->end()
  1928.                                                     ->scalarNode('type')->defaultValue('Status update')->end()
  1929.                                                     ->scalarNode('title')->end()
  1930.                                                     ->arrayNode('additionalFields')
  1931.                                                         ->prototype('array')
  1932.                                                             ->children()
  1933.                                                                 ->scalarNode('name')->isRequired()->end()
  1934.                                                                 ->enumNode('fieldType')
  1935.                                                                     ->isRequired()
  1936.                                                                     ->values(['input''textarea''select''datetime''date''user''checkbox'])
  1937.                                                                 ->end()
  1938.                                                                 ->scalarNode('title')->end()
  1939.                                                                 ->booleanNode('required')->defaultFalse()->end()
  1940.                                                                 ->scalarNode('setterFn')->end()
  1941.                                                                 ->arrayNode('fieldTypeSettings')
  1942.                                                                      ->prototype('variable')->end()
  1943.                                                                 ->end()
  1944.                                                             ->end()
  1945.                                                         ->end()
  1946.                                                     ->end()
  1947.                                                     ->arrayNode('customHtml')
  1948.                                                         ->children()
  1949.                                                             ->enumNode('position')
  1950.                                                                 ->values(['top''center''bottom'])
  1951.                                                                 ->defaultValue('top')
  1952.                                                                 ->info('Set position of custom HTML inside modal (top, center, bottom).')
  1953.                                                             ->end()
  1954.                                                             ->scalarNode('service')
  1955.                                                                 ->cannotBeEmpty()
  1956.                                                                 ->info('Define a custom service for rendering custom HTML within the note modal.')
  1957.                                                             ->end()
  1958.                                                         ->end()
  1959.                                                     ->end()
  1960.                                                 ->end()
  1961.                                                 ->info('See notes section of transitions. It works exactly the same way.')
  1962.                                             ->end()
  1963.                                         ->end()
  1964.                                     ->end()
  1965.                                     ->info('Actions which will be added to actions button independently of the current workflow place.')
  1966.                                 ->end()
  1967.                             ->end()
  1968.                             ->validate()
  1969.                                 ->ifTrue(function ($v) {
  1970.                                     return $v['supports'] && isset($v['support_strategy']);
  1971.                                 })
  1972.                                 ->thenInvalid('"supports" and "support_strategy" cannot be used together.')
  1973.                             ->end()
  1974.                             ->validate()
  1975.                                 ->ifTrue(function ($v) {
  1976.                                     return !$v['supports'] && !isset($v['support_strategy']);
  1977.                                 })
  1978.                                 ->thenInvalid('"supports" or "support_strategy" should be configured.')
  1979.                             ->end()
  1980.                             ->validate()
  1981.                                 ->ifTrue(function ($v) {
  1982.                                     if (($v['type'] ?? 'workflow') === 'state_machine') {
  1983.                                         foreach ($v['transitions'] ?? [] as $transition) {
  1984.                                             if (count($transition['to']) > 1) {
  1985.                                                 return true;
  1986.                                             }
  1987.                                         }
  1988.                                         foreach ($v['globalActions'] ?? [] as $transition) {
  1989.                                             if (count($transition['to']) > 1) {
  1990.                                                 return true;
  1991.                                             }
  1992.                                         }
  1993.                                     }
  1994.                                     return false;
  1995.                                 })
  1996.                                 ->thenInvalid('Type `state_machine` does not support multiple `to` definitions for transitions and global actions. Change definition or type to `workflow`.')
  1997.                             ->end()
  1998.                         ->end()
  1999.                     ->end()
  2000.                 ->end()
  2001.                 ->addDefaultsIfNotSet()
  2002.             ->end();
  2003.     }
  2004.     /**
  2005.      * Add predefined properties specific extension config
  2006.      *
  2007.      * @param ArrayNodeDefinition $rootNode
  2008.      */
  2009.     private function addPredefinedPropertiesNode(ArrayNodeDefinition $rootNode)
  2010.     {
  2011.         $predefinedPropertiesNode $rootNode
  2012.             ->children()
  2013.             ->arrayNode('properties')
  2014.             ->ignoreExtraKeys()
  2015.             ->addDefaultsIfNotSet();
  2016.         $predefinedPropertiesNode
  2017.         ->children()
  2018.             ->arrayNode('predefined')
  2019.                 ->addDefaultsIfNotSet()
  2020.                 ->children()
  2021.                     ->arrayNode('definitions')
  2022.                     ->normalizeKeys(false)
  2023.                         ->prototype('array')
  2024.                             ->children()
  2025.                                 ->scalarNode('name')->end()
  2026.                                 ->scalarNode('description')->end()
  2027.                                 ->scalarNode('key')->end()
  2028.                                 ->scalarNode('type')->end()
  2029.                                 ->scalarNode('data')->end()
  2030.                                 ->scalarNode('config')->end()
  2031.                                 ->scalarNode('ctype')->end()
  2032.                                 ->booleanNode('inheritable')
  2033.                                     ->beforeNormalization()
  2034.                                         ->ifString()
  2035.                                         ->then(function ($v) {
  2036.                                             return (bool)$v;
  2037.                                         })
  2038.                                         ->end()
  2039.                                 ->end()
  2040.                                 ->integerNode('creationDate')->end()
  2041.                                 ->integerNode('modificationDate')->end()
  2042.                             ->end()
  2043.                         ->end()
  2044.                     ->end()
  2045.                 ->end()
  2046.             ->end()
  2047.         ->end();
  2048.     }
  2049.     /**
  2050.      * Add static routes specific extension config
  2051.      *
  2052.      * @param ArrayNodeDefinition $rootNode
  2053.      */
  2054.     private function addStaticroutesNode(ArrayNodeDefinition $rootNode)
  2055.     {
  2056.         $rootNode
  2057.         ->children()
  2058.             ->arrayNode('staticroutes')
  2059.                 ->ignoreExtraKeys()
  2060.                 ->addDefaultsIfNotSet()
  2061.                 ->children()
  2062.                     ->arrayNode('definitions')
  2063.                     ->normalizeKeys(false)
  2064.                         ->prototype('array')
  2065.                             ->children()
  2066.                                 ->scalarNode('name')->end()
  2067.                                 ->scalarNode('pattern')->end()
  2068.                                 ->scalarNode('reverse')->end()
  2069.                                 ->scalarNode('controller')->end()
  2070.                                 ->scalarNode('variables')->end()
  2071.                                 ->scalarNode('defaults')->end()
  2072.                                 ->arrayNode('siteId')
  2073.                                     ->integerPrototype()->end()
  2074.                                 ->end()
  2075.                                 ->arrayNode('methods')
  2076.                                     ->scalarPrototype()->end()
  2077.                                 ->end()
  2078.                                 ->integerNode('priority')->end()
  2079.                                 ->integerNode('creationDate')->end()
  2080.                                 ->integerNode('modificationDate')->end()
  2081.                             ->end()
  2082.                         ->end()
  2083.                     ->end()
  2084.                 ->end()
  2085.             ->end()
  2086.         ->end();
  2087.     }
  2088.     /**
  2089.      * Add perspectives specific extension config
  2090.      *
  2091.      * @param ArrayNodeDefinition $rootNode
  2092.      */
  2093.     private function addPerspectivesNode(ArrayNodeDefinition $rootNode)
  2094.     {
  2095.         $rootNode
  2096.             ->children()
  2097.                 ->arrayNode('perspectives')
  2098.                     ->ignoreExtraKeys()
  2099.                     ->addDefaultsIfNotSet()
  2100.                     ->children()
  2101.                         ->arrayNode('definitions')
  2102.                         ->normalizeKeys(false)
  2103.                             ->prototype('array')
  2104.                                 ->children()
  2105.                                     ->scalarNode('iconCls')->end()
  2106.                                     ->scalarNode('icon')->end()
  2107.                                     ->variableNode('toolbar')->end()
  2108.                                     ->arrayNode('dashboards')
  2109.                                         ->children()
  2110.                                             ->variableNode('disabledPortlets')->end()
  2111.                                         ->end()
  2112.                                         ->children()
  2113.                                             ->variableNode('predefined')->end()
  2114.                                         ->end()
  2115.                                     ->end()
  2116.                                     ->arrayNode('elementTree')
  2117.                                         ->prototype('array')
  2118.                                             ->children()
  2119.                                                 ->scalarNode('type')->end()
  2120.                                                 ->scalarNode('position')->end()
  2121.                                                 ->scalarNode('name')->end()
  2122.                                                 ->booleanNode('expanded')->end()
  2123.                                                 ->scalarNode('hidden')->end()
  2124.                                                 ->integerNode('sort')->end()
  2125.                                                 ->scalarNode('id')->end()
  2126.                                                 ->variableNode('treeContextMenu')->end()
  2127.                                             ->end()
  2128.                                         ->end()
  2129.                                     ->end()
  2130.                                 ->end()
  2131.                             ->end()
  2132.                         ->end()
  2133.                     ->end()
  2134.                 ->end()
  2135.             ->end()
  2136.         ->end();
  2137.     }
  2138.     /**
  2139.      * Add custom views specific extension config
  2140.      *
  2141.      * @param ArrayNodeDefinition $rootNode
  2142.      */
  2143.     private function addCustomViewsNode(ArrayNodeDefinition $rootNode)
  2144.     {
  2145.         $rootNode
  2146.             ->children()
  2147.                 ->arrayNode('custom_views')
  2148.                     ->ignoreExtraKeys()
  2149.                     ->addDefaultsIfNotSet()
  2150.                     ->children()
  2151.                         ->arrayNode('definitions')
  2152.                         ->normalizeKeys(false)
  2153.                             ->prototype('array')
  2154.                             ->children()
  2155.                                 ->scalarNode('id')->end()
  2156.                                 ->scalarNode('treetype')->end()
  2157.                                 ->scalarNode('name')->end()
  2158.                                 ->scalarNode('condition')->end()
  2159.                                 ->scalarNode('icon')->end()
  2160.                                 ->scalarNode('rootfolder')->end()
  2161.                                 ->scalarNode('showroot')->end()
  2162.                                 ->variableNode('classes')->end()
  2163.                                 ->scalarNode('position')->end()
  2164.                                 ->scalarNode('sort')->end()
  2165.                                 ->booleanNode('expanded')->end()
  2166.                                 ->scalarNode('having')->end()
  2167.                                 ->scalarNode('where')->end()
  2168.                                 ->variableNode('treeContextMenu')->end()
  2169.                                 ->arrayNode('joins')
  2170.                                     ->protoType('array')
  2171.                                         ->children()
  2172.                                             ->scalarNode('type')->end()
  2173.                                             ->scalarNode('condition')->end()
  2174.                                             ->variableNode('name')->end()
  2175.                                             ->variableNode('columns')->end()
  2176.                                         ->end()
  2177.                                     ->end()
  2178.                                 ->end()
  2179.                             ->end()
  2180.                         ->end()
  2181.                     ->end()
  2182.                 ->end()
  2183.             ->end();
  2184.     }
  2185. }