Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
131 / 131 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
1 / 1 |
| Configuration | |
100.00% |
131 / 131 |
|
100.00% |
2 / 2 |
9 | |
100.00% |
1 / 1 |
| addCmsOptions | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
| addApiOptions | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
| getConfigTreeBuilder | |
100.00% |
125 / 125 |
|
100.00% |
1 / 1 |
6 | |||
| getDefaultLanguageTypehint | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
| 1 | <?php |
| 2 | namespace Apie\Common\Config; |
| 3 | |
| 4 | use Apie\Common\ValueObjects\EntityNamespace; |
| 5 | use Apie\DoctrineEntityDatalayer\IndexStrategy\DirectIndexStrategy; |
| 6 | use Apie\IanaValueObjects\LanguageAndRegion; |
| 7 | use PrinsFrank\Standards\Language\LanguageAlpha2; |
| 8 | use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
| 9 | use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
| 10 | use Symfony\Component\Config\Definition\ConfigurationInterface; |
| 11 | |
| 12 | /** |
| 13 | * Configuration |
| 14 | */ |
| 15 | abstract class Configuration implements ConfigurationInterface |
| 16 | { |
| 17 | private const ENABLE_CONFIGS = [ |
| 18 | 'enable_basic_auth' => 'Apie\Common\BasicAuth\AddBasicAuthContextBuilder', |
| 19 | 'enable_ai_instructor' => 'Apie\AiInstructor\AiInstructor', |
| 20 | 'enable_common_plugin' => 'Apie\ApieCommonPlugin\ApieCommonPlugin', |
| 21 | 'enable_cms' => 'Apie\Cms\RouteDefinitions\CmsRouteDefinitionProvider', |
| 22 | 'enable_cms_dropdown' => 'Apie\CmsApiDropdownOption\RouteDefinitions\DropdownOptionsForExistingObjectRouteDefinition', |
| 23 | 'enable_doctrine_entity_converter' => 'Apie\DoctrineEntityConverter\OrmBuilder', |
| 24 | 'enable_doctrine_entity_datalayer' => 'Apie\DoctrineEntityDatalayer\DoctrineEntityDatalayer', |
| 25 | 'enable_export' => 'Apie\Export\EntityExport', |
| 26 | 'enable_faker' => 'Apie\Faker\ApieObjectFaker', |
| 27 | 'enable_ftp' => 'Apie\FtpServer\FtpServerCommand', |
| 28 | 'enable_exchangerate' => 'Apie\ExchangeRate\ExchangeRateService', |
| 29 | 'enable_graphql' => 'Apie\Graphql\Factories\GraphqlSchemaFactory', |
| 30 | 'enable_maker' => 'Apie\Maker\Utils', |
| 31 | 'enable_mcp_server' => 'Apie\McpServer\RunMcpServerCommand', |
| 32 | 'enable_rest_api' => 'Apie\RestApi\OpenApi\OpenApiGenerator', |
| 33 | 'enable_console' => 'Apie\Console\ConsoleCommandFactory', |
| 34 | 'enable_twig_template_layout_renderer' => 'Apie\TwigTemplateLayoutRenderer\TwigRenderer', |
| 35 | 'enable_typescript_client_builder' => 'Apie\TypescriptClientBuilder\RouteDefinitions\CodeRouteDefinitionProvider', |
| 36 | 'enable_webdav' => 'Apie\Webdav\Controller\WebdavController', |
| 37 | ]; |
| 38 | |
| 39 | abstract protected function addCmsOptions(ArrayNodeDefinition $arrayNode): void; |
| 40 | |
| 41 | abstract protected function addApiOptions(ArrayNodeDefinition $arrayNode): void; |
| 42 | |
| 43 | public function getConfigTreeBuilder(): TreeBuilder |
| 44 | { |
| 45 | $treeBuilder = new TreeBuilder('apie'); |
| 46 | |
| 47 | $children = $treeBuilder->getRootNode()->children(); |
| 48 | $children->booleanNode('enable_core')->defaultValue(true)->end(); |
| 49 | $children->scalarNode('encryption_key')->end(); |
| 50 | $cmsConfig = $children->arrayNode('cms'); |
| 51 | $cmsConfig->children() |
| 52 | ->scalarNode('base_url')->defaultValue('/cms')->end() |
| 53 | ->arrayNode('asset_folders')->scalarPrototype()->end() |
| 54 | ->end(); |
| 55 | $this->addCmsOptions($cmsConfig); |
| 56 | $apiConfig = $children->arrayNode('rest_api'); |
| 57 | $apiConfig->children() |
| 58 | ->scalarNode('base_url')->defaultValue('/api')->end() |
| 59 | ->end(); |
| 60 | $this->addApiOptions($apiConfig); |
| 61 | |
| 62 | $openApiConfig = $children->arrayNode('open_api'); |
| 63 | $openApiConfig->children() |
| 64 | ->integerNode('max_enum_size')->defaultValue(100)->end() |
| 65 | ->end(); |
| 66 | |
| 67 | $ftpConfig = $children->arrayNode('ftp_server'); |
| 68 | $ftpConfig->children() |
| 69 | ->scalarNode('public_ip')->defaultValue('127.0.0.1')->end() |
| 70 | ->scalarNode('passive_min_port')->defaultValue('49152')->end() |
| 71 | ->scalarNode('passive_max_port')->defaultValue('65534')->end() |
| 72 | ->end(); |
| 73 | |
| 74 | $ftpConfig = $children->arrayNode('graphql'); |
| 75 | $ftpConfig->children() |
| 76 | ->scalarNode('base_url')->defaultValue('graphql')->end() |
| 77 | ->end(); |
| 78 | |
| 79 | $aiConfig = $children->arrayNode('ai') |
| 80 | ->addDefaultsIfNotSet(); |
| 81 | $aiConfig->children() |
| 82 | ->scalarNode('base_url')->defaultValue('https://api.openai.com/v1')->end() |
| 83 | ->scalarNode('api_key')->defaultValue('no-value')->end() |
| 84 | ->end(); |
| 85 | |
| 86 | $children->arrayNode('datalayers') |
| 87 | ->children() |
| 88 | ->scalarNode('default_datalayer')->isRequired()->end() |
| 89 | ->arrayNode('context_mapping') |
| 90 | ->useAttributeAsKey('name') |
| 91 | ->arrayPrototype() |
| 92 | ->isRequired() |
| 93 | ->children() |
| 94 | ->scalarNode('default_datalayer')->isRequired()->end() |
| 95 | ->arrayNode('entity_mapping') |
| 96 | ->useAttributeAsKey('class') |
| 97 | ->scalarPrototype() |
| 98 | ->end() |
| 99 | ->end() |
| 100 | ->end() |
| 101 | ->end() |
| 102 | ->end() |
| 103 | ->end() |
| 104 | ->end() |
| 105 | ->arrayNode('doctrine') |
| 106 | ->children() |
| 107 | ->arrayNode('indexing') |
| 108 | ->children() |
| 109 | ->enumNode('type')->values(['direct', 'late', 'background', 'custom'])->defaultValue('direct')->end() |
| 110 | ->scalarNode('service')->defaultValue(DirectIndexStrategy::class)->end() |
| 111 | ->end() |
| 112 | ->end() |
| 113 | ->scalarNode('build_once')->defaultValue(false)->end() |
| 114 | ->scalarNode('run_migrations')->defaultValue(true)->end() |
| 115 | ->arrayNode('connection_params') |
| 116 | ->defaultValue(['driver' => 'pdo_sqlite']) |
| 117 | ->useAttributeAsKey('class') |
| 118 | ->scalarPrototype() |
| 119 | ->end() |
| 120 | ->end() |
| 121 | ->end() |
| 122 | ->end() |
| 123 | ->arrayNode('storage') |
| 124 | ->arrayPrototype() |
| 125 | ->children() |
| 126 | ->scalarNode('class')->isRequired()->end() |
| 127 | ->arrayNode('options')->defaultValue([]) |
| 128 | ->scalarPrototype() |
| 129 | ->end() |
| 130 | ->end() |
| 131 | ->end() |
| 132 | ->end() |
| 133 | ->end() |
| 134 | ->arrayNode('maker') |
| 135 | ->children() |
| 136 | ->scalarNode('target_path')->defaultValue(false)->end() |
| 137 | ->scalarNode('target_namespace')->defaultValue('App\Apie')->end() |
| 138 | ->end() |
| 139 | ->end() |
| 140 | ->scalarNode('language_typehint')->defaultValue(self::getDefaultLanguageTypehint())->end() |
| 141 | ->arrayNode('bounded_contexts') |
| 142 | ->useAttributeAsKey('name') |
| 143 | ->arrayPrototype() |
| 144 | ->beforeNormalization() |
| 145 | ->always( |
| 146 | function (array $v) { |
| 147 | if (empty($v['policies_folder']) && !empty($v['entities_folder'])) { |
| 148 | $v['policies_folder'] = rtrim($v['entities_folder'], '/\\') . '/../Policies'; |
| 149 | } |
| 150 | |
| 151 | if (empty($v['policies_namespace']) && !empty($v['entities_namespace'])) { |
| 152 | $entityNamespace = EntityNamespace::fromNative($v['entities_namespace']); |
| 153 | $v['policies_namespace'] = $entityNamespace->getParentNamespace()->getChildNamespace('Policies')->toNative(); |
| 154 | } |
| 155 | |
| 156 | return $v; |
| 157 | } |
| 158 | )->end() |
| 159 | ->children() |
| 160 | ->scalarNode('entities_folder')->isRequired()->end() |
| 161 | ->scalarNode('entities_namespace')->isRequired()->end() |
| 162 | ->scalarNode('actions_folder')->isRequired()->end() |
| 163 | ->scalarNode('actions_namespace')->isRequired()->end() |
| 164 | ->scalarNode('policies_folder')->defaultNull()->end() |
| 165 | ->scalarNode('policies_namespace')->defaultNull()->end() |
| 166 | ->end() |
| 167 | ->end() |
| 168 | ->end() |
| 169 | ->arrayNode('scan_bounded_contexts') |
| 170 | ->children() |
| 171 | ->scalarNode('search_path')->end() |
| 172 | ->scalarNode('search_namespace')->end() |
| 173 | ->end() |
| 174 | ->end(); |
| 175 | $childNode = $treeBuilder->getRootNode()->children(); |
| 176 | foreach (self::ENABLE_CONFIGS as $configKey => $classNameToExist) { |
| 177 | $childNode->booleanNode($configKey)->defaultValue(class_exists($classNameToExist)); |
| 178 | } |
| 179 | $childNode->scalarNode('remote_mcp_path')->defaultValue(null)->end(); |
| 180 | return $treeBuilder; |
| 181 | } |
| 182 | |
| 183 | public static function getDefaultLanguageTypehint(): ?string |
| 184 | { |
| 185 | $languageTypehint = null; |
| 186 | if (class_exists(LanguageAlpha2::class)) { |
| 187 | $languageTypehint = LanguageAlpha2::class; |
| 188 | } |
| 189 | if (class_exists(LanguageAndRegion::class)) { |
| 190 | $languageTypehint = LanguageAndRegion::class; |
| 191 | } |
| 192 | return $languageTypehint; |
| 193 | } |
| 194 | } |