vendor/se7enxweb/legacy-bridge/bundle/LegacyMapper/Configuration.php line 113

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. namespace eZ\Bundle\EzPublishLegacyBundle\LegacyMapper;
  7. use eZ\Publish\Core\FieldType\Image\AliasCleanerInterface;
  8. use eZ\Publish\Core\MVC\Legacy\LegacyEvents;
  9. use eZ\Publish\Core\MVC\Legacy\Event\PreBuildKernelEvent;
  10. use eZ\Publish\Core\MVC\ConfigResolverInterface;
  11. use EzSystems\PlatformHttpCacheBundle\PurgeClient\PurgeClientInterface;
  12. use eZ\Bundle\EzPublishLegacyBundle\Cache\PersistenceCachePurger;
  13. use eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator;
  14. use Doctrine\DBAL\Connection;
  15. use ezpEvent;
  16. use ezxFormToken;
  17. use Symfony\Component\DependencyInjection\ContainerAwareTrait;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use RuntimeException;
  20. use Exception;
  21. /**
  22. * Maps configuration parameters to the legacy parameters.
  23. */
  24. class Configuration implements EventSubscriberInterface
  25. {
  26. use ContainerAwareTrait;
  27. /**
  28. * @var \eZ\Publish\Core\MVC\ConfigResolverInterface
  29. */
  30. private $configResolver;
  31. /**
  32. * @var \EzSystems\PlatformHttpCacheBundle\PurgeClient\PurgeClientInterface
  33. */
  34. private $purgeClient;
  35. /**
  36. * @var \eZ\Bundle\EzPublishLegacyBundle\Cache\PersistenceCachePurger
  37. */
  38. private $persistenceCachePurger;
  39. /**
  40. * @var \eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator
  41. */
  42. private $urlAliasGenerator;
  43. /**
  44. * @var \Doctrine\DBAL\Connection
  45. */
  46. private $legacyDbHandler;
  47. /**
  48. * @var array
  49. */
  50. private $options;
  51. /**
  52. * Disables the feature when set using setEnabled().
  53. *
  54. * @var bool
  55. */
  56. private $enabled = true;
  57. /**
  58. * @var AliasCleanerInterface
  59. */
  60. private $aliasCleaner;
  61. public function __construct(
  62. ConfigResolverInterface $configResolver,
  63. PurgeClientInterface $purgeClient,
  64. PersistenceCachePurger $persistenceCachePurger,
  65. UrlAliasGenerator $urlAliasGenerator,
  66. Connection $legacyDbHandler,
  67. AliasCleanerInterface $aliasCleaner,
  68. array $options = []
  69. ) {
  70. $this->configResolver = $configResolver;
  71. $this->purgeClient = $purgeClient;
  72. $this->persistenceCachePurger = $persistenceCachePurger;
  73. $this->urlAliasGenerator = $urlAliasGenerator;
  74. $this->legacyDbHandler = $legacyDbHandler;
  75. $this->aliasCleaner = $aliasCleaner;
  76. $this->options = $options;
  77. }
  78. /**
  79. * Toggles the feature.
  80. *
  81. * @param bool $isEnabled
  82. */
  83. public function setEnabled($isEnabled)
  84. {
  85. $this->enabled = (bool)$isEnabled;
  86. }
  87. public static function getSubscribedEvents()
  88. {
  89. return [
  90. LegacyEvents::PRE_BUILD_LEGACY_KERNEL => ['onBuildKernel', 128],
  91. ];
  92. }
  93. /**
  94. * Adds settings to the parameters that will be injected into the legacy kernel.
  95. *
  96. * @param \eZ\Publish\Core\MVC\Legacy\Event\PreBuildKernelEvent $event
  97. */
  98. public function onBuildKernel(PreBuildKernelEvent $event)
  99. {
  100. if (!$this->enabled) {
  101. return;
  102. }
  103. $databaseSettings = $this->legacyDbHandler->getParams();
  104. $settings = [];
  105. foreach (
  106. [
  107. 'host' => 'Server',
  108. 'port' => 'Port',
  109. 'user' => 'User',
  110. 'password' => 'Password',
  111. 'dbname' => 'Database',
  112. 'unix_socket' => 'Socket',
  113. 'driver' => 'DatabaseImplementation',
  114. ] as $key => $iniKey
  115. ) {
  116. if (isset($databaseSettings[$key])) {
  117. $iniValue = $databaseSettings[$key];
  118. switch ($key) {
  119. case 'driver':
  120. $driverMap = [
  121. 'pdo_mysql' => 'ezmysqli',
  122. 'pdo_pgsql' => 'ezpostgresql',
  123. 'oci8' => 'ezoracle',
  124. 'pdo_sqlite' => 'sqlite3',
  125. ];
  126. if (!isset($driverMap[$iniValue])) {
  127. throw new RuntimeException(
  128. "Could not map database driver to Legacy Stack database implementation.\n" .
  129. "Expected one of '" . implode("', '", array_keys($driverMap)) . "', got '" .
  130. $iniValue . "'."
  131. );
  132. }
  133. $iniValue = $driverMap[$iniValue];
  134. break;
  135. }
  136. $settings["site.ini/DatabaseSettings/$iniKey"] = $iniValue;
  137. }
  138. // Some settings need specific values when not present.
  139. else {
  140. switch ($key) {
  141. case 'unix_socket':
  142. $settings["site.ini/DatabaseSettings/$iniKey"] = 'disabled';
  143. break;
  144. }
  145. }
  146. }
  147. // For SQLite, DBAL uses 'path' instead of 'dbname'; inject it as Database so the legacy
  148. // SQLite3 handler receives the full absolute path to the shared database file.
  149. if (isset($databaseSettings['path'], $databaseSettings['driver']) && $databaseSettings['driver'] === 'pdo_sqlite') {
  150. $settings['site.ini/DatabaseSettings/Database'] = $databaseSettings['path'];
  151. }
  152. // Image settings
  153. $settings += $this->getImageSettings();
  154. // File settings
  155. $settings += [
  156. 'site.ini/FileSettings/VarDir' => $this->configResolver->getParameter('var_dir'),
  157. 'site.ini/FileSettings/StorageDir' => $this->configResolver->getParameter('storage_dir'),
  158. ];
  159. // Multisite settings (PathPrefix and co)
  160. $settings += $this->getMultiSiteSettings();
  161. // User settings
  162. $settings['site.ini/UserSettings/AnonymousUserID'] = $this->configResolver->getParameter('anonymous_user_id');
  163. // Cache settings
  164. // Enforce ViewCaching to be enabled in order to persistence/http cache to be purged correctly.
  165. $settings['site.ini/ContentSettings/ViewCaching'] = 'enabled';
  166. // Cluster Settings
  167. $settings += $this->getClusterSettings();
  168. $event->getParameters()->set(
  169. 'injected-settings',
  170. $settings + (array)$event->getParameters()->get('injected-settings')
  171. );
  172. if (class_exists('ezxFormToken')) {
  173. // Inject csrf protection settings to make sure legacy & symfony stack work together
  174. if (
  175. $this->container->hasParameter('form.type_extension.csrf.enabled') &&
  176. $this->container->getParameter('form.type_extension.csrf.enabled')
  177. ) {
  178. ezxFormToken::setSecret($this->container->getParameter('kernel.secret'));
  179. ezxFormToken::setFormField($this->container->getParameter('form.type_extension.csrf.field_name'));
  180. }
  181. // csrf protection is disabled, disable it in legacy extension as well.
  182. else {
  183. ezxFormToken::setIsEnabled(false);
  184. }
  185. }
  186. // Register http cache content/cache event listener
  187. $ezpEvent = ezpEvent::getInstance();
  188. $ezpEvent->attach('content/cache', [$this->purgeClient, 'purge']);
  189. $ezpEvent->attach('content/cache/all', [$this->purgeClient, 'purgeAll']);
  190. // Register persistence cache event listeners
  191. $ezpEvent->attach('content/cache', [$this->persistenceCachePurger, 'content']);
  192. $ezpEvent->attach('content/cache/all', [$this->persistenceCachePurger, 'all']);
  193. $ezpEvent->attach('content/cache/version', [$this->persistenceCachePurger, 'contentVersion']);
  194. $ezpEvent->attach('content/class/cache/all', [$this->persistenceCachePurger, 'contentType']);
  195. $ezpEvent->attach('content/class/cache', [$this->persistenceCachePurger, 'contentType']);
  196. $ezpEvent->attach('content/class/group/cache', [$this->persistenceCachePurger, 'contentTypeGroup']);
  197. $ezpEvent->attach('content/section/cache', [$this->persistenceCachePurger, 'section']);
  198. $ezpEvent->attach('user/cache/all', [$this->persistenceCachePurger, 'user']);
  199. $ezpEvent->attach('content/translations/cache', [$this->persistenceCachePurger, 'languages']);
  200. $ezpEvent->attach('content/state/assign', [$this->persistenceCachePurger, 'stateAssign']);
  201. // Register image alias removal listeners
  202. $ezpEvent->attach('image/removeAliases', [$this->aliasCleaner, 'removeAliases']);
  203. $ezpEvent->attach('image/trashAliases', [$this->aliasCleaner, 'removeAliases']);
  204. $ezpEvent->attach('image/purgeAliases', [$this->aliasCleaner, 'removeAliases']);
  205. }
  206. private function getImageSettings()
  207. {
  208. $imageSettings = [
  209. // Basic settings
  210. 'image.ini/FileSettings/TemporaryDir' => $this->configResolver->getParameter('image.temporary_dir'),
  211. 'image.ini/FileSettings/PublishedImages' => $this->configResolver->getParameter('image.published_images_dir'),
  212. 'image.ini/FileSettings/VersionedImages' => $this->configResolver->getParameter('image.versioned_images_dir'),
  213. 'image.ini/AliasSettings/AliasList' => [],
  214. // ImageMagick configuration
  215. 'image.ini/ImageMagick/IsEnabled' => $this->options['imagemagick_enabled'] ? 'true' : 'false',
  216. 'image.ini/ImageMagick/ExecutablePath' => $this->options['imagemagick_executable_path'],
  217. 'image.ini/ImageMagick/Executable' => $this->options['imagemagick_executable'],
  218. 'image.ini/ImageMagick/PreParameters' => $this->configResolver->getParameter('imagemagick.pre_parameters'),
  219. 'image.ini/ImageMagick/PostParameters' => $this->configResolver->getParameter('imagemagick.post_parameters'),
  220. 'image.ini/ImageMagick/Filters' => [],
  221. ];
  222. // Aliases configuration
  223. $imageVariations = $this->configResolver->getParameter('image_variations');
  224. foreach ($imageVariations as $aliasName => $aliasSettings) {
  225. $imageSettings['image.ini/AliasSettings/AliasList'][] = $aliasName;
  226. if (isset($aliasSettings['reference'])) {
  227. $imageSettings["image.ini/$aliasName/Reference"] = $aliasSettings['reference'];
  228. }
  229. foreach ($aliasSettings['filters'] as $filterName => $filter) {
  230. if (!isset($this->options['imagemagick_filters'][$filterName])) {
  231. continue;
  232. }
  233. $imageSettings["image.ini/$aliasName/Filters"][] = $filterName . '=' . implode(';', $filter);
  234. }
  235. }
  236. foreach ($this->options['imagemagick_filters'] as $filterName => $filter) {
  237. $imageSettings['image.ini/ImageMagick/Filters'][] = "$filterName=" . strtr($filter, ['{' => '%', '}' => '']);
  238. }
  239. return $imageSettings;
  240. }
  241. private function getMultiSiteSettings()
  242. {
  243. $rootLocationId = $this->configResolver->getParameter('content.tree_root.location_id');
  244. $indexPage = $this->configResolver->getParameter('index_page');
  245. $defaultPage = $this->configResolver->getParameter('default_page');
  246. if ($rootLocationId === null) {
  247. // return SiteSettings if there is no MultiSite (rootLocation is not defined)
  248. $result = [];
  249. if ($indexPage !== null) {
  250. $result['site.ini/SiteSettings/IndexPage'] = $indexPage;
  251. }
  252. if ($defaultPage !== null) {
  253. $result['site.ini/SiteSettings/DefaultPage'] = $defaultPage;
  254. }
  255. return $result;
  256. }
  257. $pathPrefix = $this->loadPathPrefix($rootLocationId);
  258. $pathPrefixExcludeItems = array_map(
  259. static function ($value) {
  260. return trim($value, '/');
  261. },
  262. $this->configResolver->getParameter('content.tree_root.excluded_uri_prefixes')
  263. );
  264. return [
  265. 'site.ini/SiteAccessSettings/PathPrefix' => $pathPrefix,
  266. 'site.ini/SiteAccessSettings/PathPrefixExclude' => $pathPrefixExcludeItems,
  267. 'logfile.ini/AccessLogFileSettings/PathPrefix' => $pathPrefix,
  268. 'site.ini/SiteSettings/IndexPage' => $indexPage !== null ? $indexPage : "/content/view/full/$rootLocationId/",
  269. 'site.ini/SiteSettings/DefaultPage' => $defaultPage !== null ? $defaultPage : "/content/view/full/$rootLocationId/",
  270. ];
  271. }
  272. private function getClusterSettings()
  273. {
  274. $clusterSettings = [];
  275. if ($this->container->hasParameter('dfs_nfs_path')) {
  276. $clusterSettings += [
  277. 'file.ini/ClusteringSettings/FileHandler' => 'eZDFSFileHandler',
  278. 'file.ini/eZDFSClusteringSettings/MountPointPath' => $this->container->getParameter('dfs_nfs_path'),
  279. 'file.ini/eZDFSClusteringSettings/DBHost' => $this->container->getParameter('dfs_database_host'),
  280. 'file.ini/eZDFSClusteringSettings/DBPort' => $this->container->getParameter('dfs_database_port'),
  281. 'file.ini/eZDFSClusteringSettings/DBName' => $this->container->getParameter('dfs_database_name'),
  282. 'file.ini/eZDFSClusteringSettings/DBUser' => $this->container->getParameter('dfs_database_user'),
  283. 'file.ini/eZDFSClusteringSettings/DBPassword' => $this->container->getParameter('dfs_database_password'),
  284. ];
  285. }
  286. return $clusterSettings;
  287. }
  288. private function loadPathPrefix($rootLocationId)
  289. {
  290. // If root location is 2 we know path is empty, so we can skip loading location + urlAlias data
  291. if ($rootLocationId === 2) {
  292. return '';
  293. }
  294. try {
  295. return trim($this->urlAliasGenerator->getPathPrefixByRootLocationId($rootLocationId), '/');
  296. } catch (Exception $e) {
  297. // Ignore any errors
  298. // Most probable cause for error is database not being ready yet,
  299. // i.e. initial install of the project which includes eZ Publish Legacy
  300. }
  301. return '';
  302. }
  303. }