PageRenderTime 33ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/code/utils/EasyCSV.php

https://github.com/rajeevgandhis/silverstripe-tools
PHP | 251 lines | 212 code | 32 blank | 7 comment | 43 complexity | c4e9f87734369f2a5c8f2c477d3c0638 MD5 | raw file
  1. <?php
  2. /**
  3. * Simple Object Oriented Interface for traversing a CSV file.
  4. *
  5. * @author William Wheatley <will@iwill.id.au>
  6. */
  7. class EasyCSV implements Iterator {
  8. private $file_handle;
  9. private $filename;
  10. private $columns;
  11. private $column_count;
  12. private $row;
  13. private $row_number;
  14. private $access_method;
  15. private $row_buffer;
  16. private $header;
  17. private $delimiter;
  18. public function __construct($filename, $process_header = true, $method = 'class', $delimiter = ",") {
  19. $this->filename = $filename;
  20. $this->file_handle = false;
  21. $this->columns = array();
  22. $this->row = false;
  23. $this->row_number = 0;
  24. $this->header = true;
  25. $this->delimiter = $delimiter;
  26. $this->set_access_method($method);
  27. $this->row_buffer = 5000;
  28. $this->process_header($process_header);
  29. }
  30. public function process_header($header) {
  31. if ($header) {
  32. $this->header = true;
  33. }
  34. else {
  35. $this->access_method = 'array';
  36. $this->header = false;
  37. }
  38. }
  39. public function set_row_buffer($buffer) {
  40. $this->row_buffer = intval($buffer);
  41. }
  42. public function set_delimiter($delimiter) {
  43. $this->delimiter = $delimiter;
  44. }
  45. public function set_access_method($method) {
  46. switch ($method) {
  47. case 'array':
  48. $this->access_method = 'array';
  49. break;
  50. case 'class':
  51. default:
  52. if ($this->header) {
  53. $this->access_method = 'class';
  54. }
  55. else {
  56. trigger_error('Cannot set CSV Access Method to "class" when not reading the header', E_USER_WARNING);
  57. $this->access_method = 'array';
  58. }
  59. }
  60. }
  61. static public function open($filename) {
  62. return new EasyCSV($filename);
  63. }
  64. public function __get($name) {
  65. if (array_key_exists($name, $this->columns)) {
  66. if ($this->row) {
  67. if (array_key_exists($this->columns[$name], $this->row)) {
  68. if (strlen($this->row[$this->columns[$name]])) {
  69. return $this->row[$this->columns[$name]];
  70. }
  71. else {
  72. return false;
  73. }
  74. }
  75. }
  76. else {
  77. trigger_error('Cannot Access a Row without loading the file', E_USER_WARNING);
  78. return false;
  79. }
  80. }
  81. else {
  82. trigger_error('Invalid Column Name: '.$name, E_USER_WARNING);
  83. return false;
  84. }
  85. }
  86. public function __isset($name) {
  87. if (array_key_exists($name, $this->columns)) {
  88. if ($this->row) {
  89. if (strlen($this->row[$this->columns[$name]])) {
  90. return true;
  91. }
  92. else {
  93. return false;
  94. }
  95. }
  96. else {
  97. trigger_error('Cannot Access a Row without loading the file', E_USER_WARNING);
  98. return false;
  99. }
  100. }
  101. }
  102. public function set_columns($columns) {
  103. foreach($columns as $column) {
  104. $this->columns[$column] = count($this->columns);
  105. }
  106. $this->header = true;
  107. $this->column_count = count($this->columns);
  108. $this->set_access_method('class');
  109. }
  110. private function read_column_titles() {
  111. $row = fgetcsv($this->file_handle, $this->row_buffer, $this->delimiter);
  112. $blank_count = 0;
  113. foreach ($row as $column_name) {
  114. $column_name = trim($column_name);
  115. $column_name = str_replace(' ','_',$column_name);
  116. if (!strlen($column_name)) {
  117. $blank_count++;
  118. $column_name = 'Blank_'.$blank_count;
  119. }
  120. if (array_key_exists($column_name, $this->columns)) {
  121. trigger_error("Duplicate column name '$column_name' in file '$this->filename'", E_USER_ERROR);
  122. }
  123. else {
  124. $this->columns[$column_name] = count($this->columns);
  125. }
  126. }
  127. $this->column_count = count($this->columns);
  128. }
  129. public function rewind() {
  130. if ($this->file_handle) {
  131. rewind($this->file_handle);
  132. // Read in the Column headers
  133. if ($this->header) {
  134. fgetcsv($this->file_handle, $this->row_buffer, $this->delimiter);
  135. $this->row_number = 1;
  136. }
  137. else {
  138. $this->row_number = 0;
  139. }
  140. $this->next();
  141. }
  142. else {
  143. $this->file_handle = fopen($this->filename, 'r');
  144. if ($this->file_handle) {
  145. if ($this->header) {
  146. $this->read_column_titles();
  147. $this->row_number = 1;
  148. }
  149. else {
  150. $this->row_number = 0;
  151. }
  152. $this->next();
  153. }
  154. else {
  155. trigger_error('Could not open file: '.$this->filename, E_USER_ERROR);
  156. }
  157. }
  158. }
  159. public function valid() {
  160. if ($this->row) {
  161. return true;
  162. }
  163. else {
  164. return false;
  165. }
  166. }
  167. public function current() {
  168. if ($this->row) {
  169. if ($this->access_method == 'array') {
  170. if ($this->header) {
  171. $row_count = count($this->row);
  172. if ($this->column_count == $row_count) {
  173. return array_combine(array_keys($this->columns), $this->row);
  174. }
  175. else if ($this->column_count > $row_count) {
  176. // Pad out the Row to equal the number of columns
  177. return array_combine(
  178. array_keys($this->columns),
  179. array_merge($this->row, array_fill($row_count, $this->column_count - $row_count, false)));
  180. }
  181. else if ($this->column_count < $row_count) {
  182. return array_combine(
  183. array_keys($this->columns),
  184. array_slice($this->row, 0, $this->column_count, true));
  185. }
  186. return array();
  187. }
  188. else {
  189. return $this->row;
  190. }
  191. }
  192. else {
  193. return $this;
  194. }
  195. }
  196. else {
  197. return false;
  198. }
  199. }
  200. public function key() {
  201. return $this->row_number;
  202. }
  203. public function get_line_number() {
  204. return $this->row_number;
  205. }
  206. public function index() {
  207. return $this->row_number - 1;
  208. }
  209. public function next() {
  210. $this->row = fgetcsv($this->file_handle, $this->row_buffer, $this->delimiter);
  211. $this->row_number++;
  212. }
  213. public function get_columns() {
  214. return $this->columns;
  215. }
  216. public function get_row() {
  217. return $this->row;
  218. }
  219. }