Module.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Service\Security;
  4. use App\Entity\Organization\Organization;
  5. use App\Enum\Organization\SettingsProductEnum;
  6. use App\Service\Utils\Reflection;
  7. use Doctrine\Common\Cache\ApcuCache;
  8. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  9. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  10. /**
  11. * Class Module : classe gérant la récupération de l'ensemble des modules possédées par une organisation.
  12. */
  13. class Module
  14. {
  15. public function __construct(
  16. readonly private Reflection $reflection,
  17. readonly private ParameterBagInterface $parameterBag
  18. ) {
  19. }
  20. /**
  21. * @todo activer le cache après que la fin de la migration.
  22. * Récupère tous les modules de l'organisation
  23. *
  24. * @return list<string>
  25. */
  26. public function getOrganizationModules(Organization $organization): array
  27. {
  28. // $cacheDriver = new ApcuCache();
  29. // //If the modules are all ready available inside the APCu cache
  30. // if($cacheDriver->contains('organization_modules_' . $organization->getId())){
  31. // return $cacheDriver->fetch('organization_modules_' . $organization->getId());
  32. // }
  33. // Get modules from the organization settings
  34. $modulesBySettings = $this->getModuleBySettings($organization);
  35. // Get modules according to the conditions defined in the config
  36. $modulesByConditions = $this->getModulesByConditions($organization);
  37. // Get the modules from the owned product
  38. $product = $organization->getSettings()->getProduct();
  39. $modulesForProduct = $this->getModulesByProductConfiguration($product);
  40. // Controls that no modules where setup in different locations (this should not happen, and can lead to unexpected
  41. // behaviors whend serializing the OrganizationProfile)
  42. $intersection = array_merge(
  43. array_intersect($modulesBySettings, $modulesByConditions),
  44. array_intersect($modulesByConditions, $modulesForProduct),
  45. array_intersect($modulesBySettings, $modulesForProduct)
  46. );
  47. if (!empty($intersection)) {
  48. throw new \RuntimeException('Those modules are defined more than once : '.implode(', ', $intersection));
  49. }
  50. $organizationModules = array_merge_recursive($modulesForProduct, $modulesBySettings, $modulesByConditions);
  51. // //Keep the modules inside the APCu cache
  52. // $cacheDriver->save('organization_modules_' . $organization->getId(), $organizationModules, '86400');
  53. return $organizationModules;
  54. }
  55. /**
  56. * Récupère les modules disponibles dans les settings de l'organisation (Sms, Pes, etc).
  57. *
  58. * @return list<string>
  59. *
  60. * @see ModuleTest::testGetModuleBySettings()
  61. */
  62. public function getModuleBySettings(Organization $organization): array
  63. {
  64. $moduleByOptions = [];
  65. $modulesOptions = $organization->getSettings()->getModules();
  66. if (!empty($modulesOptions)) {
  67. foreach ($modulesOptions as $moduleOptionName => $moduleOptionValue) {
  68. if ($moduleOptionValue) {
  69. $moduleByOptions[] = $moduleOptionName;
  70. }
  71. }
  72. }
  73. return $moduleByOptions;
  74. }
  75. /**
  76. * Récupère les modules par conditions, grace au fichier modulebyconditions.yaml.
  77. *
  78. * @return list<string>
  79. *
  80. * @see ModuleTest::testGetModulesByConditions()
  81. */
  82. public function getModulesByConditions(Organization $organization): array
  83. {
  84. $modulesByConditions = [];
  85. $modules = $this->parameterBag->get('opentalent.modulesbyconditions');
  86. foreach ($modules as $moduleName => $module) {
  87. try {
  88. $service = $module['conditions']['service'];
  89. $args = $service['args'] ?? [];
  90. $response = $this->reflection->dynamicInvokeServiceWithArgsAndMethod(
  91. $service['name'],
  92. $service['function'],
  93. array_merge([$organization], $args)
  94. );
  95. if ($response) {
  96. $modulesByConditions[] = $moduleName;
  97. }
  98. } catch (\Exception $exception) {
  99. throw new \LogicException($exception->getMessage(), 400, $exception);
  100. }
  101. }
  102. return $modulesByConditions;
  103. }
  104. /**
  105. * Récupère les modules disponibles par produit grace au fichier products.yaml.
  106. *
  107. * @return list<string>|null
  108. *
  109. * @see ModuleTest::testGetModulesByProductConfiguration()
  110. */
  111. public function getModulesByProductConfiguration(SettingsProductEnum $product): ?array
  112. {
  113. $opentalentProducts = $this->parameterBag->get('opentalent.products');
  114. if (!array_key_exists($product->value, $opentalentProducts)) {
  115. throw new AccessDeniedHttpException(sprintf('The product %s does not exist !', $product->value));
  116. }
  117. $productConfig = $opentalentProducts[$product->value];
  118. $modules = $productConfig['modules'] ?? [];
  119. if (array_key_exists('extend', $productConfig)) {
  120. $modules = array_merge(
  121. $modules,
  122. $this->getModulesByProductConfiguration(SettingsProductEnum::from($productConfig['extend']))
  123. );
  124. unset($productConfig['extend']);
  125. }
  126. return $modules;
  127. }
  128. /**
  129. * Retourne le module possédant la resource passée en paramètre.
  130. */
  131. public function getModuleByResourceName(string $resource): int|string|null
  132. {
  133. $modules = $this->parameterBag->get('opentalent.modules');
  134. foreach ($modules as $module => $data) {
  135. if ($data['entities'] && in_array($resource, $data['entities'], true)) {
  136. return $module;
  137. }
  138. }
  139. return null;
  140. }
  141. }