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