JsonConfigSource.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Config;
  12. use Composer\Json\JsonFile;
  13. use Composer\Json\JsonManipulator;
  14. /**
  15. * JSON Configuration Source
  16. *
  17. * @author Jordi Boggiano <j.boggiano@seld.be>
  18. * @author Beau Simensen <beau@dflydev.com>
  19. */
  20. class JsonConfigSource implements ConfigSourceInterface
  21. {
  22. /**
  23. * @var \Composer\Json\JsonFile
  24. */
  25. private $file;
  26. /**
  27. * Constructor
  28. *
  29. * @param JsonFile $file
  30. */
  31. public function __construct(JsonFile $file)
  32. {
  33. $this->file = $file;
  34. }
  35. /**
  36. * {@inheritdoc}
  37. */
  38. public function addRepository($name, $config)
  39. {
  40. $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
  41. $config['repositories'][$repo] = $repoConfig;
  42. });
  43. }
  44. /**
  45. * {@inheritdoc}
  46. */
  47. public function removeRepository($name)
  48. {
  49. $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
  50. unset($config['repositories'][$repo]);
  51. });
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. public function addConfigSetting($name, $value)
  57. {
  58. $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) {
  59. $config['config'][$key] = $val;
  60. });
  61. }
  62. /**
  63. * {@inheritdoc}
  64. */
  65. public function removeConfigSetting($name)
  66. {
  67. $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) {
  68. unset($config['config'][$key]);
  69. });
  70. }
  71. /**
  72. * {@inheritdoc}
  73. */
  74. public function addLink($type, $name, $value)
  75. {
  76. $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
  77. $config[$type][$name] = $value;
  78. });
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function removeLink($type, $name)
  84. {
  85. $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
  86. unset($config[$type][$name]);
  87. });
  88. }
  89. protected function manipulateJson($method, $args, $fallback)
  90. {
  91. $args = func_get_args();
  92. // remove method & fallback
  93. array_shift($args);
  94. $fallback = array_pop($args);
  95. if ($this->file->exists()) {
  96. $contents = file_get_contents($this->file->getPath());
  97. } else {
  98. $contents = "{\n \"config\": {\n }\n}\n";
  99. }
  100. $manipulator = new JsonManipulator($contents);
  101. $newFile = !$this->file->exists();
  102. // try to update cleanly
  103. if (call_user_func_array(array($manipulator, $method), $args)) {
  104. file_put_contents($this->file->getPath(), $manipulator->getContents());
  105. } else {
  106. // on failed clean update, call the fallback and rewrite the whole file
  107. $config = $this->file->read();
  108. $this->array_unshift_ref($args, $config);
  109. call_user_func_array($fallback, $args);
  110. $this->file->write($config);
  111. }
  112. if ($newFile) {
  113. @chmod($this->file->getPath(), 0600);
  114. }
  115. }
  116. /**
  117. * Prepend a reference to an element to the beginning of an array.
  118. *
  119. * @param array $array
  120. * @param mixed $value
  121. * @return array
  122. */
  123. function array_unshift_ref(&$array, &$value)
  124. {
  125. $return = array_unshift($array, '');
  126. $array[0] =& $value;
  127. return $return;
  128. }
  129. }