Add CSV file data source
authorChristian Weiske <cweiske@cweiske.de>
Wed, 18 Mar 2015 19:42:33 +0000 (20:42 +0100)
committerChristian Weiske <cweiske@cweiske.de>
Wed, 18 Mar 2015 19:42:33 +0000 (20:42 +0100)
README.rst
src/bdrem/Source/Csv.php [new file with mode: 0644]

index a451e3948fe39a1743b0200ec2b584297866ec9f..e503d3b2aaed5c3482d7291b4eb132bd7e693705 100644 (file)
@@ -19,6 +19,7 @@ Data sources
   - Multiple date fields per record supported.
 - An LDAP server
 - `Birthday reminder <http://cweiske.de/birthday3.htm>`_ files (``.bdf``)
+- CSV files
 
 Output formats
 ==============
@@ -133,6 +134,63 @@ __ http://cweiske.de/birthday.htm
 __ http://cweiske.de/birthday3.htm 
 
 
+CSV file
+========
+Comma separated value files can be used with bdrem.
+They should at least contain a column with the name, and one with the date.
+
+Simple configuration if you use the default settings::
+
+    $source = array(
+        'Csv',
+        '/path/to/file.csv'
+    );
+
+Complex configuration::
+
+    $source = array(
+        'Csv',
+        array(
+            'filename' => '/path/to/file.csv',
+            'columns' => array(
+                'name'  => 0,
+                'event' => 1,
+                'date'  => 2
+            ),
+            'firstLineIsHeader' => true,
+            'defaultEvent' => 'Birthday',
+            'separator' => ',',
+        )
+    );
+
+Configuration options
+---------------------
+``columns``
+  Determines the position of the name, event and date columns.
+  ``0`` is the first column.
+  You can use ``false`` to disable a column; helpful if there is no
+  ``event`` column.
+
+  Default:
+
+  ``array('name' => 0, 'event' => 1, 'date' => 2)``
+  
+``defaultEvent``
+  Text to use as event if there is no event column.
+
+  Defaults to ``Birthday``
+
+``firstLineIsHeader``
+  If the first line in the CSV is column header data
+
+  Defaults to ``true``
+
+``separator``
+  How columns are separated.
+
+  Defaults to ``,``
+
+
 LDAP server
 ===========
 *bdrem* can read birthdays and other events from persons in an LDAP server.
diff --git a/src/bdrem/Source/Csv.php b/src/bdrem/Source/Csv.php
new file mode 100644 (file)
index 0000000..62cf777
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Part of bdrem
+ *
+ * PHP version 5
+ *
+ * @category  Tools
+ * @package   Bdrem
+ * @author    Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link      http://cweiske.de/bdrem.htm
+ */
+namespace bdrem;
+
+/**
+ * Reads comma separated value files (CSV)
+ *
+ * @category  Tools
+ * @package   Bdrem
+ * @author    Christian Weiske <cweiske@cweiske.de>
+ * @copyright 2014 Christian Weiske
+ * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
+ * @link      http://cweiske.de/bdrem.htm
+ */
+class Source_Csv
+{
+    /**
+     * Full path of CSV file
+     * @var string
+     */
+    protected $filename;
+
+    /**
+     * If the first line is to be seen as header
+     * @var boolean
+     */
+    protected $firstLineIsHeader = true;
+
+    /**
+     * If the CSV does not contain a column for the event type,
+     * this text will be used.
+     * @var string
+     */
+    protected $defaultEvent = 'Birthday';
+
+    /**
+     * Field separator in the CSV file
+     * @var string
+     */
+    protected $separator = ',';
+
+    /**
+     * Position of the name, event and date columns. First column is 0.
+     * Use "false" to disable the column (useful for "event").
+     *
+     * @var array
+     */
+    protected $columns = array(
+        'name'  => 0,
+        'event' => 1,
+        'date'  => 2,
+    );
+
+    /**
+     * Set the CSV file name
+     *
+     * @param array|string $config Config array or path to CSV file
+     */
+    public function __construct($config)
+    {
+        if (is_string($config)) {
+            $config = array(
+                'filename' => $config
+            );
+        }
+        $this->filename = $config['filename'];
+        if (!file_exists($this->filename)) {
+            throw new \Exception(
+                'CSV file does not exist: ' . $this->filename
+            );
+        }
+        if (isset($config['columns'])) {
+            $this->columns = $config['columns'];
+        }
+        if (isset($config['defaultEvent'])) {
+            $this->defaultEvent = $config['defaultEvent'];
+        }
+        if (isset($config['separator'])) {
+            $this->separator = $config['separator'];
+        }
+    }
+
+    /**
+     * Return all events for the given date range
+     *
+     * @param string  $strDate       Date the events shall be found for,
+     *                               YYYY-MM-DD
+     * @param integer $nDaysPrevious Include number of days before $strDate
+     * @param integer $nDaysNext     Include number of days after $strDate
+     *
+     * @return Event[] Array of matching event objects
+     */
+    public function getEvents($strDate, $nDaysPrevious, $nDaysNext)
+    {
+        $handle = fopen($this->filename, 'r');
+        if ($handle === false) {
+            throw new \Exception('Error opening CSV file');
+        }
+
+        $first = true;
+        while (($row = fgetcsv($handle, 1000, $this->separator)) !== false) {
+            if ($first && $this->firstLineIsHeader) {
+                $first = false;
+                continue;
+            }
+
+            if ($this->columns['event'] === false) {
+                $eventType = $this->defaultEvent;
+            } else {
+                $eventType = $row[$this->columns['event']];
+            }
+
+            if ($row[$this->columns['date']] == '') {
+                continue;
+            }
+            //convert from DD.MM.YYYY to YYYY-MM-DD
+            $date = implode(
+                '-',
+                array_reverse(
+                    explode('.', $row[$this->columns['date']])
+                )
+            );
+
+            $event = new Event(
+                (string) $row[$this->columns['name']],
+                $eventType,
+                $date
+            );
+            if ($event->isWithin($strDate, $nDaysPrevious, $nDaysNext)) {
+                $arEvents[] = $event;
+            }
+        }
+        fclose($handle);
+        return $arEvents;
+    }
+}
+?>