/app/bundles/CoreBundle/Configurator/Configurator.php

https://gitlab.com/mautic-master/mautic · PHP · 314 lines · 151 code · 45 blank · 118 comment · 14 complexity · c47b4d62af4a9d27cd05028c95c2165f MD5 · raw file

  1. <?php
  2. /**
  3. * @package Mautic
  4. * @copyright 2014 Mautic Contributors. All rights reserved.
  5. * @author Mautic
  6. * @link http://mautic.org
  7. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
  8. */
  9. namespace Mautic\CoreBundle\Configurator;
  10. use Mautic\CoreBundle\Configurator\Step\StepInterface;
  11. use Mautic\CoreBundle\Helper\PathsHelper;
  12. use Symfony\Component\Process\Exception\RuntimeException;
  13. /**
  14. * Configurator.
  15. *
  16. * @author Marc Weistroff <marc.weistroff@gmail.com>
  17. * @note This class is based on Sensio\Bundle\DistributionBundle\Configurator\Configurator
  18. */
  19. class Configurator
  20. {
  21. /**
  22. * Configuration filename
  23. *
  24. * @var string
  25. */
  26. protected $filename;
  27. /**
  28. * Array containing the steps
  29. *
  30. * @var StepInterface[]
  31. */
  32. protected $steps = array();
  33. /**
  34. * Array containing the sorted steps
  35. *
  36. * @var StepInterface[]
  37. */
  38. protected $sortedSteps = array();
  39. /**
  40. * Configuration parameters
  41. *
  42. * @var array
  43. */
  44. protected $parameters;
  45. /**
  46. * Configurator constructor.
  47. *
  48. * @param PathsHelper $pathsHelper
  49. */
  50. public function __construct(PathsHelper $pathsHelper)
  51. {
  52. $this->filename = $pathsHelper->getSystemPath('local_config');
  53. $this->parameters = $this->read();
  54. }
  55. /**
  56. * Check if the configuration path is writable.
  57. *
  58. * @return bool
  59. */
  60. public function isFileWritable()
  61. {
  62. // If there's already a file, check it
  63. if (file_exists($this->filename)) {
  64. return is_writable($this->filename);
  65. }
  66. // If there isn't already, we check the parent folder
  67. return is_writable(dirname($this->filename));
  68. }
  69. /**
  70. * Add a step to the configurator.
  71. *
  72. * @param StepInterface $step
  73. * @param int $priority
  74. */
  75. public function addStep(StepInterface $step, $priority = 0)
  76. {
  77. if (!isset($this->steps[$priority])) {
  78. $this->steps[$priority] = array();
  79. }
  80. $this->steps[$priority][] = $step;
  81. $this->sortedSteps = array();
  82. }
  83. /**
  84. * Retrieves the specified step.
  85. *
  86. * @param integer $index
  87. *
  88. * @return StepInterface
  89. * @throws \InvalidArgumentException
  90. */
  91. public function getStep($index)
  92. {
  93. if (isset($this->steps[$index])) {
  94. return $this->steps[$index];
  95. }
  96. throw new \InvalidArgumentException(sprintf('There is not a step %s', $index));
  97. }
  98. /**
  99. * Retrieves the loaded steps in sorted order.
  100. *
  101. * @return array
  102. */
  103. public function getSteps()
  104. {
  105. if ($this->sortedSteps === array()) {
  106. $this->sortedSteps = $this->getSortedSteps();
  107. }
  108. return $this->sortedSteps;
  109. }
  110. /**
  111. * Sort routers by priority.
  112. * The highest priority number is the highest priority (reverse sorting).
  113. *
  114. * @return StepInterface[]
  115. */
  116. private function getSortedSteps()
  117. {
  118. $sortedSteps = array();
  119. krsort($this->steps);
  120. foreach ($this->steps as $steps) {
  121. $sortedSteps = array_merge($sortedSteps, $steps);
  122. }
  123. return $sortedSteps;
  124. }
  125. /**
  126. * Retrieves the configuration parameters.
  127. *
  128. * @return array
  129. */
  130. public function getParameters()
  131. {
  132. return $this->parameters;
  133. }
  134. /**
  135. * Return the number of steps in the configurator.
  136. *
  137. * @return integer
  138. */
  139. public function getStepCount()
  140. {
  141. return count($this->getSteps());
  142. }
  143. /**
  144. * Merges parameters to the main configuration.
  145. *
  146. * @param array $parameters
  147. */
  148. public function mergeParameters($parameters)
  149. {
  150. $this->parameters = array_merge($this->parameters, $parameters);
  151. }
  152. /**
  153. * Fetches the requirements from the defined steps.
  154. *
  155. * @return array
  156. */
  157. public function getRequirements()
  158. {
  159. $majors = array();
  160. foreach ($this->getSteps() as $step) {
  161. foreach ($step->checkRequirements() as $major) {
  162. $majors[] = $major;
  163. }
  164. }
  165. return $majors;
  166. }
  167. /**
  168. * Fetches the optional settings from the defined steps.
  169. *
  170. * @return array
  171. */
  172. public function getOptionalSettings()
  173. {
  174. $minors = array();
  175. foreach ($this->getSteps() as $step) {
  176. foreach ($step->checkOptionalSettings() as $minor) {
  177. $minors[] = $minor;
  178. }
  179. }
  180. return $minors;
  181. }
  182. /**
  183. * Renders parameters as a string.
  184. *
  185. * @return string
  186. */
  187. public function render()
  188. {
  189. $string = "<?php\n";
  190. $string .= "\$parameters = array(\n";
  191. foreach ($this->parameters as $key => $value) {
  192. if ($value !== '') {
  193. if (is_string($value)) {
  194. $value = "'" . addslashes($value) . "'";
  195. } elseif (is_bool($value)) {
  196. $value = ($value) ? 'true' : 'false';
  197. } elseif (is_null($value)) {
  198. $value = 'null';
  199. } elseif (is_array($value)) {
  200. $value = $this->renderArray($value);
  201. }
  202. $string .= "\t'$key' => $value,\n";
  203. }
  204. }
  205. $string .= ");\n";
  206. return $string;
  207. }
  208. /**
  209. * @param $array
  210. * @param int $level
  211. *
  212. * @return string
  213. */
  214. protected function renderArray($array, $level = 1)
  215. {
  216. $string = "array(\n";
  217. $count = $counter = count($array);
  218. foreach ($array as $key => $value) {
  219. if (is_string($key) or is_numeric($key)) {
  220. if ($counter === $count) {
  221. $string .= str_repeat("\t", $level + 1);
  222. }
  223. $string .= '"'.$key.'" => ';
  224. }
  225. if (is_array($value)) {
  226. $string .= $this->renderArray($value, $level + 1);
  227. } else {
  228. $string .= '"'.addslashes($value).'"';
  229. }
  230. $counter--;
  231. if ($counter > 0) {
  232. $string .= ", \n" . str_repeat("\t", $level + 1);
  233. }
  234. }
  235. $string .= "\n" . str_repeat("\t", $level) . ")";
  236. return $string;
  237. }
  238. /**
  239. * Writes parameters to file.
  240. *
  241. * @return integer
  242. * @throws \Symfony\Component\Process\Exception\RuntimeException
  243. */
  244. public function write()
  245. {
  246. if (!$this->isFileWritable()) {
  247. throw new RuntimeException('Cannot write the config file, the destination is unwritable.');
  248. }
  249. $return = file_put_contents($this->filename, $this->render());
  250. if ($return === false) {
  251. throw new RuntimeException('An error occurred while attempting to write the config file to the filesystem.');
  252. }
  253. return $return;
  254. }
  255. /**
  256. * Reads parameters from file.
  257. *
  258. * @return array
  259. */
  260. protected function read()
  261. {
  262. if (!file_exists($this->filename)) {
  263. return array();
  264. }
  265. include $this->filename;
  266. // Return the $parameters array defined in the file
  267. return isset($parameters) ? $parameters : array();
  268. }
  269. }