Properties.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. /*
  3. * $Id: Properties.php 905 2010-10-05 16:28:03Z mrook $
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information please see
  19. * <http://phing.info>.
  20. */
  21. include_once 'phing/system/io/PhingFile.php';
  22. include_once 'phing/system/io/FileWriter.php';
  23. /**
  24. * Convenience class for reading and writing property files.
  25. *
  26. * FIXME
  27. * - Add support for arrays (separated by ',')
  28. *
  29. * @package phing.system.util
  30. * @version $Revision: 905 $
  31. */
  32. class Properties {
  33. private $properties = array();
  34. /**
  35. * Load properties from a file.
  36. *
  37. * @param PhingFile $file
  38. * @return void
  39. * @throws IOException - if unable to read file.
  40. */
  41. function load(PhingFile $file) {
  42. if ($file->canRead()) {
  43. $this->parse($file->getPath(), false);
  44. } else {
  45. throw new IOException("Can not read file ".$file->getPath());
  46. }
  47. }
  48. /**
  49. * Replaces parse_ini_file() or better_parse_ini_file().
  50. * Saves a step since we don't have to parse and then check return value
  51. * before throwing an error or setting class properties.
  52. *
  53. * @param string $filePath
  54. * @param boolean $processSections Whether to honor [SectionName] sections in INI file.
  55. * @return array Properties loaded from file (no prop replacements done yet).
  56. */
  57. protected function parse($filePath) {
  58. // load() already made sure that file is readable
  59. // but we'll double check that when reading the file into
  60. // an array
  61. if (($lines = @file($filePath)) === false) {
  62. throw new IOException("Unable to parse contents of $filePath");
  63. }
  64. $this->properties = array();
  65. $sec_name = "";
  66. foreach($lines as $line) {
  67. $line = trim($line);
  68. if($line == "")
  69. continue;
  70. if ($line{0} == '#' or $line{0} == ';') {
  71. // it's a comment, so continue to next line
  72. continue;
  73. } else {
  74. $pos = strpos($line, '=');
  75. $property = trim(substr($line, 0, $pos));
  76. $value = trim(substr($line, $pos + 1));
  77. $this->properties[$property] = $this->inVal($value);
  78. }
  79. } // for each line
  80. }
  81. /**
  82. * Process values when being read in from properties file.
  83. * does things like convert "true" => true
  84. * @param string $val Trimmed value.
  85. * @return mixed The new property value (may be boolean, etc.)
  86. */
  87. protected function inVal($val) {
  88. if ($val === "true") {
  89. $val = true;
  90. } elseif ($val === "false") {
  91. $val = false;
  92. }
  93. return $val;
  94. }
  95. /**
  96. * Process values when being written out to properties file.
  97. * does things like convert true => "true"
  98. * @param mixed $val The property value (may be boolean, etc.)
  99. * @return string
  100. */
  101. protected function outVal($val) {
  102. if ($val === true) {
  103. $val = "true";
  104. } elseif ($val === false) {
  105. $val = "false";
  106. }
  107. return $val;
  108. }
  109. /**
  110. * Create string representation that can be written to file and would be loadable using load() method.
  111. *
  112. * Essentially this function creates a string representation of properties that is ready to
  113. * write back out to a properties file. This is used by store() method.
  114. *
  115. * @return string
  116. */
  117. public function toString() {
  118. $buf = "";
  119. foreach($this->properties as $key => $item) {
  120. $buf .= $key . "=" . $this->outVal($item) . PHP_EOL;
  121. }
  122. return $buf;
  123. }
  124. /**
  125. * Stores current properties to specified file.
  126. *
  127. * @param PhingFile $file File to create/overwrite with properties.
  128. * @param string $header Header text that will be placed (within comments) at the top of properties file.
  129. * @return void
  130. * @throws IOException - on error writing properties file.
  131. */
  132. function store(PhingFile $file, $header = null) {
  133. // stores the properties in this object in the file denoted
  134. // if file is not given and the properties were loaded from a
  135. // file prior, this method stores them in the file used by load()
  136. try {
  137. $fw = new FileWriter($file);
  138. if ($header !== null) {
  139. $fw->write( "# " . $header . PHP_EOL );
  140. }
  141. $fw->write($this->toString());
  142. $fw->close();
  143. } catch (IOException $e) {
  144. throw new IOException("Error writing property file: " . $e->getMessage());
  145. }
  146. }
  147. /**
  148. * Returns copy of internal properties hash.
  149. * Mostly for performance reasons, property hashes are often
  150. * preferable to passing around objects.
  151. *
  152. * @return array
  153. */
  154. function getProperties() {
  155. return $this->properties;
  156. }
  157. /**
  158. * Get value for specified property.
  159. * This is the same as get() method.
  160. *
  161. * @param string $prop The property name (key).
  162. * @return mixed
  163. * @see get()
  164. */
  165. function getProperty($prop) {
  166. if (!isset($this->properties[$prop])) {
  167. return null;
  168. }
  169. return $this->properties[$prop];
  170. }
  171. /**
  172. * Get value for specified property.
  173. * This function exists to provide a hashtable-like interface for
  174. * properties.
  175. *
  176. * @param string $prop The property name (key).
  177. * @return mixed
  178. * @see getProperty()
  179. */
  180. function get($prop) {
  181. if (!isset($this->properties[$prop])) {
  182. return null;
  183. }
  184. return $this->properties[$prop];
  185. }
  186. /**
  187. * Set the value for a property.
  188. *
  189. * @param string $key
  190. * @param mixed $value
  191. * @return mixed Old property value or NULL if none was set.
  192. */
  193. function setProperty($key, $value) {
  194. $oldValue = null;
  195. if (isset($this->properties[$key])) {
  196. $oldValue = $this->properties[$key];
  197. }
  198. $this->properties[$key] = $value;
  199. return $oldValue;
  200. }
  201. /**
  202. * Set the value for a property.
  203. * This function exists to provide hashtable-lie
  204. * interface for properties.
  205. *
  206. * @param string $key
  207. * @param mixed $value
  208. */
  209. function put($key, $value) {
  210. return $this->setProperty($key, $value);
  211. }
  212. /**
  213. * Appends a value to a property if it already exists with a delimiter
  214. *
  215. * If the property does not, it just adds it.
  216. *
  217. * @param string $key
  218. * @param mixed $value
  219. * @param string $delimiter
  220. */
  221. function append($key, $value, $delimiter = ',') {
  222. $newValue = $value;
  223. if (isset($this->properties[$key]) && !empty($this->properties[$key]) ) {
  224. $newValue = $this->properties[$key] . $delimiter . $value;
  225. }
  226. $this->properties[$key] = $newValue;
  227. }
  228. /**
  229. * Same as keys() function, returns an array of property names.
  230. * @return array
  231. */
  232. function propertyNames() {
  233. return $this->keys();
  234. }
  235. /**
  236. * Whether loaded properties array contains specified property name.
  237. * @return boolean
  238. */
  239. function containsKey($key) {
  240. return isset($this->properties[$key]);
  241. }
  242. /**
  243. * Returns properties keys.
  244. * Use this for foreach() {} iterations, as this is
  245. * faster than looping through property values.
  246. * @return array
  247. */
  248. function keys() {
  249. return array_keys($this->properties);
  250. }
  251. /**
  252. * Whether properties list is empty.
  253. * @return boolean
  254. */
  255. function isEmpty() {
  256. return empty($this->properties);
  257. }
  258. }