Catch CSV errors
[bdrem.git] / src / bdrem / Source / Csv.php
1 <?php
2 /**
3  * Part of bdrem
4  *
5  * PHP version 5
6  *
7  * @category  Tools
8  * @package   Bdrem
9  * @author    Christian Weiske <cweiske@cweiske.de>
10  * @copyright 2014 Christian Weiske
11  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
12  * @link      http://cweiske.de/bdrem.htm
13  */
14 namespace bdrem;
15
16 /**
17  * Reads comma separated value files (CSV)
18  *
19  * @category  Tools
20  * @package   Bdrem
21  * @author    Christian Weiske <cweiske@cweiske.de>
22  * @copyright 2014 Christian Weiske
23  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
24  * @link      http://cweiske.de/bdrem.htm
25  */
26 class Source_Csv
27 {
28     /**
29      * Full path of CSV file
30      * @var string
31      */
32     protected $filename;
33
34     /**
35      * If the first line is to be seen as header
36      * @var boolean
37      */
38     protected $firstLineIsHeader = true;
39
40     /**
41      * If the CSV does not contain a column for the event type,
42      * this text will be used.
43      * @var string
44      */
45     protected $defaultEvent = 'Birthday';
46
47     /**
48      * Field separator in the CSV file
49      * @var string
50      */
51     protected $separator = ',';
52
53     /**
54      * Position of the name, event and date columns. First column is 0.
55      * Use "false" to disable the column (useful for "event").
56      *
57      * @var array
58      */
59     protected $columns = array(
60         'name'  => 0,
61         'event' => 1,
62         'date'  => 2,
63     );
64
65     /**
66      * Set the CSV file name
67      *
68      * @param array|string $config Config array or path to CSV file
69      */
70     public function __construct($config)
71     {
72         if (is_string($config)) {
73             $config = array(
74                 'filename' => $config
75             );
76         }
77         $this->filename = $config['filename'];
78         if (!file_exists($this->filename)) {
79             throw new \Exception(
80                 'CSV file does not exist: ' . $this->filename
81             );
82         }
83         if (isset($config['columns'])) {
84             $this->columns = $config['columns'];
85         }
86         if (isset($config['defaultEvent'])) {
87             $this->defaultEvent = $config['defaultEvent'];
88         }
89         if (isset($config['separator'])) {
90             $this->separator = $config['separator'];
91         }
92     }
93
94     /**
95      * Return all events for the given date range
96      *
97      * @param string  $strDate       Date the events shall be found for,
98      *                               YYYY-MM-DD
99      * @param integer $nDaysPrevious Include number of days before $strDate
100      * @param integer $nDaysNext     Include number of days after $strDate
101      *
102      * @return Event[] Array of matching event objects
103      */
104     public function getEvents($strDate, $nDaysPrevious, $nDaysNext)
105     {
106         $handle = fopen($this->filename, 'r');
107         if ($handle === false) {
108             throw new \Exception('Error opening CSV file');
109         }
110
111         $first = true;
112         $arEvents = array();
113         while (($row = fgetcsv($handle, 1000, $this->separator)) !== false) {
114             if ($first && $this->firstLineIsHeader) {
115                 $first = false;
116                 continue;
117             }
118
119             if ($this->columns['event'] === false) {
120                 $eventType = $this->defaultEvent;
121             } else {
122                 if (!isset($row[$this->columns['event']])) {
123                     throw new \Exception('Event column does not exist in CSV');
124                 }
125                 $eventType = $row[$this->columns['event']];
126             }
127
128             if (!isset($row[$this->columns['date']])) {
129                 throw new \Exception('Date column does not exist in CSV');
130             }
131             if ($row[$this->columns['date']] == '') {
132                 continue;
133             }
134             //convert from DD.MM.YYYY to YYYY-MM-DD
135             $date = implode(
136                 '-',
137                 array_reverse(
138                     explode('.', $row[$this->columns['date']])
139                 )
140             );
141
142             if (!isset($row[$this->columns['name']])) {
143                 throw new \Exception('Name column does not exist in CSV');
144             }
145
146             $event = new Event(
147                 (string) $row[$this->columns['name']],
148                 $eventType,
149                 $date
150             );
151             if ($event->isWithin($strDate, $nDaysPrevious, $nDaysNext)) {
152                 $arEvents[] = $event;
153             }
154         }
155         fclose($handle);
156         return $arEvents;
157     }
158 }
159 ?>