Update Horde_Data to H4
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 12 May 2010 21:34:26 +0000 (15:34 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 14 May 2010 20:08:42 +0000 (14:08 -0600)
Remove dependency on Core.

This library still is way too much of a UI/widget-y class and not enough
of a standalone library.

39 files changed:
fima/data.php
framework/Core/lib/Horde/Core/Binder/Data.php [new file with mode: 0644]
framework/Core/lib/Horde/Core/Factory/Data.php [new file with mode: 0644]
framework/Core/lib/Horde/Registry.php
framework/Core/package.xml
framework/Data/Data.php [deleted file]
framework/Data/Data/csv.php [deleted file]
framework/Data/Data/icalendar.php [deleted file]
framework/Data/Data/imc.php [deleted file]
framework/Data/Data/outlookcsv.php [deleted file]
framework/Data/Data/tsv.php [deleted file]
framework/Data/Data/vcard.php [deleted file]
framework/Data/Data/vnote.php [deleted file]
framework/Data/Data/vtodo.php [deleted file]
framework/Data/lib/Horde/Data.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Csv.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Driver.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Exception.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Icalendar.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Imc.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Outlookcsv.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Tsv.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Vcard.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Vnote.php [new file with mode: 0644]
framework/Data/lib/Horde/Data/Vtodo.php [new file with mode: 0644]
framework/Data/package.xml
framework/Data/test/Horde/Data/csv_importFile_01.phpt [new file with mode: 0644]
framework/Data/test/Horde/Data/simple_dos.csv [new file with mode: 0644]
framework/Data/test/Horde/Data/simple_unix.csv [new file with mode: 0644]
framework/Data/tests/csv_importFile_01.phpt [deleted file]
framework/Data/tests/simple_dos.csv [deleted file]
framework/Data/tests/simple_unix.csv [deleted file]
kronolith/data.php
mnemo/data.php
nag/data.php
operator/lib/Form/SearchCDR.php
skoli/data.php
turba/data.php
turba/vcard.php

index 70f976e..69198e0 100644 (file)
@@ -6,16 +6,14 @@
  * did not receive this file, see http://www.horde.org/licenses/asl.php.
  */
 
-function _cleanup()
+function _cleanupData()
 {
-    global $import_step;
-    $import_step = 1;
-    return IMPORT_FILE;
+    $GLOBALS['import_step'] = 1;
+    return Horde_Data::IMPORT_FILE;
 }
 
 @define('FIMA_BASE', dirname(__FILE__));
 require_once FIMA_BASE . '/lib/base.php';
-require_once 'Horde/Data.php';
 
 $ledger = Fima::getActiveLedger();
 
@@ -25,11 +23,11 @@ $file_types = array('csv'      => _("CSV"),
 
 /* Templates for the different import steps. */
 $templates = array(
-    IMPORT_CSV => array($registry->get('templates', 'horde') . '/data/csvinfo.inc'),
-    IMPORT_TSV => array($registry->get('templates', 'horde') . '/data/tsvinfo.inc'),
-    IMPORT_MAPPED => array($registry->get('templates', 'horde') . '/data/csvmap.inc'),
-    IMPORT_DATETIME => array($registry->get('templates', 'horde') . '/data/datemap.inc'),
-    IMPORT_FILE => array(FIMA_TEMPLATES . '/data/import.inc', FIMA_TEMPLATES . '/data/export.inc'),
+    Horde_Data::IMPORT_CSV => array($registry->get('templates', 'horde') . '/data/csvinfo.inc'),
+    Horde_Data::IMPORT_TSV => array($registry->get('templates', 'horde') . '/data/tsvinfo.inc'),
+    Horde_Data::IMPORT_MAPPED => array($registry->get('templates', 'horde') . '/data/csvmap.inc'),
+    Horde_Data::IMPORT_DATETIME => array($registry->get('templates', 'horde') . '/data/datemap.inc'),
+    Horde_Data::IMPORT_FILE => array(FIMA_TEMPLATES . '/data/import.inc', FIMA_TEMPLATES . '/data/export.inc'),
 );
 
 /* Field/clear name mapping. */
@@ -48,7 +46,7 @@ $param = array('time_fields' => $time_fields,
                'file_types'  => $file_types);
 $import_format = Horde_Util::getFormData('import_format', '');
 $import_step   = Horde_Util::getFormData('import_step', 0) + 1;
-$next_step     = IMPORT_FILE;
+$next_step     = Horde_Data::IMPORT_FILE;
 $actionID      = Horde_Util::getFormData('actionID');
 $error         = false;
 
@@ -56,7 +54,7 @@ $error         = false;
 switch ($actionID) {
 case 'export':
     $data = array();
-    
+
     /* Create a Fima storage instance. */
     $storage = &Fima_Driver::singleton($ledger);
     if (is_a($storage, 'PEAR_Error')) {
@@ -65,13 +63,13 @@ case 'export':
         break;
     }
     $params = $storage->getParams();
-    
+
     $filters = array(array('type', $prefs->getValue('active_postingtype')));
 
     /* Get accounts and postings. */
     $accounts = Fima::listAccounts();
     $postings = Fima::listPostings($filters);
-   
+
     foreach ($postings as $postingId => $posting) {
         $row = array();
         foreach ($posting as $key => $value) {
@@ -105,18 +103,16 @@ case 'export':
 
     switch (Horde_Util::getFormData('exportID')) {
     case EXPORT_CSV:
-        $csv = &Horde_Data::singleton('csv');
-        $csv->exportFile(_("postings.csv"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))->exportFile(_("postings.csv"), $data, true);
         exit;
 
     case EXPORT_TSV:
-        $tsv = &Horde_Data::singleton('tsv');
-        $tsv->exportFile(_("postings.tsv"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Tsv', array('cleanup' => '_cleanupData'))->exportFile(_("postings.tsv"), $data, true);
         exit;
     }
     break;
 
-case IMPORT_FILE:
+case Horde_Data::IMPORT_FILE:
     $storage = &Fima_Driver::singleton($ledger);
     if (is_a($storage, 'PEAR_Error')) {
         $notification->push(sprintf(_("Failed to access the ledger: %s"), $storage->getMessage()), 'horde.error');
@@ -130,15 +126,16 @@ case IMPORT_FILE:
 }
 
 if (!$error) {
-    $data = &Horde_Data::singleton($import_format);
-    if (is_a($data, 'PEAR_Error')) {
-        $notification->push(_("This file format is not supported."), 'horde.error');
-        $next_step = IMPORT_FILE;
-    } else {
+    try {
+        $data = $injector->getInstance('Horde_Data')->getOb($import_format, array('cleanup' => '_cleanupData'));
         $next_step = $data->nextStep($actionID, $param);
-        if (is_a($next_step, 'PEAR_Error')) {
-            $notification->push($next_step->getMessage(), 'horde.error');
+    } catch (Horde_Data_Exception $e) {
+        if ($data) {
+            $notification->push($e, 'horde.error');
             $next_step = $data->cleanup();
+        } else {
+            $notification->push(_("This file format is not supported."), 'horde.error');
+            $next_step = Horde_Data::IMPORT_FILE;
         }
     }
 }
@@ -198,9 +195,6 @@ if (is_array($next_step)) {
     if (!count($next_step)) {
         $notification->push(sprintf(_("The %s file didn't contain any postings."),
                                     $file_types[$_SESSION['import_data']['format']]), 'horde.error');
-    } elseif (is_a($result, 'PEAR_Error')) {
-        $notification->push(sprintf(_("There was an error importing the data: %s"),
-                                    $result->getMessage()), 'horde.error');
     } else {
         $notification->push(sprintf(_("%s successfully imported"),
                                     $file_types[$_SESSION['import_data']['format']]), 'horde.success');
@@ -212,7 +206,7 @@ $title = _("Import/Export Postings");
 require FIMA_TEMPLATES . '/common-header.inc';
 require FIMA_TEMPLATES . '/menu.inc';
 
-if ($next_step == IMPORT_FILE) {
+if ($next_step == Horde_Data::IMPORT_FILE) {
     /* Build the charset options. */
     $charsets = Horde_Nls::$config['encodings'];
     $all_charsets = Horde_Nls::$config['charsets'];
diff --git a/framework/Core/lib/Horde/Core/Binder/Data.php b/framework/Core/lib/Horde/Core/Binder/Data.php
new file mode 100644 (file)
index 0000000..83d0df8
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ * @category Horde
+ * @package  Core
+ */
+class Horde_Core_Binder_Data implements Horde_Injector_Binder
+{
+    public function create(Horde_Injector $injector)
+    {
+        return new Horde_Core_Factory_Data($injector);
+    }
+
+    public function equals(Horde_Injector_Binder $binder)
+    {
+        return false;
+    }
+}
diff --git a/framework/Core/lib/Horde/Core/Factory/Data.php b/framework/Core/lib/Horde/Core/Factory/Data.php
new file mode 100644 (file)
index 0000000..de94899
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/**
+ * A Horde_Injector:: based Horde_Data:: factory.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package  Core
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Core
+ */
+
+/**
+ * A Horde_Injector:: based Horde_Data:: factory.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package  Core
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Core
+ */
+class Horde_Core_Factory_Data
+{
+    /**
+     * The injector.
+     *
+     * @var Horde_Injector
+     */
+    private $_injector;
+
+    /**
+     * Constructor.
+     *
+     * @param Horde_Injector $injector  The injector to use.
+     */
+    public function __construct(Horde_Injector $injector)
+    {
+        $this->_injector = $injector;
+    }
+
+    /**
+     * Return the Horde_Data:: instance.
+     *
+     * @param string $driver  The driver.
+     * @param string $params  Driver parameters.
+     *
+     * @return Horde_Data_Driver  The instance.
+     * @throws Horde_Data_Exception
+     */
+    public function getOb($driver, array $params = array())
+    {
+        $params['browser'] = $this->_injector->getInstance('Horde_Browser');
+        $params['vars'] = Horde_Variables::getDefaultVariables();
+
+        return Horde_Data::factory($driver, $params);
+    }
+
+}
index 671aa50..cf81121 100644 (file)
@@ -236,6 +236,7 @@ class Horde_Registry
             'Horde_Alarm' => new Horde_Core_Binder_Alarm(),
             // 'Horde_Browser' - initialized below
             'Horde_Cache' => new Horde_Core_Binder_Cache(),
+            'Horde_Data' => new Horde_Core_Binder_Data(),
             'Horde_Db_Adapter_Base' => new Horde_Core_Binder_Db(),
             'Horde_Db_Pear' => new Horde_Core_Binder_DbPear(),
             'Horde_Editor' => new Horde_Core_Binder_Editor(),
index 29e7835..6290539 100644 (file)
@@ -67,6 +67,7 @@ Application Framework.
       <dir name="Binder">
        <file name="Alarm.php" role="php" />
        <file name="Cache.php" role="php" />
+       <file name="Data.php" role="php" />
        <file name="Db.php" role="php" />
        <file name="DbPear.php" role="php" />
        <file name="Dns.php" role="php" />
@@ -88,6 +89,7 @@ Application Framework.
       </dir> <!-- /lib/Horde/Core/Binder -->
       <dir name="Factory">
        <file name="DbPear.php" role="php" />
+       <file name="Data.php" role="php" />
        <file name="Editor.php" role="php" />
        <file name="Identity.php" role="php" />
        <file name="KolabServer.php" role="php" />
@@ -224,6 +226,7 @@ Application Framework.
    <install name="lib/Horde/Core/Autoloader/Callback/Mime.php" as="Horde/Core/Autoloader/Callback/Mime.php" />
    <install name="lib/Horde/Core/Binder/Alarm.php" as="Horde/Core/Binder/Alarm.php" />
    <install name="lib/Horde/Core/Binder/Cache.php" as="Horde/Core/Binder/Cache.php" />
+   <install name="lib/Horde/Core/Binder/Data.php" as="Horde/Core/Binder/Data.php" />
    <install name="lib/Horde/Core/Binder/Db.php" as="Horde/Core/Binder/Db.php" />
    <install name="lib/Horde/Core/Binder/DbPear.php" as="Horde/Core/Binder/DbPear.php" />
    <install name="lib/Horde/Core/Binder/Dns.php" as="Horde/Core/Binder/Dns.php" />
@@ -243,6 +246,7 @@ Application Framework.
    <install name="lib/Horde/Core/Binder/Vfs.php" as="Horde/Core/Binder/Vfs.php" />
    <install name="lib/Horde/Core/Binder/Facebook.php" as="Horde/Core/Binder/Facebook.php" />
    <install name="lib/Horde/Core/Factory/DbPear.php" as="Horde/Core/Factory/DbPear.php" />
+   <install name="lib/Horde/Core/Factory/Data.php" as="Horde/Core/Factory/Data.php" />
    <install name="lib/Horde/Core/Factory/Editor.php" as="Horde/Core/Factory/Editor.php" />
    <install name="lib/Horde/Core/Factory/Identity.php" as="Horde/Core/Factory/Identity.php" />
    <install name="lib/Horde/Core/Factory/KolabServer.php" as="Horde/Core/Factory/KolabServer.php" />
diff --git a/framework/Data/Data.php b/framework/Data/Data.php
deleted file mode 100644 (file)
index f75343f..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-<?php
-/**
- * Abstract class to handle different kinds of Data formats and to
- * help data exchange between Horde applications and external sources.
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Data
- */
-class Horde_Data extends PEAR {
-
-// Import constants
-/** Import already mapped csv data.        */ const IMPORT_MAPPED = 1;
-/** Map date and time entries of csv data. */ const IMPORT_DATETIME =  2;
-/** Import generic CSV data.               */ const IMPORT_CSV = 3;
-/** Import MS Outlook data.                */ const IMPORT_OUTLOOK = 4;
-/** Import vCalendar/iCalendar data.       */ const IMPORT_ICALENDAR = 5;
-/** Import vCards.                         */ const IMPORT_VCARD = 6;
-/** Import generic tsv data.               */ const IMPORT_TSV = 7;
-/** Import Mulberry address book data      */ const IMPORT_MULBERRY = 8;
-/** Import Pine address book data.         */ const IMPORT_PINE = 9;
-/** Import file.                           */ const IMPORT_FILE = 11;
-/** Import data.                           */ const IMPORT_DATA = 12;
-
-// Export constants
-/** Export generic CSV data. */ const EXPORT_CSV = 100;
-/** Export iCalendar data.   */ const EXPORT_ICALENDAR = 101;
-/** Export vCards.           */ const EXPORT_VCARD = 102;
-/** Export TSV data.         */ const EXPORT_TSV = 103;
-/** Export Outlook CSV data. */ const EXPORT_OUTLOOKCSV = 104;
-
-    /**
-     * File extension.
-     *
-     * @var string
-     */
-    var $_extension;
-
-    /**
-     * MIME content type.
-     *
-     * @var string
-     */
-    var $_contentType = 'text/plain';
-
-    /**
-     * A list of warnings raised during the last operation.
-     *
-     * @var array
-     */
-    var $_warnings = array();
-
-    /**
-     * Stub to import passed data.
-     */
-    function importData()
-    {
-    }
-
-    /**
-     * Stub to return exported data.
-     */
-    function exportData()
-    {
-    }
-
-    /**
-     * Stub to import a file.
-     */
-    function importFile($filename, $header = false)
-    {
-        $data = file_get_contents($filename);
-        return $this->importData($data, $header);
-    }
-
-    /**
-     * Stub to export data to a file.
-     */
-    function exportFile()
-    {
-    }
-
-    /**
-     * Tries to determine the expected newline character based on the
-     * platform information passed by the browser's agent header.
-     *
-     * @return string  The guessed expected newline characters, either \n, \r
-     *                 or \r\n.
-     */
-    function getNewline()
-    {
-        switch ($GLOBALS['browser']->getPlatform()) {
-        case 'win':
-            return "\r\n";
-
-        case 'mac':
-            return "\r";
-
-        case 'unix':
-        default:
-            return "\n";
-        }
-    }
-
-    /**
-     * Returns the full filename including the basename and extension.
-     *
-     * @param string $basename  Basename for the file.
-     *
-     * @return string  The file name.
-     */
-    function getFilename($basename)
-    {
-        return $basename . '.' . $this->_extension;
-    }
-
-    /**
-     * Returns the content type.
-     *
-     * @return string  The content type.
-     */
-    function getContentType()
-    {
-        return $this->_contentType;
-    }
-
-    /**
-     * Returns a list of warnings that have been raised during the last
-     * operation.
-     *
-     * @return array  A (possibly empty) list of warnings.
-     */
-    function warnings()
-    {
-        return $this->_warnings;
-    }
-
-    /**
-     * Attempts to return a concrete Horde_Data instance based on $format.
-     *
-     * @param mixed $format  The type of concrete Horde_Data subclass to
-     *                       return. If $format is an array, then we will look
-     *                       in $format[0]/lib/Data/ for the subclass
-     *                       implementation named $format[1].php.
-     *
-     * @return Horde_Data  The newly created concrete Horde_Data instance, or
-     *                     false on an error.
-     */
-    function &factory($format)
-    {
-        if (is_array($format)) {
-            $app = $format[0];
-            $format = $format[1];
-        }
-
-        $format = basename($format);
-
-        if (empty($format) || (strcmp($format, 'none') == 0)) {
-            $data = new Horde_Data();
-            return $data;
-        }
-
-        if (!empty($app)) {
-            require_once $GLOBALS['registry']->get('fileroot', $app) . '/lib/Data/' . $format . '.php';
-        } else {
-            require_once 'Horde/Data/' . $format . '.php';
-        }
-        $class = 'Horde_Data_' . $format;
-        if (class_exists($class)) {
-            $data = new $class();
-        } else {
-            $data = PEAR::raiseError('Class definition of ' . $class . ' not found.');
-        }
-
-        return $data;
-    }
-
-    /**
-     * Attempts to return a reference to a concrete Horde_Data instance
-     * based on $format. It will only create a new instance if no Horde_Data
-     * instance with the same parameters currently exists.
-     *
-     * This should be used if multiple data sources (and, thus, multiple
-     * Horde_Data instances) are required.
-     *
-     * This method must be invoked as: $var = &Horde_Data::singleton()
-     *
-     * @param string $format  The type of concrete Horde_Data subclass to
-     *                        return.
-     *
-     * @return Horde_Data  The concrete Horde_Data reference, or false on an
-     *                     error.
-     */
-    function &singleton($format)
-    {
-        static $instances = array();
-
-        $signature = serialize($format);
-        if (!isset($instances[$signature])) {
-            $instances[$signature] = &Horde_Data::factory($format);
-        }
-
-        return $instances[$signature];
-    }
-
-    /**
-     * Maps a date/time string to an associative array.
-     *
-     * The method signature has changed in Horde 3.1.3.
-     *
-     * @access private
-     *
-     * @param string $date   The date.
-     * @param string $type   One of 'date', 'time' or 'datetime'.
-     * @param array $params  Two-dimensional array with additional information
-     *                       about the formatting. Possible keys are:
-     *                       - delimiter - The character that seperates the
-     *                         different date/time parts.
-     *                       - format - If 'ampm' and $date contains a time we
-     *                         assume that it is in AM/PM format.
-     *                       - order - If $type is 'datetime' the order of the
-     *                         day and time parts: -1 (timestamp), 0
-     *                         (day/time), 1 (time/day).
-     * @param integer $key   The key to use for $params.
-     *
-     * @return string  The date or time in ISO format.
-     */
-    function mapDate($date, $type, $params, $key)
-    {
-        switch ($type) {
-        case 'date':
-        case 'monthday':
-        case 'monthdayyear':
-            $dates = explode($params['delimiter'][$key], $date);
-            if (count($dates) != 3) {
-                return $date;
-            }
-            $index = array_flip(explode('/', $params['format'][$key]));
-            return $dates[$index['year']] . '-' . $dates[$index['month']] . '-' . $dates[$index['mday']];
-
-        case 'time':
-            $dates = explode($params['delimiter'][$key], $date);
-            if (count($dates) < 2 || count($dates) > 3) {
-                return $date;
-            }
-            if ($params['format'][$key] == 'ampm') {
-                if (strpos(strtolower($dates[count($dates)-1]), 'pm') !== false) {
-                    if ($dates[0] !== '12') {
-                        $dates[0] += 12;
-                    }
-                } elseif ($dates[0] == '12') {
-                    $dates[0] = '0';
-                }
-                $dates[count($dates) - 1] = sprintf('%02d', $dates[count($dates)-1]);
-            }
-            return $dates[0] . ':' . $dates[1] . (count($dates) == 3 ? (':' . $dates[2]) : ':00');
-
-        case 'datetime':
-            switch ($params['order'][$key]) {
-            case -1:
-                return (string)(int)$date == $date
-                    ? date('Y-m-d H:i:s', $date)
-                    : $date;
-            case 0:
-                list($day, $time) = explode(' ', $date, 2);
-                break;
-            case 1:
-               list($time, $day) = explode(' ', $date, 2);
-               break;
-            }
-            $date = $this->mapDate($day, 'date',
-                                   array('delimiter' => $params['day_delimiter'],
-                                         'format' => $params['day_format']),
-                                   $key);
-            $time = $this->mapDate($time, 'time',
-                                   array('delimiter' => $params['time_delimiter'],
-                                         'format' => $params['time_format']),
-                                   $key);
-            return $date . ' ' . $time;
-
-        }
-    }
-
-    /**
-     * Takes all necessary actions for the given import step, parameters and
-     * form values and returns the next necessary step.
-     *
-     * @param integer $action  The current step. One of the IMPORT_* constants.
-     * @param array $param     An associative array containing needed
-     *                         parameters for the current step.
-     *
-     * @return mixed  Either the next step as an integer constant or imported
-     *                data set after the final step.
-     */
-    function nextStep($action, $param = array())
-    {
-        /* First step. */
-        if (is_null($action)) {
-            $_SESSION['import_data'] = array();
-            return self::IMPORT_FILE;
-        }
-
-        switch ($action) {
-        case self::IMPORT_FILE:
-            /* Sanitize uploaded file. */
-            $import_format = Horde_Util::getFormData('import_format');
-            try {
-                $GLOBALS['browser']->wasFileUploaded('import_file', $param['file_types'][$import_format]);
-            } catch (Horde_Exception $e) {
-                PEAR::raiseError($e->getMessage());
-            }
-            if ($_FILES['import_file']['size'] <= 0) {
-                return PEAR::raiseError(_("The file contained no data."));
-            }
-            $_SESSION['import_data']['format'] = $import_format;
-            break;
-
-        case self::IMPORT_MAPPED:
-            $dataKeys = Horde_Util::getFormData('dataKeys', '');
-            $appKeys = Horde_Util::getFormData('appKeys', '');
-            if (empty($dataKeys) || empty($appKeys)) {
-                global $registry;
-                return PEAR::raiseError(sprintf(_("You didn't map any fields from the imported file to the corresponding fields in %s."),
-                                                $registry->get('name')));
-            }
-            $dataKeys = explode("\t", $dataKeys);
-            $appKeys = explode("\t", $appKeys);
-            $map = array();
-            $dates = array();
-            foreach ($appKeys as $key => $app) {
-                $map[$dataKeys[$key]] = $app;
-                if (isset($param['time_fields']) &&
-                    isset($param['time_fields'][$app])) {
-                    $dates[$dataKeys[$key]]['type'] = $param['time_fields'][$app];
-                    $dates[$dataKeys[$key]]['values'] = array();
-                    $i = 0;
-                    /* Build an example array of up to 10 date/time fields. */
-                    while ($i < count($_SESSION['import_data']['data']) && count($dates[$dataKeys[$key]]['values']) < 10) {
-                        if (!empty($_SESSION['import_data']['data'][$i][$dataKeys[$key]])) {
-                            $dates[$dataKeys[$key]]['values'][] = $_SESSION['import_data']['data'][$i][$dataKeys[$key]];
-                        }
-                        $i++;
-                    }
-                }
-            }
-            $_SESSION['import_data']['map'] = $map;
-            if (count($dates) > 0) {
-                foreach ($dates as $key => $data) {
-                    if (count($data['values'])) {
-                        $_SESSION['import_data']['dates'] = $dates;
-                        return self::IMPORT_DATETIME;
-                    }
-                }
-            }
-            return $this->nextStep(self::IMPORT_DATA, $param);
-
-        case self::IMPORT_DATETIME:
-        case self::IMPORT_DATA:
-            if ($action == self::IMPORT_DATETIME) {
-                $params = array('delimiter' => Horde_Util::getFormData('delimiter'),
-                                'format' => Horde_Util::getFormData('format'),
-                                'order' => Horde_Util::getFormData('order'),
-                                'day_delimiter' => Horde_Util::getFormData('day_delimiter'),
-                                'day_format' => Horde_Util::getFormData('day_format'),
-                                'time_delimiter' => Horde_Util::getFormData('time_delimiter'),
-                                'time_format' => Horde_Util::getFormData('time_format'));
-            }
-            if (!isset($_SESSION['import_data']['data'])) {
-                return PEAR::raiseError(_("The uploaded data was lost since the previous step."));
-            }
-            /* Build the result data set as an associative array. */
-            $data = array();
-            foreach ($_SESSION['import_data']['data'] as $row) {
-                $data_row = array();
-                foreach ($row as $key => $val) {
-                    if (isset($_SESSION['import_data']['map'][$key])) {
-                        $mapped_key = $_SESSION['import_data']['map'][$key];
-                        if ($action == self::IMPORT_DATETIME &&
-                            !empty($val) &&
-                            isset($param['time_fields']) &&
-                            isset($param['time_fields'][$mapped_key])) {
-                            $val = $this->mapDate($val, $param['time_fields'][$mapped_key], $params, $key);
-                        }
-                        $data_row[$_SESSION['import_data']['map'][$key]] = $val;
-                    }
-                }
-                $data[] = $data_row;
-            }
-            return $data;
-        }
-    }
-
-    /**
-     * Cleans the session data up and removes any uploaded and moved
-     * files. If a function called "_cleanup()" exists, this gets
-     * called too.
-     *
-     * @return mixed  If _cleanup() was called, the return value of this call.
-     *                This should be the value of the first import step.
-     */
-    function cleanup()
-    {
-        if (isset($_SESSION['import_data']['file_name'])) {
-            @unlink($_SESSION['import_data']['file_name']);
-        }
-        $_SESSION['import_data'] = array();
-        if (function_exists('_cleanup')) {
-            return _cleanup();
-        }
-    }
-
-}
diff --git a/framework/Data/Data/csv.php b/framework/Data/Data/csv.php
deleted file mode 100644 (file)
index a1724f7..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-<?php
-/**
- * @package Horde_Data
- */
-
-/**
- * Horde_Data implementation for comma-separated data (CSV).
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_csv extends Horde_Data {
-
-    var $_extension = 'csv';
-    var $_contentType = 'text/comma-separated-values';
-
-    /**
-     * Tries to discover the CSV file's parameters.
-     *
-     * @param string $filename  The name of the file to investigate.
-     *
-     * @return array  An associative array with the following possible keys:
-     * <pre>
-     * 'sep':    The field separator
-     * 'quote':  The quoting character
-     * 'fields': The number of fields (columns)
-     * </pre>
-     */
-    function discoverFormat($filename)
-    {
-        return Horde_File_Csv::discoverFormat($filename);
-    }
-
-    /**
-     * Imports and parses a CSV file.
-     *
-     * @param string $filename  The name of the file to parse.
-     * @param boolean $header   Does the first line contain the field/column
-     *                          names?
-     * @param string $sep       The field/column separator.
-     * @param string $quote     The quoting character.
-     * @param integer $fields   The number or fields/columns.
-     * @param string $charset   The file's charset. @since Horde 3.1.
-     * @param string $crlf      The file's linefeed characters. @since Horde 3.1.
-     *
-     * @return array  A two-dimensional array of all imported data rows.  If
-     *                $header was true the rows are associative arrays with the
-     *                field/column names as the keys.
-     *@throws Horde_File_Csv_Exception
-     */
-    function importFile($filename, $header = false, $sep = '', $quote = '',
-                        $fields = null, $import_mapping = array(),
-                        $charset = null, $crlf = null)
-    {
-        /* Horde_File_Csv is a bit picky at what parameters it expects. */
-        $conf = array();
-        if ($fields) {
-            $conf['fields'] = $fields;
-        } else {
-            return array();
-        }
-        if (!empty($quote)) {
-            $conf['quote'] = $quote;
-        }
-        if (empty($sep)) {
-            $conf['sep'] = ',';
-        } else {
-            $conf['sep'] = $sep;
-        }
-        if (!empty($crlf)) {
-            $conf['crlf'] = $crlf;
-        }
-
-        /* Strip and keep the first line if it contains the field
-         * names. */
-        if ($header) {
-            $head = Horde_File_Csv::read($filename, $conf);
-            if (!empty($charset)) {
-                $head = Horde_String::convertCharset($head, $charset, Horde_Nls::getCharset());
-            }
-        }
-
-        $data = array();
-        while ($line = Horde_File_Csv::read($filename, $conf)) {
-            if (!empty($charset)) {
-                $line = Horde_String::convertCharset($line, $charset, Horde_Nls::getCharset());
-            }
-            if (!isset($head)) {
-                $data[] = $line;
-            } else {
-                $newline = array();
-                for ($i = 0; $i < count($head); $i++) {
-                    if (isset($import_mapping[$head[$i]])) {
-                        $head[$i] = $import_mapping[$head[$i]];
-                    }
-                    $cell = $line[$i];
-                    $cell = preg_replace("/\"\"/", "\"", $cell);
-                    $newline[$head[$i]] = empty($cell) ? '' : $cell;
-                }
-                $data[] = $newline;
-            }
-        }
-
-        $fp = Horde_File_Csv::getPointer($filename, $conf);
-        if ($fp) {
-            rewind($fp);
-        }
-
-        $this->_warnings = Horde_File_Csv::warning();
-        return $data;
-    }
-
-    /**
-     * Builds a CSV file from a given data structure and returns it as a
-     * string.
-     *
-     * @param array $data      A two-dimensional array containing the data set.
-     * @param boolean $header  If true, the rows of $data are associative
-     *                         arrays with field names as their keys.
-     *
-     * @return string  The CSV data.
-     */
-    function exportData($data, $header = false, $export_mapping = array())
-    {
-        if (!is_array($data) || count($data) == 0) {
-            return '';
-        }
-
-        $export = '';
-        $eol = "\n";
-        $head = array_keys(current($data));
-        if ($header) {
-            foreach ($head as $key) {
-                if (!empty($key)) {
-                    if (isset($export_mapping[$key])) {
-                        $key = $export_mapping[$key];
-                    }
-                    $export .= '"' . $key . '"';
-                }
-                $export .= ',';
-            }
-            $export = substr($export, 0, -1) . $eol;
-        }
-
-        foreach ($data as $row) {
-            foreach ($head as $key) {
-                $cell = $row[$key];
-                if (!empty($cell) || $cell === 0) {
-                    $export .= '"' . $cell . '"';
-                }
-                $export .= ',';
-            }
-            $export = substr($export, 0, -1) . $eol;
-        }
-
-        return $export;
-    }
-
-    /**
-     * Builds a CSV file from a given data structure and triggers its
-     * download.  It DOES NOT exit the current script but only outputs the
-     * correct headers and data.
-     *
-     * @param string $filename  The name of the file to be downloaded.
-     * @param array $data       A two-dimensional array containing the data
-     *                          set.
-     * @param boolean $header   If true, the rows of $data are associative
-     *                          arrays with field names as their keys.
-     */
-    function exportFile($filename, $data, $header = false,
-                        $export_mapping = array())
-    {
-        $export = $this->exportData($data, $header, $export_mapping);
-        $GLOBALS['browser']->downloadHeaders($filename, 'application/csv', false, strlen($export));
-        echo $export;
-    }
-
-    /**
-     * Takes all necessary actions for the given import step, parameters and
-     * form values and returns the next necessary step.
-     *
-     * @param integer $action  The current step. One of the IMPORT_* constants.
-     * @param array $param     An associative array containing needed
-     *                         parameters for the current step.
-     *
-     * @return mixed  Either the next step as an integer constant or imported
-     *                data set after the final step.
-     */
-    function nextStep($action, $param = array())
-    {
-        switch ($action) {
-        case self::IMPORT_FILE:
-            $next_step = parent::nextStep($action, $param);
-            if (is_a($next_step, 'PEAR_Error')) {
-                return $next_step;
-            }
-
-            /* Move uploaded file so that we can read it again in the next
-               step after the user gave some format details. */
-            $file_name = Horde::getTempFile('import', false);
-            if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) {
-                return PEAR::raiseError(_("The uploaded file could not be saved."));
-            }
-            $_SESSION['import_data']['file_name'] = $file_name;
-
-            /* Try to discover the file format ourselves. */
-            $conf = $this->discoverFormat($file_name);
-            if (!$conf) {
-                $conf = array('sep' => ',');
-            }
-            $_SESSION['import_data'] = array_merge($_SESSION['import_data'], $conf);
-
-            /* Check if charset was specified. */
-            $_SESSION['import_data']['charset'] = Horde_Util::getFormData('charset');
-
-            /* Read the file's first two lines to show them to the user. */
-            $_SESSION['import_data']['first_lines'] = '';
-            $fp = @fopen($file_name, 'r');
-            if ($fp) {
-                $line_no = 1;
-                while ($line_no < 3 && $line = fgets($fp)) {
-                    if (!empty($_SESSION['import_data']['charset'])) {
-                        $line = Horde_String::convertCharset($line, $_SESSION['import_data']['charset'], Horde_Nls::getCharset());
-                    }
-                    $newline = Horde_String::length($line) > 100 ? "\n" : '';
-                    $_SESSION['import_data']['first_lines'] .= substr($line, 0, 100) . $newline;
-                    $line_no++;
-                }
-            }
-            return self::IMPORT_CSV;
-
-        case self::IMPORT_CSV:
-            $_SESSION['import_data']['header'] = Horde_Util::getFormData('header');
-            $import_mapping = array();
-            if (isset($param['import_mapping'])) {
-                $import_mapping = $param['import_mapping'];
-            }
-            $import_data = $this->importFile($_SESSION['import_data']['file_name'],
-                                             $_SESSION['import_data']['header'],
-                                             Horde_Util::getFormData('sep'),
-                                             Horde_Util::getFormData('quote'),
-                                             Horde_Util::getFormData('fields'),
-                                             $import_mapping,
-                                             $_SESSION['import_data']['charset'],
-                                             $_SESSION['import_data']['crlf']);
-            $_SESSION['import_data']['data'] = $import_data;
-            unset($_SESSION['import_data']['map']);
-            return self::IMPORT_MAPPED;
-
-        default:
-            return parent::nextStep($action, $param);
-        }
-    }
-
-}
diff --git a/framework/Data/Data/icalendar.php b/framework/Data/Data/icalendar.php
deleted file mode 100644 (file)
index c130228..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-/** We rely on the Horde_Data_imc:: abstract class. */
-require_once dirname(__FILE__) . '/imc.php';
-
-/**
- * This is iCalendar (vCalendar).
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @author  Karsten Fourmont <fourmont@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_icalendar extends Horde_Data_imc {
-
-}
diff --git a/framework/Data/Data/imc.php b/framework/Data/Data/imc.php
deleted file mode 100644 (file)
index f25dcea..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/**
- * Abstract implementation of the Horde_Data:: API for IMC data -
- * vCards and iCalendar data, etc. Provides a number of utility
- * methods that vCard and iCalendar implementation can share and rely
- * on.
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_imc extends Horde_Data {
-
-    var $_iCal = false;
-
-    function importData($text)
-    {
-        $this->_iCal = new Horde_iCalendar();
-        if (!$this->_iCal->parsevCalendar($text)) {
-            return PEAR::raiseError(_("There was an error importing the iCalendar data."));
-        }
-
-        return $this->_iCal->getComponents();
-    }
-
-    /**
-     * Builds an iCalendar file from a given data structure and
-     * returns it as a string.
-     *
-     * @param array $data     An array containing Horde_iCalendar_vevent
-     *                        objects
-     * @param string $method  The iTip method to use.
-     *
-     * @return string  The iCalendar data.
-     */
-    function exportData($data, $method = 'REQUEST')
-    {
-        $this->_iCal = new Horde_iCalendar();
-        $this->_iCal->setAttribute('METHOD', $method);
-
-        foreach ($data as $event) {
-            $this->_iCal->addComponent($event);
-        }
-
-        return $this->_iCal->exportvCalendar();
-    }
-
-    /**
-     * Builds an iCalendar file from a given data structure and
-     * triggers its download.  It DOES NOT exit the current script but
-     * only outputs the correct headers and data.
-     *
-     * @param string $filename   The name of the file to be downloaded.
-     * @param array $data        An array containing Horde_iCalendar_vevents
-     */
-    function exportFile($filename, $data)
-    {
-        $export = $this->exportData($data);
-        $GLOBALS['browser']->downloadHeaders($filename, 'text/calendar', false, strlen($export));
-        echo $export;
-    }
-
-    /**
-     * Takes all necessary actions for the given import step,
-     * parameters and form values and returns the next necessary step.
-     *
-     * @param integer $action  The current step. One of the IMPORT_* constants.
-     * @param array $param     An associative array containing needed
-     *                         parameters for the current step.
-     * @return mixed  Either the next step as an integer constant or imported
-     *                data set after the final step.
-     */
-    function nextStep($action, $param = array())
-    {
-        switch ($action) {
-        case self::IMPORT_FILE:
-            $next_step = parent::nextStep($action, $param);
-            if (is_a($next_step, 'PEAR_Error')) {
-                return $next_step;
-            }
-
-            $import_data = $this->importFile($_FILES['import_file']['tmp_name']);
-            if (is_a($import_data, 'PEAR_Error')) {
-                return $import_data;
-            }
-
-            return $this->_iCal->getComponents();
-            break;
-
-        default:
-            return parent::nextStep($action, $param);
-            break;
-        }
-    }
-
-}
diff --git a/framework/Data/Data/outlookcsv.php b/framework/Data/Data/outlookcsv.php
deleted file mode 100644 (file)
index 627bda2..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-require_once 'Horde/Data/csv.php';
-
-/**
- * Horde_Data implementation for Outlook comma-separated data (CSV).
- *
- * @package Horde_Data
- */
-class Horde_Data_outlookcsv extends Horde_Data_csv {
-
-    /**
-     * Builds a CSV file from a given data structure and returns it as a
-     * string.
-     *
-     * @param array   $data       A two-dimensional array containing the data
-     *                            set.
-     * @param boolean $header     If true, the rows of $data are associative
-     *                            arrays with field names as their keys.
-     *
-     * @return string  The CSV data.
-     */
-    function exportData($data, $header = false, $export_mapping = array())
-    {
-        if (!is_array($data) || count($data) == 0) {
-            return '';
-        }
-
-        $export = '';
-        $eol = "\r\n";
-        $head = array_keys(current($data));
-        if ($header) {
-            foreach ($head as $key) {
-                if (!empty($key)) {
-                    if (isset($export_mapping[$key])) {
-                        $key = $export_mapping[$key];
-                    }
-                    $export .= '"' . $key . '"';
-                }
-                $export .= ',';
-            }
-            $export = substr($export, 0, -1) . $eol;
-        }
-
-        foreach ($data as $row) {
-            foreach ($head as $key) {
-                $cell = $row[$key];
-                if (!empty($cell) || $cell === 0) {
-                    $cell = preg_replace("/\"/", "\"\"", $cell);
-                    $export .= '"' . $cell . '"';
-                }
-                $export .= ',';
-            }
-            $export = substr($export, 0, -1) . $eol;
-        }
-
-        return $export;
-    }
-
-}
diff --git a/framework/Data/Data/tsv.php b/framework/Data/Data/tsv.php
deleted file mode 100644 (file)
index 3b79404..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-<?php
-/**
- * Horde_Data implementation for tab-separated data (TSV).
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_tsv extends Horde_Data {
-
-    var $_extension = 'tsv';
-    var $_contentType = 'text/tab-separated-values';
-
-    /**
-     * Convert data file contents to list of data records.
-     *
-     * @param string $contents   Data file contents.
-     * @param boolean $header    True if a header row is present.
-     * @param string $delimiter  Field delimiter.
-     *
-     * @return array  List of data records.
-     */
-    function importData($contents, $header = false, $delimiter = "\t")
-    {
-        if ($_SESSION['import_data']['format'] == 'pine') {
-            $contents = preg_replace('/\n +/', '', $contents);
-        }
-        $contents = explode("\n", $contents);
-        $data = array();
-        if ($header) {
-            $head = explode($delimiter, array_shift($contents));
-        }
-        foreach ($contents as $line) {
-            if (trim($line) == '') {
-                continue;
-            }
-            $line = explode($delimiter, $line);
-            if (!isset($head)) {
-                $data[] = $line;
-            } else {
-                $newline = array();
-                for ($i = 0; $i < count($head); $i++) {
-                    $newline[$head[$i]] = empty($line[$i]) ? '' : $line[$i];
-                }
-                $data[] = $newline;
-            }
-        }
-        return $data;
-    }
-
-    /**
-     * Builds a TSV file from a given data structure and returns it as a
-     * string.
-     *
-     * @param array $data      A two-dimensional array containing the data set.
-     * @param boolean $header  If true, the rows of $data are associative
-     *                         arrays with field names as their keys.
-     *
-     * @return string  The TSV data.
-     */
-    function exportData($data, $header = false)
-    {
-        if (!is_array($data) || count($data) == 0) {
-            return '';
-        }
-        $export = '';
-        $head = array_keys(current($data));
-        if ($header) {
-            $export = implode("\t", $head) . "\n";
-        }
-        foreach ($data as $row) {
-            foreach ($head as $key) {
-                $cell = $row[$key];
-                if (!empty($cell) || $cell === 0) {
-                    $export .= $cell;
-                }
-                $export .= "\t";
-            }
-            $export = substr($export, 0, -1) . "\n";
-        }
-        return $export;
-    }
-
-    /**
-     * Builds a TSV file from a given data structure and triggers its download.
-     * It DOES NOT exit the current script but only outputs the correct headers
-     * and data.
-     *
-     * @param string $filename  The name of the file to be downloaded.
-     * @param array $data       A two-dimensional array containing the data
-     *                          set.
-     * @param boolean $header   If true, the rows of $data are associative
-     *                          arrays with field names as their keys.
-     */
-    function exportFile($filename, $data, $header = false)
-    {
-        $export = $this->exportData($data, $header);
-        $GLOBALS['browser']->downloadHeaders($filename, 'text/tab-separated-values', false, strlen($export));
-        echo $export;
-    }
-
-    /**
-     * Takes all necessary actions for the given import step, parameters and
-     * form values and returns the next necessary step.
-     *
-     * @param integer $action  The current step. One of the IMPORT_* constants.
-     * @param array $param     An associative array containing needed
-     *                         parameters for the current step.
-     *
-     * @return mixed  Either the next step as an integer constant or imported
-     *                data set after the final step.
-     */
-    function nextStep($action, $param = array())
-    {
-        switch ($action) {
-        case self::IMPORT_FILE:
-            $next_step = parent::nextStep($action, $param);
-            if (is_a($next_step, 'PEAR_Error')) {
-                return $next_step;
-            }
-
-            if ($_SESSION['import_data']['format'] == 'mulberry' ||
-                $_SESSION['import_data']['format'] == 'pine') {
-                $_SESSION['import_data']['data'] = $this->importFile($_FILES['import_file']['tmp_name']);
-                $format = $_SESSION['import_data']['format'];
-                if ($format == 'mulberry') {
-                    $appKeys  = array('alias', 'name', 'email', 'company', 'workAddress', 'workPhone', 'homePhone', 'fax', 'notes');
-                    $dataKeys = array(0, 1, 2, 3, 4, 5, 6, 7, 9);
-                } elseif ($format == 'pine') {
-                    $appKeys = array('alias', 'name', 'email', 'notes');
-                    $dataKeys = array(0, 1, 2, 4);
-                }
-                foreach ($appKeys as $key => $app) {
-                    $map[$dataKeys[$key]] = $app;
-                }
-                $data = array();
-                foreach ($_SESSION['import_data']['data'] as $row) {
-                    $hash = array();
-                    if ($format == 'mulberry') {
-                        if (preg_match("/^Grp:/", $row[0]) || empty($row[1])) {
-                            continue;
-                        }
-                        $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
-                        foreach ($dataKeys as $key) {
-                            if (array_key_exists($key, $row)) {
-                                $hash[$key] = stripslashes(preg_replace('/\\\\r/', "\n", $row[$key]));
-                            }
-                        }
-                    } elseif ($format == 'pine') {
-                        if (count($row) < 3 || preg_match("/^#DELETED/", $row[0]) || preg_match("/[()]/", $row[2])) {
-                            continue;
-                        }
-                        $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
-                        /* Address can be a full RFC822 address */
-                        try {
-                            $addr_arr = Horde_Mime_Address::parseAddressList($row[2]);
-                        } catch (Horde_Mime_Exception $e) {
-                            continue;
-                        }
-                        if (empty($addr_arr[0]->mailbox)) {
-                            continue;
-                        }
-                        $row[2] = $addr_arr[0]->mailbox . '@' . $addr_arr[0]->host;
-                        if (empty($row[1]) && !empty($addr_arr[0]->personal)) {
-                            $row[1] = $addr_arr[0]->personal;
-                        }
-                        foreach ($dataKeys as $key) {
-                            if (array_key_exists($key, $row)) {
-                                $hash[$key] = $row[$key];
-                            }
-                        }
-                    }
-                    $data[] = $hash;
-                }
-                $_SESSION['import_data']['data'] = $data;
-                $_SESSION['import_data']['map'] = $map;
-                $ret = $this->nextStep(self::IMPORT_DATA, $param);
-                return $ret;
-            }
-
-            /* Move uploaded file so that we can read it again in the next step
-               after the user gave some format details. */
-            try {
-                $GLOBALS['browser']->wasFileUploaded('import_file', _("TSV file"));
-            } catch (Horde_Browser_Exception $e) {
-                return PEAR::raiseError($e->getMessage());
-            }
-            $file_name = Horde::getTempFile('import', false);
-            if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) {
-                return PEAR::raiseError(_("The uploaded file could not be saved."));
-            }
-            $_SESSION['import_data']['file_name'] = $file_name;
-
-            /* Read the file's first two lines to show them to the user. */
-            $_SESSION['import_data']['first_lines'] = '';
-            $fp = @fopen($file_name, 'r');
-            if ($fp) {
-                $line_no = 1;
-                while ($line_no < 3 && $line = fgets($fp)) {
-                    $newline = Horde_String::length($line) > 100 ? "\n" : '';
-                    $_SESSION['import_data']['first_lines'] .= substr($line, 0, 100) . $newline;
-                    $line_no++;
-                }
-            }
-            return self::IMPORT_TSV;
-            break;
-
-        case self::IMPORT_TSV:
-            $_SESSION['import_data']['header'] = Horde_Util::getFormData('header');
-            $import_data = $this->importFile($_SESSION['import_data']['file_name'],
-                                             $_SESSION['import_data']['header']);
-            $_SESSION['import_data']['data'] = $import_data;
-            unset($_SESSION['import_data']['map']);
-            return self::IMPORT_MAPPED;
-            break;
-
-        default:
-            return parent::nextStep($action, $param);
-            break;
-        }
-    }
-
-}
diff --git a/framework/Data/Data/vcard.php b/framework/Data/Data/vcard.php
deleted file mode 100644 (file)
index 9807a1e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * Implement the Horde_Data:: API for vCard data.
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_vcard extends Horde_Data_imc {
-
-    /**
-     * Exports vcalendar data as a string. Unlike vEvent, vCard data
-     * is not enclosed in BEGIN|END:vCalendar.
-     *
-     * @param array $data     An array containing Horde_iCalendar_vcard
-     *                        objects.
-     * @param string $method  The iTip method to use.
-     *
-     * @return string  The iCalendar data.
-     */
-    function exportData($data, $method = 'REQUEST')
-    {
-        $s = '';
-        foreach ($data as $vcard) {
-            $s.= $vcard->exportvCalendar();
-        }
-        return $s;
-    }
-
-}
diff --git a/framework/Data/Data/vnote.php b/framework/Data/Data/vnote.php
deleted file mode 100644 (file)
index 1e03c9b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Implement the Horde_Data:: API for vNote data.
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_vnote extends Horde_Data_imc {
-
-    /**
-     * Exports vcalendar data as a string. Unlike vEvent, vNote data
-     * is not enclosed in BEGIN|END:vCalendar.
-     *
-     * @param array $data     An array containing Horde_iCalendar_vnote
-     *                        objects.
-     * @param string $method  The iTip method to use.
-     *
-     * @return string  The iCalendar data.
-     */
-    function exportData($data, $method = 'REQUEST')
-    {
-        global $prefs;
-
-        $this->_iCal = new Horde_iCalendar();
-
-        $this->_iCal->setAttribute('METHOD', $method);
-        $s = '';
-        foreach ($data as $event) {
-            $s.= $event->exportvCalendar();
-        }
-        return $s;
-    }
-
-}
diff --git a/framework/Data/Data/vtodo.php b/framework/Data/Data/vtodo.php
deleted file mode 100644 (file)
index 683ff17..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-/**
- * Implement the Horde_Data:: API for vTodo data.
- *
- * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author  Jan Schneider <jan@horde.org>
- * @author  Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_Data
- */
-class Horde_Data_vtodo extends Horde_Data_imc {
-
-}
diff --git a/framework/Data/lib/Horde/Data.php b/framework/Data/lib/Horde/Data.php
new file mode 100644 (file)
index 0000000..313b14d
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Abstract class to handle different kinds of Data formats and to
+ * help data exchange between Horde applications and external sources.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data
+{
+    /* Import already mapped csv data. */
+    const IMPORT_MAPPED = 1;
+    /* Map date and time entries of csv data. */
+    const IMPORT_DATETIME =  2;
+    /* Import generic CSV data. */
+    const IMPORT_CSV = 3;
+    /* Import MS Outlook data. */
+    const IMPORT_OUTLOOK = 4;
+    /* Import vCalendar/iCalendar data. */
+    const IMPORT_ICALENDAR = 5;
+    /* Import vCards. */
+    const IMPORT_VCARD = 6;
+    /* Import generic tsv data. */
+    const IMPORT_TSV = 7;
+    /* Import Mulberry address book data. */
+    const IMPORT_MULBERRY = 8;
+    /* Import Pine address book data. */
+    const IMPORT_PINE = 9;
+    /* Import file. */
+    const IMPORT_FILE = 11;
+    /* Import data. */
+    const IMPORT_DATA = 12;
+
+    /* Export generic CSV data. */
+    const EXPORT_CSV = 100;
+    /* Export iCalendar data. */
+    const EXPORT_ICALENDAR = 101;
+    /* Export vCards. */
+    const EXPORT_VCARD = 102;
+    /* Export TSV data. */
+    const EXPORT_TSV = 103;
+    /* Export Outlook CSV data. */
+    const EXPORT_OUTLOOKCSV = 104;
+
+    /**
+     * Attempts to return a concrete instance based on $format.
+     *
+     * @param string $format  The type of concrete subclass to return.
+     * @param array $params   Parameters to pass to the format driver.
+     *
+     * @return Horde_Data_Driver  The newly created concrete instance.
+     * @throws Horde_Data_Exception
+     */
+    public function factory($format, array $params = array())
+    {
+        $format = ucfirst(strtolower(basename($format)));
+        $class = __CLASS__ . '_' . $format;
+
+        if (class_exists($class)) {
+            return new $class($params);
+        }
+
+        throw new Horde_Data_Exception('Driver not found: ' . $driver);
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Csv.php b/framework/Data/lib/Horde/Data/Csv.php
new file mode 100644 (file)
index 0000000..cec3c5c
--- /dev/null
@@ -0,0 +1,269 @@
+<?php
+/**
+ * @category Horde
+ * @package  Data
+ */
+
+/**
+ * Horde_Data implementation for comma-separated data (CSV).
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Csv extends Horde_Data_Driver
+{
+    /**
+     * File extension.
+     *
+     * @var string
+     */
+    protected $_extension = 'csv';
+
+    /**
+     * MIME content type.
+     *
+     * @var string
+     */
+    protected $_contentType = 'text/comma-separated-values';
+
+    /**
+     * Tries to discover the CSV file's parameters.
+     *
+     * @param string $filename  The name of the file to investigate.
+     *
+     * @return array  An associative array with the following possible keys:
+     * <pre>
+     * 'sep':    The field separator
+     * 'quote':  The quoting character
+     * 'fields': The number of fields (columns)
+     * </pre>
+     */
+    public function discoverFormat($filename)
+    {
+        return Horde_File_Csv::discoverFormat($filename);
+    }
+
+    /**
+     * Imports and parses a CSV file.
+     *
+     * @param string $filename  The name of the file to parse.
+     * @param boolean $header   Does the first line contain the field/column
+     *                          names?
+     * @param string $sep       The field/column separator.
+     * @param string $quote     The quoting character.
+     * @param integer $fields   The number or fields/columns.
+     * @param string $charset   The file's charset.
+     * @param string $crlf      The file's linefeed characters.
+     *
+     * @return array  A two-dimensional array of all imported data rows.  If
+     *                $header was true the rows are associative arrays with the
+     *                field/column names as the keys.
+     *@throws Horde_File_Csv_Exception
+     */
+    public function importFile($filename, $header = false, $sep = ',',
+                               $quote = '', $fields = null,
+                               $import_mapping = array(), $charset = null,
+                               $crlf = null)
+    {
+        if (empty($fields)) {
+            return array();
+        }
+
+        $conf = array(
+            'crlf' => $crlf,
+            'fields' => $fields,
+            'quote' => $quote,
+            'sep' => $sep
+        );
+
+        /* Strip and keep the first line if it contains the field
+         * names. */
+        if ($header) {
+            $head = Horde_File_Csv::read($filename, $conf);
+            if (!empty($charset)) {
+                $head = Horde_String::convertCharset($head, $charset, Horde_Nls::getCharset());
+            }
+        }
+
+        $data = array();
+        while ($line = Horde_File_Csv::read($filename, $conf)) {
+            if (!empty($charset)) {
+                $line = Horde_String::convertCharset($line, $charset, Horde_Nls::getCharset());
+            }
+            if (!isset($head)) {
+                $data[] = $line;
+            } else {
+                $newline = array();
+                for ($i = 0; $i < count($head); $i++) {
+                    if (isset($import_mapping[$head[$i]])) {
+                        $head[$i] = $import_mapping[$head[$i]];
+                    }
+                    $cell = $line[$i];
+                    $cell = preg_replace("/\"\"/", "\"", $cell);
+                    $newline[$head[$i]] = empty($cell) ? '' : $cell;
+                }
+                $data[] = $newline;
+            }
+        }
+
+        $fp = Horde_File_Csv::getPointer($filename, $conf);
+        if ($fp) {
+            rewind($fp);
+        }
+
+        $this->_warnings = Horde_File_Csv::warning();
+
+        return $data;
+    }
+
+    /**
+     * Builds a CSV file from a given data structure and returns it as a
+     * string.
+     *
+     * @param array $data      A two-dimensional array containing the data set.
+     * @param boolean $header  If true, the rows of $data are associative
+     *                         arrays with field names as their keys.
+     *
+     * @return string  The CSV data.
+     */
+    public function exportData($data, $header = false,
+                               $export_mapping = array())
+    {
+        if (!is_array($data) || count($data) == 0) {
+            return '';
+        }
+
+        $export = '';
+        $eol = "\n";
+        $head = array_keys(current($data));
+        if ($header) {
+            foreach ($head as $key) {
+                if (!empty($key)) {
+                    if (isset($export_mapping[$key])) {
+                        $key = $export_mapping[$key];
+                    }
+                    $export .= '"' . $key . '"';
+                }
+                $export .= ',';
+            }
+            $export = substr($export, 0, -1) . $eol;
+        }
+
+        foreach ($data as $row) {
+            foreach ($head as $key) {
+                $cell = $row[$key];
+                if (!empty($cell) || $cell === 0) {
+                    $export .= '"' . $cell . '"';
+                }
+                $export .= ',';
+            }
+            $export = substr($export, 0, -1) . $eol;
+        }
+
+        return $export;
+    }
+
+    /**
+     * Builds a CSV file from a given data structure and triggers its
+     * download.  It DOES NOT exit the current script but only outputs the
+     * correct headers and data.
+     *
+     * @param string $filename  The name of the file to be downloaded.
+     * @param array $data       A two-dimensional array containing the data
+     *                          set.
+     * @param boolean $header   If true, the rows of $data are associative
+     *                          arrays with field names as their keys.
+     */
+    public function exportFile($filename, $data, $header = false,
+                               $export_mapping = array())
+    {
+        $export = $this->exportData($data, $header, $export_mapping);
+        $this->_browser->downloadHeaders($filename, 'application/csv', false, strlen($export));
+        echo $export;
+    }
+
+    /**
+     * Takes all necessary actions for the given import step, parameters and
+     * form values and returns the next necessary step.
+     *
+     * @param integer $action  The current step. One of the IMPORT_* constants.
+     * @param array $param     An associative array containing needed
+     *                         parameters for the current step.
+     *
+     * @return mixed  Either the next step as an integer constant or imported
+     *                data set after the final step.
+     * @throws Horde_Data_Exception
+     */
+    public function nextStep($action, $param = array())
+    {
+        switch ($action) {
+        case Horde_Data::IMPORT_FILE:
+            parent::nextStep($action, $param);
+
+            /* Move uploaded file so that we can read it again in the next
+               step after the user gave some format details. */
+            $file_name = Horde_Util::getTempFile('import', false);
+            if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) {
+                throw new Horde_Data_Exception('The uploaded file could not be saved.');
+            }
+            $_SESSION['import_data']['file_name'] = $file_name;
+
+            /* Try to discover the file format ourselves. */
+            $conf = $this->discoverFormat($file_name);
+            if (!$conf) {
+                $conf = array('sep' => ',');
+            }
+            $_SESSION['import_data'] = array_merge($_SESSION['import_data'], $conf);
+
+            /* Check if charset was specified. */
+            $_SESSION['import_data']['charset'] = $this->_vars->charset;
+
+            /* Read the file's first two lines to show them to the user. */
+            $_SESSION['import_data']['first_lines'] = '';
+            $fp = @fopen($file_name, 'r');
+            if ($fp) {
+                $line_no = 1;
+                while ($line_no < 3 && $line = fgets($fp)) {
+                    if (!empty($_SESSION['import_data']['charset'])) {
+                        $line = Horde_String::convertCharset($line, $_SESSION['import_data']['charset'], Horde_Nls::getCharset());
+                    }
+                    $newline = Horde_String::length($line) > 100 ? "\n" : '';
+                    $_SESSION['import_data']['first_lines'] .= substr($line, 0, 100) . $newline;
+                    $line_no++;
+                }
+            }
+            return Horde_Data::IMPORT_CSV;
+
+        case Horde_Data::IMPORT_CSV:
+            $_SESSION['import_data']['header'] = $this->_vars->header;
+            $import_mapping = array();
+            if (isset($param['import_mapping'])) {
+                $import_mapping = $param['import_mapping'];
+            }
+            $import_data = $this->importFile(
+                $_SESSION['import_data']['file_name'],
+                $_SESSION['import_data']['header'],
+                $this->_vars->sep,
+                $this->_vars->quote,
+                $this->_vars->fields,
+                $import_mapping,
+                $_SESSION['import_data']['charset'],
+                $_SESSION['import_data']['crlf']
+            );
+            $_SESSION['import_data']['data'] = $import_data;
+            unset($_SESSION['import_data']['map']);
+            return Horde_Data::IMPORT_MAPPED;
+
+        default:
+            return parent::nextStep($action, $param);
+        }
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Driver.php b/framework/Data/lib/Horde/Data/Driver.php
new file mode 100644 (file)
index 0000000..b4da049
--- /dev/null
@@ -0,0 +1,368 @@
+<?php
+/**
+ * Abstract class that Data drivers extend.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+abstract class Horde_Data
+{
+    /**
+     * Browser object.
+     *
+     * @var Horde_Browser
+     */
+    protected $_browser;
+
+    /**
+     * File extension.
+     *
+     * @var string
+     */
+    protected $_extension = '';
+
+    /**
+     * MIME content type.
+     *
+     * @var string
+     */
+    protected $_contentType = 'text/plain';
+
+    /**
+     * Cleanup callback function.
+     *
+     * @var callback
+     */
+    protected $_cleanupCallback;
+
+    /**
+     * Variables object.
+     *
+     * @var Horde_Variables
+     */
+    protected $_vars;
+
+    /**
+     * A list of warnings raised during the last operation.
+     *
+     * @var array
+     */
+    protected $_warnings = array();
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Optional parameters:
+     * <pre>
+     * 'browser' - (Horde_Browser) A Horde_Browser object.
+     * 'cleanup' - (callback) A callback to call at cleanup time.
+     * </pre>
+     *
+     * @throws Horde_Data_Exception
+     */
+    public function __construct(array $params = array())
+    {
+        if (!isset($params['browser'])) {
+            throw new Horde_Data_Exception('Missing browser parameter.');
+        }
+        $this->_browser = $params['browser'];
+
+        if (isset($params['cleanup']) &&
+            is_callable($params['cleanup'])) {
+            $this->_cleanupCallback = $params['cleanup'];
+        }
+
+        $this->_vars = isset($params['vars'])
+            ? $params['vars']
+            : Horde_Variables::getDefaultVariables();
+    }
+
+    /**
+     * Stub to import passed data.
+     */
+    abstract public function importData();
+
+    /**
+     * Stub to return exported data.
+     */
+    abstract public function exportData();
+
+    /**
+     * Stub to import a file.
+     */
+    public function importFile($filename, $header = false)
+    {
+        $data = file_get_contents($filename);
+        return $this->importData($data, $header);
+    }
+
+    /**
+     * Stub to export data to a file.
+     */
+    abstract public function exportFile();
+
+    /**
+     * Tries to determine the expected newline character based on the
+     * platform information passed by the browser's agent header.
+     *
+     * @return string  The guessed expected newline characters, either \n, \r
+     *                 or \r\n.
+     */
+    public function getNewline()
+    {
+        switch ($this->_browser->getPlatform()) {
+        case 'win':
+            return "\r\n";
+
+        case 'mac':
+            return "\r";
+
+        case 'unix':
+        default:
+            return "\n";
+        }
+    }
+
+    /**
+     * Returns the full filename including the basename and extension.
+     *
+     * @param string $basename  Basename for the file.
+     *
+     * @return string  The file name.
+     */
+    public function getFilename($basename)
+    {
+        return $basename . '.' . $this->_extension;
+    }
+
+    /**
+     * Returns the content type.
+     *
+     * @return string  The content type.
+     */
+    public function getContentType()
+    {
+        return $this->_contentType;
+    }
+
+    /**
+     * Returns a list of warnings that have been raised during the last
+     * operation.
+     *
+     * @return array  A (possibly empty) list of warnings.
+     */
+    public function warnings()
+    {
+        return $this->_warnings;
+    }
+
+    /**
+     * Maps a date/time string to an associative array.
+     *
+     * @param string $date   The date.
+     * @param string $type   One of 'date', 'time' or 'datetime'.
+     * @param array $params  Two-dimensional array with additional information
+     *                       about the formatting. Possible keys are:
+     *                       - delimiter - The character that seperates the
+     *                         different date/time parts.
+     *                       - format - If 'ampm' and $date contains a time we
+     *                         assume that it is in AM/PM format.
+     *                       - order - If $type is 'datetime' the order of the
+     *                         day and time parts: -1 (timestamp), 0
+     *                         (day/time), 1 (time/day).
+     * @param integer $key   The key to use for $params.
+     *
+     * @return string  The date or time in ISO format.
+     */
+    protected function _mapDate($date, $type, $params, $key)
+    {
+        switch ($type) {
+        case 'date':
+        case 'monthday':
+        case 'monthdayyear':
+            $dates = explode($params['delimiter'][$key], $date);
+            if (count($dates) != 3) {
+                return $date;
+            }
+            $index = array_flip(explode('/', $params['format'][$key]));
+            return $dates[$index['year']] . '-' . $dates[$index['month']] . '-' . $dates[$index['mday']];
+
+        case 'time':
+            $dates = explode($params['delimiter'][$key], $date);
+            if (count($dates) < 2 || count($dates) > 3) {
+                return $date;
+            }
+            if ($params['format'][$key] == 'ampm') {
+                if (strpos(strtolower($dates[count($dates)-1]), 'pm') !== false) {
+                    if ($dates[0] !== '12') {
+                        $dates[0] += 12;
+                    }
+                } elseif ($dates[0] == '12') {
+                    $dates[0] = '0';
+                }
+                $dates[count($dates) - 1] = sprintf('%02d', $dates[count($dates)-1]);
+            }
+            return $dates[0] . ':' . $dates[1] . (count($dates) == 3 ? (':' . $dates[2]) : ':00');
+
+        case 'datetime':
+            switch ($params['order'][$key]) {
+            case -1:
+                return (string)(int)$date == $date
+                    ? date('Y-m-d H:i:s', $date)
+                    : $date;
+            case 0:
+                list($day, $time) = explode(' ', $date, 2);
+                break;
+            case 1:
+               list($time, $day) = explode(' ', $date, 2);
+               break;
+            }
+            $date = $this->mapDate($day, 'date',
+                                   array('delimiter' => $params['day_delimiter'],
+                                         'format' => $params['day_format']),
+                                   $key);
+            $time = $this->mapDate($time, 'time',
+                                   array('delimiter' => $params['time_delimiter'],
+                                         'format' => $params['time_format']),
+                                   $key);
+            return $date . ' ' . $time;
+
+        }
+    }
+
+    /**
+     * Takes all necessary actions for the given import step, parameters and
+     * form values and returns the next necessary step.
+     *
+     * @param integer $action  The current step. One of the IMPORT_* constants.
+     * @param array $param     An associative array containing needed
+     *                         parameters for the current step.
+     *
+     * @return mixed  Either the next step as an integer constant or imported
+     *                data set after the final step.
+     * @throws Horde_Data_Exception
+     */
+    public function nextStep($action, $param = array())
+    {
+        /* First step. */
+        if (is_null($action)) {
+            $_SESSION['import_data'] = array();
+            return Horde_Data::IMPORT_FILE;
+        }
+
+        switch ($action) {
+        case Horde_Data::IMPORT_FILE:
+            /* Sanitize uploaded file. */
+            try {
+                $this->_browser->wasFileUploaded('import_file', $param['file_types'][$this->_vars->import_format]);
+            } catch (Horde_Exception $e) {
+                throw new Horde_Data_Exception($e);
+            }
+            if ($_FILES['import_file']['size'] <= 0) {
+                return PEAR::raiseError(_("The file contained no data."));
+            }
+            $_SESSION['import_data']['format'] = $this->_vars->import_format;
+            break;
+
+        case Horde_Data::IMPORT_MAPPED:
+            if (!$this->_vars->dataKeys || !$this->_vars->appKeys) {
+                throw new Horde_Data_Exception('You didn\'t map any fields from the imported file to the corresponding fields.');
+            }
+            $dataKeys = explode("\t", $this->_vars->dataKeys);
+            $appKeys = explode("\t", $this->_vars->appKeys);
+            $map = array();
+            $dates = array();
+            foreach ($appKeys as $key => $app) {
+                $map[$dataKeys[$key]] = $app;
+                if (isset($param['time_fields']) &&
+                    isset($param['time_fields'][$app])) {
+                    $dates[$dataKeys[$key]]['type'] = $param['time_fields'][$app];
+                    $dates[$dataKeys[$key]]['values'] = array();
+                    $i = 0;
+                    /* Build an example array of up to 10 date/time fields. */
+                    while ($i < count($_SESSION['import_data']['data']) && count($dates[$dataKeys[$key]]['values']) < 10) {
+                        if (!empty($_SESSION['import_data']['data'][$i][$dataKeys[$key]])) {
+                            $dates[$dataKeys[$key]]['values'][] = $_SESSION['import_data']['data'][$i][$dataKeys[$key]];
+                        }
+                        $i++;
+                    }
+                }
+            }
+            $_SESSION['import_data']['map'] = $map;
+            if (count($dates) > 0) {
+                foreach ($dates as $key => $data) {
+                    if (count($data['values'])) {
+                        $_SESSION['import_data']['dates'] = $dates;
+                        return Horde_Data::IMPORT_DATETIME;
+                    }
+                }
+            }
+            return $this->nextStep(Horde_Data::IMPORT_DATA, $param);
+
+        case Horde_Data::IMPORT_DATETIME:
+        case Horde_Data::IMPORT_DATA:
+            if ($action == Horde_Data::IMPORT_DATETIME) {
+                $params = array(
+                    'delimiter' => $this->_vars->delimiter,
+                    'format' => $this->_vars->format,
+                    'order' => $this->_vars->order,
+                    'day_delimiter' => $this->_vars->day_delimiter,
+                    'day_format' => $this->_vars->day_format,
+                    'time_delimiter' => $this->_vars->time_delimiter,
+                    'time_format' => $this->_vars->time_format
+                );
+            }
+
+            if (!isset($_SESSION['import_data']['data'])) {
+                throw new Horde_Data_Exception('The uploaded data was lost since the previous step.');
+            }
+
+            /* Build the result data set as an associative array. */
+            $data = array();
+            foreach ($_SESSION['import_data']['data'] as $row) {
+                $data_row = array();
+                foreach ($row as $key => $val) {
+                    if (isset($_SESSION['import_data']['map'][$key])) {
+                        $mapped_key = $_SESSION['import_data']['map'][$key];
+                        if ($action == Horde_Data::IMPORT_DATETIME &&
+                            !empty($val) &&
+                            isset($param['time_fields']) &&
+                            isset($param['time_fields'][$mapped_key])) {
+                            $val = $this->mapDate($val, $param['time_fields'][$mapped_key], $params, $key);
+                        }
+                        $data_row[$_SESSION['import_data']['map'][$key]] = $val;
+                    }
+                }
+                $data[] = $data_row;
+            }
+            return $data;
+        }
+    }
+
+    /**
+     * Cleans the session data up and removes any uploaded and moved
+     * files.
+     *
+     * @return mixed  If callback called, the return value of this call.
+     *                This should be the value of the first import step.
+     */
+    public function cleanup()
+    {
+        if (isset($_SESSION['import_data']['file_name'])) {
+            @unlink($_SESSION['import_data']['file_name']);
+        }
+        $_SESSION['import_data'] = array();
+
+        if ($this->_cleanupCallback) {
+            return call_user_func($this->_cleanupCallback);
+        }
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Exception.php b/framework/Data/lib/Horde/Data/Exception.php
new file mode 100644 (file)
index 0000000..12a2328
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Exception handler for the Horde_Data package.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Exception extends Horde_Exception_Prior
+{
+}
diff --git a/framework/Data/lib/Horde/Data/Icalendar.php b/framework/Data/lib/Horde/Data/Icalendar.php
new file mode 100644 (file)
index 0000000..dd39f24
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This is iCalendar (vCalendar).
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @author   Karsten Fourmont <fourmont@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Icalendar extends Horde_Data_Imc {}
diff --git a/framework/Data/lib/Horde/Data/Imc.php b/framework/Data/lib/Horde/Data/Imc.php
new file mode 100644 (file)
index 0000000..8e7150e
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Abstract implementation of the Horde_Data:: API for IMC data -
+ * vCards and iCalendar data, etc. Provides a number of utility
+ * methods that vCard and iCalendar implementation can share and rely
+ * on.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Imc extends Horde_Data_Driver
+{
+    /**
+     * @var
+     */
+    protected $_iCal = false;
+
+    /**
+     *
+     * @throws Horde_Data_Exception
+     */
+    public function importData($text)
+    {
+        $this->_iCal = new Horde_iCalendar();
+        if (!$this->_iCal->parsevCalendar($text)) {
+            throw new Horde_Data_Exception('There was an error importing the iCalendar data.');
+        }
+
+        return $this->_iCal->getComponents();
+    }
+
+    /**
+     * Builds an iCalendar file from a given data structure and
+     * returns it as a string.
+     *
+     * @param array $data     An array containing Horde_iCalendar_vevent
+     *                        objects
+     * @param string $method  The iTip method to use.
+     *
+     * @return string  The iCalendar data.
+     */
+    public function exportData($data, $method = 'REQUEST')
+    {
+        $this->_iCal = new Horde_iCalendar();
+        $this->_iCal->setAttribute('METHOD', $method);
+
+        foreach ($data as $event) {
+            $this->_iCal->addComponent($event);
+        }
+
+        return $this->_iCal->exportvCalendar();
+    }
+
+    /**
+     * Builds an iCalendar file from a given data structure and
+     * triggers its download.  It DOES NOT exit the current script but
+     * only outputs the correct headers and data.
+     *
+     * @param string $filename   The name of the file to be downloaded.
+     * @param array $data        An array containing Horde_iCalendar_vevents
+     */
+    public function exportFile($filename, $data)
+    {
+        $export = $this->exportData($data);
+        $this->_browser->downloadHeaders($filename, 'text/calendar', false, strlen($export));
+        echo $export;
+    }
+
+    /**
+     * Takes all necessary actions for the given import step,
+     * parameters and form values and returns the next necessary step.
+     *
+     * @param integer $action  The current step. One of the IMPORT_* constants.
+     * @param array $param     An associative array containing needed
+     *                         parameters for the current step.
+     *
+     * @return mixed  Either the next step as an integer constant or imported
+     *                data set after the final step.
+     * @throws Horde_Data_Exception
+     */
+    public function nextStep($action, $param = array())
+    {
+        switch ($action) {
+        case Horde_Data::IMPORT_FILE:
+            parent::nextStep($action, $param);
+            $this->importFile($_FILES['import_file']['tmp_name']);
+            return $this->_iCal->getComponents();
+        }
+
+        return parent::nextStep($action, $param);
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Outlookcsv.php b/framework/Data/lib/Horde/Data/Outlookcsv.php
new file mode 100644 (file)
index 0000000..978ea66
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Horde_Data implementation for Outlook comma-separated data (CSV).
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Outlookcsv extends Horde_Data_Csv
+{
+    /**
+     * Builds a CSV file from a given data structure and returns it as a
+     * string.
+     *
+     * @param array $data      A two-dimensional array containing the data
+     *                         set.
+     * @param boolean $header  If true, the rows of $data are associative
+     *                         arrays with field names as their keys.
+     *
+     * @return string  The CSV data.
+     */
+    public function exportData($data, $header = false,
+                               $export_mapping = array())
+    {
+        if (!is_array($data) || (count($data) == 0)) {
+            return '';
+        }
+
+        $export = '';
+        $eol = "\r\n";
+        $head = array_keys(current($data));
+
+        if ($header) {
+            foreach ($head as $key) {
+                if (!empty($key)) {
+                    if (isset($export_mapping[$key])) {
+                        $key = $export_mapping[$key];
+                    }
+                    $export .= '"' . $key . '"';
+                }
+                $export .= ',';
+            }
+            $export = substr($export, 0, -1) . $eol;
+        }
+
+        foreach ($data as $row) {
+            foreach ($head as $key) {
+                $cell = $row[$key];
+                if (!empty($cell) || $cell === 0) {
+                    $cell = preg_replace("/\"/", "\"\"", $cell);
+                    $export .= '"' . $cell . '"';
+                }
+                $export .= ',';
+            }
+            $export = substr($export, 0, -1) . $eol;
+        }
+
+        return $export;
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Tsv.php b/framework/Data/lib/Horde/Data/Tsv.php
new file mode 100644 (file)
index 0000000..a0f76c9
--- /dev/null
@@ -0,0 +1,238 @@
+<?php
+/**
+ * Horde_Data implementation for tab-separated data (TSV).
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Tsv extends Horde_Data_Driver
+{
+    /**
+     * File extension.
+     *
+     * @var string
+     */
+    protected $_extension = 'tsv';
+
+    /**
+     * MIME content type.
+     *
+     * @var string
+     */
+    protected $_contentType = 'text/tab-separated-values';
+
+    /**
+     * Convert data file contents to list of data records.
+     *
+     * @param string $contents   Data file contents.
+     * @param boolean $header    True if a header row is present.
+     * @param string $delimiter  Field delimiter.
+     *
+     * @return array  List of data records.
+     */
+    public function importData($contents, $header = false, $delimiter = "\t")
+    {
+        if ($_SESSION['import_data']['format'] == 'pine') {
+            $contents = preg_replace('/\n +/', '', $contents);
+        }
+
+        $contents = explode("\n", $contents);
+        $data = array();
+        if ($header) {
+            $head = explode($delimiter, array_shift($contents));
+        }
+
+        foreach ($contents as $line) {
+            if (trim($line) == '') {
+                continue;
+            }
+            $line = explode($delimiter, $line);
+            if (!isset($head)) {
+                $data[] = $line;
+            } else {
+                $newline = array();
+                for ($i = 0; $i < count($head); $i++) {
+                    $newline[$head[$i]] = empty($line[$i]) ? '' : $line[$i];
+                }
+                $data[] = $newline;
+            }
+        }
+
+        return $data;
+    }
+
+    /**
+     * Builds a TSV file from a given data structure and returns it as a
+     * string.
+     *
+     * @param array $data      A two-dimensional array containing the data set.
+     * @param boolean $header  If true, the rows of $data are associative
+     *                         arrays with field names as their keys.
+     *
+     * @return string  The TSV data.
+     */
+    public function exportData($data, $header = false)
+    {
+        if (!is_array($data) || count($data) == 0) {
+            return '';
+        }
+        $export = '';
+        $head = array_keys(current($data));
+        if ($header) {
+            $export = implode("\t", $head) . "\n";
+        }
+        foreach ($data as $row) {
+            foreach ($head as $key) {
+                $cell = $row[$key];
+                if (!empty($cell) || $cell === 0) {
+                    $export .= $cell;
+                }
+                $export .= "\t";
+            }
+            $export = substr($export, 0, -1) . "\n";
+        }
+
+        return $export;
+    }
+
+    /**
+     * Builds a TSV file from a given data structure and triggers its download.
+     * It DOES NOT exit the current script but only outputs the correct headers
+     * and data.
+     *
+     * @param string $filename  The name of the file to be downloaded.
+     * @param array $data       A two-dimensional array containing the data
+     *                          set.
+     * @param boolean $header   If true, the rows of $data are associative
+     *                          arrays with field names as their keys.
+     */
+    public function exportFile($filename, $data, $header = false)
+    {
+        $export = $this->exportData($data, $header);
+        $this->_browser->downloadHeaders($filename, 'text/tab-separated-values', false, strlen($export));
+        echo $export;
+    }
+
+    /**
+     * Takes all necessary actions for the given import step, parameters and
+     * form values and returns the next necessary step.
+     *
+     * @param integer $action  The current step. One of the IMPORT_* constants.
+     * @param array $param     An associative array containing needed
+     *                         parameters for the current step.
+     *
+     * @return mixed  Either the next step as an integer constant or imported
+     *                data set after the final step.
+     * @throws Horde_Data_Exception
+     */
+    public function nextStep($action, $param = array())
+    {
+        switch ($action) {
+        case Horde_Data::IMPORT_FILE:
+            parent::nextStep($action, $param);
+
+            if ($_SESSION['import_data']['format'] == 'mulberry' ||
+                $_SESSION['import_data']['format'] == 'pine') {
+                $_SESSION['import_data']['data'] = $this->importFile($_FILES['import_file']['tmp_name']);
+                $format = $_SESSION['import_data']['format'];
+                if ($format == 'mulberry') {
+                    $appKeys  = array('alias', 'name', 'email', 'company', 'workAddress', 'workPhone', 'homePhone', 'fax', 'notes');
+                    $dataKeys = array(0, 1, 2, 3, 4, 5, 6, 7, 9);
+                } elseif ($format == 'pine') {
+                    $appKeys = array('alias', 'name', 'email', 'notes');
+                    $dataKeys = array(0, 1, 2, 4);
+                }
+                foreach ($appKeys as $key => $app) {
+                    $map[$dataKeys[$key]] = $app;
+                }
+                $data = array();
+                foreach ($_SESSION['import_data']['data'] as $row) {
+                    $hash = array();
+                    if ($format == 'mulberry') {
+                        if (preg_match("/^Grp:/", $row[0]) || empty($row[1])) {
+                            continue;
+                        }
+                        $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
+                        foreach ($dataKeys as $key) {
+                            if (array_key_exists($key, $row)) {
+                                $hash[$key] = stripslashes(preg_replace('/\\\\r/', "\n", $row[$key]));
+                            }
+                        }
+                    } elseif ($format == 'pine') {
+                        if (count($row) < 3 || preg_match("/^#DELETED/", $row[0]) || preg_match("/[()]/", $row[2])) {
+                            continue;
+                        }
+                        $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
+                        /* Address can be a full RFC822 address */
+                        try {
+                            $addr_arr = Horde_Mime_Address::parseAddressList($row[2]);
+                        } catch (Horde_Mime_Exception $e) {
+                            continue;
+                        }
+                        if (empty($addr_arr[0]->mailbox)) {
+                            continue;
+                        }
+                        $row[2] = $addr_arr[0]->mailbox . '@' . $addr_arr[0]->host;
+                        if (empty($row[1]) && !empty($addr_arr[0]->personal)) {
+                            $row[1] = $addr_arr[0]->personal;
+                        }
+                        foreach ($dataKeys as $key) {
+                            if (array_key_exists($key, $row)) {
+                                $hash[$key] = $row[$key];
+                            }
+                        }
+                    }
+                    $data[] = $hash;
+                }
+                $_SESSION['import_data']['data'] = $data;
+                $_SESSION['import_data']['map'] = $map;
+                $ret = $this->nextStep(Horde_Data::IMPORT_DATA, $param);
+                return $ret;
+            }
+
+            /* Move uploaded file so that we can read it again in the next step
+               after the user gave some format details. */
+            try {
+                $this->_browser->wasFileUploaded('import_file', _("TSV file"));
+            } catch (Horde_Browser_Exception $e) {
+                throw new Horde_Data_Exception($e);
+            }
+            $file_name = Horde_Util::getTempFile('import', false);
+            if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) {
+                throw new Horde_Data_Exception('The uploaded file could not be saved.');
+            }
+            $_SESSION['import_data']['file_name'] = $file_name;
+
+            /* Read the file's first two lines to show them to the user. */
+            $_SESSION['import_data']['first_lines'] = '';
+            $fp = @fopen($file_name, 'r');
+            if ($fp) {
+                $line_no = 1;
+                while ($line_no < 3 && $line = fgets($fp)) {
+                    $newline = Horde_String::length($line) > 100 ? "\n" : '';
+                    $_SESSION['import_data']['first_lines'] .= substr($line, 0, 100) . $newline;
+                    $line_no++;
+                }
+            }
+            return Horde_Data::IMPORT_TSV;
+
+        case Horde_Data::IMPORT_TSV:
+            $_SESSION['import_data']['header'] = $this->_vars->header;
+            $import_data = $this->importFile($_SESSION['import_data']['file_name'],
+                                             $_SESSION['import_data']['header']);
+            $_SESSION['import_data']['data'] = $import_data;
+            unset($_SESSION['import_data']['map']);
+            return Horde_Data::IMPORT_MAPPED;
+        }
+
+        return parent::nextStep($action, $param);
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Vcard.php b/framework/Data/lib/Horde/Data/Vcard.php
new file mode 100644 (file)
index 0000000..89f6b8d
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Implement the Horde_Data:: API for vCard data.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Vcard extends Horde_Data_Imc {
+
+    /**
+     * Exports vcalendar data as a string. Unlike vEvent, vCard data
+     * is not enclosed in BEGIN|END:vCalendar.
+     *
+     * @param array $data     An array containing Horde_iCalendar_Vcard
+     *                        objects.
+     * @param string $method  The iTip method to use.
+     *
+     * @return string  The iCalendar data.
+     */
+    public function exportData($data, $method = 'REQUEST')
+    {
+        $s = '';
+
+        foreach ($data as $vcard) {
+            $s.= $vcard->exportvCalendar();
+        }
+
+        return $s;
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Vnote.php b/framework/Data/lib/Horde/Data/Vnote.php
new file mode 100644 (file)
index 0000000..068ce15
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Implement the Horde_Data:: API for vNote data.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Vnote extends Horde_Data_Imc
+{
+    /**
+     * Exports vcalendar data as a string. Unlike vEvent, vNote data
+     * is not enclosed in BEGIN|END:vCalendar.
+     *
+     * @param array $data     An array containing Horde_iCalendar_Vnote
+     *                        objects.
+     * @param string $method  The iTip method to use.
+     *
+     * @return string  The iCalendar data.
+     */
+    public function exportData($data, $method = 'REQUEST')
+    {
+        $this->_iCal = new Horde_iCalendar();
+        $this->_iCal->setAttribute('METHOD', $method);
+
+        $s = '';
+        foreach ($data as $event) {
+            $s. = $event->exportvCalendar();
+        }
+
+        return $s;
+    }
+
+}
diff --git a/framework/Data/lib/Horde/Data/Vtodo.php b/framework/Data/lib/Horde/Data/Vtodo.php
new file mode 100644 (file)
index 0000000..123fcf9
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Implement the Horde_Data:: API for vTodo data.
+ *
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @category Horde
+ * @package  Data
+ */
+class Horde_Data_Vtodo extends Horde_Data_Imc {}
index fe19682..9d53aca 100644 (file)
@@ -3,7 +3,7 @@
 http://pear.php.net/dtd/tasks-1.0.xsd
 http://pear.php.net/dtd/package-2.0
 http://pear.php.net/dtd/package-2.0.xsd">
- <name>Horde_Data</name>
+ <name>Data</name>
  <channel>pear.horde.org</channel>
  <summary>Horde Data API</summary>
  <description>This package provides a data import and export API, with backends for:
@@ -26,37 +26,46 @@ http://pear.php.net/dtd/package-2.0.xsd">
   <email>chuck@horde.org</email>
   <active>yes</active>
  </developer>
- <date>2006-05-08</date>
- <time>21:12:22</time>
+ <date>2010-05-12</date>
  <version>
-  <release>0.0.3</release>
-  <api>0.0.3</api>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
  </version>
  <stability>
   <release>beta</release>
   <api>beta</api>
  </stability>
  <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
- <notes>Converted to package.xml 2.0 for pear.horde.org
+ <notes>* Initial Horde 4 package.
  </notes>
  <contents>
   <dir name="/">
-   <dir name="Data">
-    <file baseinstalldir="/Horde" name="csv.php" role="php" />
-    <file baseinstalldir="/Horde" name="icalendar.php" role="php" />
-    <file baseinstalldir="/Horde" name="imc.php" role="php" />
-    <file baseinstalldir="/Horde" name="outlookcsv.php" role="php" />
-    <file baseinstalldir="/Horde" name="tsv.php" role="php" />
-    <file baseinstalldir="/Horde" name="vcard.php" role="php" />
-    <file baseinstalldir="/Horde" name="vnote.php" role="php" />
-    <file baseinstalldir="/Horde" name="vtodo.php" role="php" />
-   </dir> <!-- /Data -->
-   <dir name="tests">
-    <file baseinstalldir="/Horde" name="csv_importFile_01.phpt" role="test" />
-    <file baseinstalldir="/Horde" name="simple_dos.csv" role="test" />
-    <file baseinstalldir="/Horde" name="simple_unix.csv" role="test" />
-   </dir> <!-- /tests -->
-   <file baseinstalldir="/Horde" name="Data.php" role="php" />
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Data">
+      <file name="Csv.php" role="php" />
+      <file name="Driver.php" role="php" />
+      <file name="Exception.php" role="php" />
+      <file name="Icalendar.php" role="php" />
+      <file name="Imc.php" role="php" />
+      <file name="Outlookcsv.php" role="php" />
+      <file name="Tsv.php" role="php" />
+      <file name="Vcard.php" role="php" />
+      <file name="Vnote.php" role="php" />
+      <file name="Vtodo.php" role="php" />
+     </dir> <!-- /lib/Horde/Data -->
+     <file name="Data.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+   <dir name="test">
+    <dir name="Horde">
+     <dir name="Data">
+      <file name="csv_importFile_01.phpt" role="test" />
+      <file name="simple_dos.csv" role="test" />
+      <file name="simple_unix.csv" role="test" />
+     </dir> <!-- /test/Horde/Data -->
+    </dir> <!-- /test/Horde -->
+   </dir> <!-- /test -->
   </dir> <!-- / -->
  </contents>
  <dependencies>
@@ -68,7 +77,15 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <min>1.7.0</min>
    </pearinstaller>
    <package>
-    <name>iCalendar</name>
+    <name>Browser</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>Exception</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>File_Csv</name>
     <channel>pear.horde.org</channel>
    </package>
    <package>
@@ -79,16 +96,44 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <name>Util</name>
     <channel>pear.horde.org</channel>
    </package>
+   <package>
+    <name>iCalendar</name>
+    <channel>pear.horde.org</channel>
+   </package>
   </required>
-  <optional>
-   <extension>
-    <name>gettext</name>
-   </extension>
-  </optional>
  </dependencies>
- <phprelease />
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Data/Csv.php" as="Horde/Data/Csv.php" />
+   <install name="lib/Horde/Data/Driver.php" as="Horde/Data/Driver.php" />
+   <install name="lib/Horde/Data/Exception.php" as="Horde/Data/Exception.php" />
+   <install name="lib/Horde/Data/Icalendar.php" as="Horde/Data/Icalendar.php" />
+   <install name="lib/Horde/Data/Imc.php" as="Horde/Data/Imc.php" />
+   <install name="lib/Horde/Data/Outlookcsv.php" as="Horde/Data/Outlookcsv.php" />
+   <install name="lib/Horde/Data/Tsv.php" as="Horde/Data/Tsv.php" />
+   <install name="lib/Horde/Data/Vcard.php" as="Horde/Data/Vcard.php" />
+   <install name="lib/Horde/Data/Vnote.php" as="Horde/Data/Vnote.php" />
+   <install name="lib/Horde/Data/Vtodo.php" as="Horde/Data/Vtodo.php" />
+   <install name="lib/Horde/Data.php" as="Horde/Data.php" />
+  </filelist>
+ </phprelease>
  <changelog>
   <release>
+   <date>2006-05-08</date>
+   <time>21:12:22</time>
+   <version>
+    <release>0.0.3</release>
+    <api>0.0.3</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Converted to package.xml 2.0 for pear.horde.org
+   </notes>
+  </release>
+  <release>
    <version>
     <release>0.0.2</release>
     <api>0.0.2</api>
diff --git a/framework/Data/test/Horde/Data/csv_importFile_01.phpt b/framework/Data/test/Horde/Data/csv_importFile_01.phpt
new file mode 100644 (file)
index 0000000..7999b3d
--- /dev/null
@@ -0,0 +1,90 @@
+--TEST--
+Simple CSV files
+--FILE--
+<?php
+
+require 'Horde.php';
+require 'Horde/Data.php';
+
+$data = Horde_Data::factory('csv');
+var_dump($data->importFile(dirname(__FILE__) . '/simple_dos.csv', false, '', '', 4));
+var_dump($data->importFile(dirname(__FILE__) . '/simple_unix.csv', false, '', '', 4));
+var_dump($data->importFile(dirname(__FILE__) . '/simple_dos.csv', true, '', '', 4));
+var_dump($data->importFile(dirname(__FILE__) . '/simple_unix.csv', true, '', '', 4));
+
+?>
+--EXPECT--
+array(2) {
+  [0]=>
+  array(4) {
+    [0]=>
+    string(3) "one"
+    [1]=>
+    string(3) "two"
+    [2]=>
+    string(10) "three four"
+    [3]=>
+    string(4) "five"
+  }
+  [1]=>
+  array(4) {
+    [0]=>
+    string(3) "six"
+    [1]=>
+    string(5) "seven"
+    [2]=>
+    string(10) "eight nine"
+    [3]=>
+    string(4) " ten"
+  }
+}
+array(2) {
+  [0]=>
+  array(4) {
+    [0]=>
+    string(3) "one"
+    [1]=>
+    string(3) "two"
+    [2]=>
+    string(10) "three four"
+    [3]=>
+    string(4) "five"
+  }
+  [1]=>
+  array(4) {
+    [0]=>
+    string(3) "six"
+    [1]=>
+    string(5) "seven"
+    [2]=>
+    string(10) "eight nine"
+    [3]=>
+    string(4) " ten"
+  }
+}
+array(1) {
+  [0]=>
+  array(4) {
+    ["one"]=>
+    string(3) "six"
+    ["two"]=>
+    string(5) "seven"
+    ["three four"]=>
+    string(10) "eight nine"
+    ["five"]=>
+    string(4) " ten"
+  }
+}
+array(1) {
+  [0]=>
+  array(4) {
+    ["one"]=>
+    string(3) "six"
+    ["two"]=>
+    string(5) "seven"
+    ["three four"]=>
+    string(10) "eight nine"
+    ["five"]=>
+    string(4) " ten"
+  }
+}
\ No newline at end of file
diff --git a/framework/Data/test/Horde/Data/simple_dos.csv b/framework/Data/test/Horde/Data/simple_dos.csv
new file mode 100644 (file)
index 0000000..7cc025d
--- /dev/null
@@ -0,0 +1,2 @@
+one,two,three four,five
+six,seven,eight nine, ten
diff --git a/framework/Data/test/Horde/Data/simple_unix.csv b/framework/Data/test/Horde/Data/simple_unix.csv
new file mode 100644 (file)
index 0000000..7cc025d
--- /dev/null
@@ -0,0 +1,2 @@
+one,two,three four,five
+six,seven,eight nine, ten
diff --git a/framework/Data/tests/csv_importFile_01.phpt b/framework/Data/tests/csv_importFile_01.phpt
deleted file mode 100644 (file)
index 7999b3d..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
---TEST--
-Simple CSV files
---FILE--
-<?php
-
-require 'Horde.php';
-require 'Horde/Data.php';
-
-$data = Horde_Data::factory('csv');
-var_dump($data->importFile(dirname(__FILE__) . '/simple_dos.csv', false, '', '', 4));
-var_dump($data->importFile(dirname(__FILE__) . '/simple_unix.csv', false, '', '', 4));
-var_dump($data->importFile(dirname(__FILE__) . '/simple_dos.csv', true, '', '', 4));
-var_dump($data->importFile(dirname(__FILE__) . '/simple_unix.csv', true, '', '', 4));
-
-?>
---EXPECT--
-array(2) {
-  [0]=>
-  array(4) {
-    [0]=>
-    string(3) "one"
-    [1]=>
-    string(3) "two"
-    [2]=>
-    string(10) "three four"
-    [3]=>
-    string(4) "five"
-  }
-  [1]=>
-  array(4) {
-    [0]=>
-    string(3) "six"
-    [1]=>
-    string(5) "seven"
-    [2]=>
-    string(10) "eight nine"
-    [3]=>
-    string(4) " ten"
-  }
-}
-array(2) {
-  [0]=>
-  array(4) {
-    [0]=>
-    string(3) "one"
-    [1]=>
-    string(3) "two"
-    [2]=>
-    string(10) "three four"
-    [3]=>
-    string(4) "five"
-  }
-  [1]=>
-  array(4) {
-    [0]=>
-    string(3) "six"
-    [1]=>
-    string(5) "seven"
-    [2]=>
-    string(10) "eight nine"
-    [3]=>
-    string(4) " ten"
-  }
-}
-array(1) {
-  [0]=>
-  array(4) {
-    ["one"]=>
-    string(3) "six"
-    ["two"]=>
-    string(5) "seven"
-    ["three four"]=>
-    string(10) "eight nine"
-    ["five"]=>
-    string(4) " ten"
-  }
-}
-array(1) {
-  [0]=>
-  array(4) {
-    ["one"]=>
-    string(3) "six"
-    ["two"]=>
-    string(5) "seven"
-    ["three four"]=>
-    string(10) "eight nine"
-    ["five"]=>
-    string(4) " ten"
-  }
-}
\ No newline at end of file
diff --git a/framework/Data/tests/simple_dos.csv b/framework/Data/tests/simple_dos.csv
deleted file mode 100644 (file)
index 7cc025d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-one,two,three four,five
-six,seven,eight nine, ten
diff --git a/framework/Data/tests/simple_unix.csv b/framework/Data/tests/simple_unix.csv
deleted file mode 100644 (file)
index 7cc025d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-one,two,three four,five
-six,seven,eight nine, ten
index d57392d..aa9bb0e 100644 (file)
@@ -9,10 +9,9 @@
  * @package Kronolith
  */
 
-function _cleanup()
+function _cleanupData()
 {
-    global $import_step;
-    $import_step = 1;
+    $GLOBALS['import_step'] = 1;
     return Horde_Data::IMPORT_FILE;
 }
 
@@ -147,8 +146,7 @@ case 'export':
             }
         }
 
-        $csv = &Horde_Data::singleton('csv');
-        $csv->exportFile(_("events.csv"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))->exportFile(_("events.csv"), $data, true);
         exit;
 
     case Horde_Data::EXPORT_ICALENDAR:
@@ -185,34 +183,36 @@ case Horde_Data::IMPORT_FILE:
 }
 
 if (!$error) {
-    $data = &Horde_Data::singleton($import_format);
-    if ($data instanceof PEAR_Error) {
-        $notification->push(_("This file format is not supported."), 'horde.error');
-        $next_step = Horde_Data::IMPORT_FILE;
-    } else {
+    try {
+        $data = $injector->getInstance('Horde_Data')->getOb($import_format, array('cleanup' => '_cleanupData'));
+
         if ($actionID == Horde_Data::IMPORT_FILE) {
+            $cleanup = true;
             try {
                 $share = $kronolith_shares->getShare($_SESSION['import_data']['import_cal']);
                 if (!$share->hasPermission(Horde_Auth::getAuth(), Horde_Perms::EDIT)) {
                     $notification->push(_("You do not have permission to add events to the selected calendar."), 'horde.error');
-                    $next_step = $data->cleanup();
                 } else {
                     $next_step = $data->nextStep($actionID, $param);
-                    if ($next_step instanceof PEAR_Error) {
-                        $notification->push($next_step->getMessage(), 'horde.error');
-                        $next_step = $data->cleanup();
-                    }
+                    $cleanup = false;
                 }
             } catch (Exception $e) {
                 $notification->push(_("You have specified an invalid calendar."), 'horde.error');
+            }
+
+            if ($cleanup) {
                 $next_step = $data->cleanup();
             }
         } else {
             $next_step = $data->nextStep($actionID, $param);
-            if ($next_step instanceof PEAR_Error) {
-                $notification->push($next_step->getMessage(), 'horde.error');
-                $next_step = $data->cleanup();
-            }
+        }
+    } catch (Horde_Data_Exception $e) {
+        if ($data) {
+            $notification->push($e, 'horde.error');
+            $next_step = $data->cleanup();
+        } else {
+            $notification->push(_("This file format is not supported."), 'horde.error');
+            $next_step = Horde_Data::IMPORT_FILE;
         }
     }
 }
index 76a7f00..b47d917 100644 (file)
@@ -1,26 +1,21 @@
 <?php
 /**
- * $Horde: mnemo/data.php,v 1.55 2009/12/04 17:42:24 jan Exp $
- *
  * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
  *
  * See the enclosed file LICENSE for license information (ASL). If you
  * did not receive this file, see http://www.horde.org/licenses/asl.php.
  *
  * @author  Jan Schneider <jan@horde.org>
- * @since   Mnemo 1.0
  * @package Mnemo
  */
 
-function _cleanup()
+function _cleanupData()
 {
-    global $import_step;
-    $import_step = 1;
+    $GLOBALS['import_step'] = 1;
     return Horde_Data::IMPORT_FILE;
 }
 
-@define('MNEMO_BASE', dirname(__FILE__));
-require_once MNEMO_BASE . '/lib/Application.php';
+require_once dirname(__FILE__) . '/lib/Application.php';
 Horde_Registry::appInit('mnemo');
 
 if (!$conf['menu']['import_export']) {
@@ -86,8 +81,7 @@ case 'export':
                 unset($note['uid']);
                 $data[] = $note;
             }
-            $csv = &Horde_Data::singleton('csv');
-            $csv->exportFile(_("notes.csv"), $data, true);
+            $injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))->exportFile(_("notes.csv"), $data, true);
             exit;
         }
     }
@@ -100,15 +94,16 @@ case Horde_Data::IMPORT_FILE:
 
 $next_step = null;
 if (!$error) {
-    $data = &Horde_Data::singleton($import_format);
-    if (is_a($data, 'PEAR_Error')) {
-        $notification->push(_("This file format is not supported."), 'horde.error');
-        $next_step = Horde_Data::IMPORT_FILE;
-    } else {
+    try {
+        $data = $injector->getInstance('Horde_Data')->getOb($import_format, array('cleanup' => '_cleanupData'));
         $next_step = $data->nextStep($actionID, $param);
-        if (is_a($next_step, 'PEAR_Error')) {
-            $notification->push($next_step->getMessage(), 'horde.error');
+    } catch (Horde_Data_Exception $e) {
+        if ($data) {
+            $notification->push($e, 'horde.error');
             $next_step = $data->cleanup();
+        } else {
+            $notification->push(_("This file format is not supported."), 'horde.error');
+            $next_step = Horde_Data::IMPORT_FILE;
         }
     }
 }
index 69c2ff5..9340066 100644 (file)
  * @author Jan Schneider <jan@horde.org>
  */
 
-function _cleanup()
+function _cleanupData()
 {
-    global $import_step;
-    $import_step = 1;
+    $GLOBALS['import_step'] = 1;
     return Horde_Data::IMPORT_FILE;
 }
 
@@ -114,8 +113,7 @@ case 'export':
                 unset($task['delete_link']);
                 $data[] = $task;
             }
-            $csv = Horde_Data::singleton('csv');
-            $csv->exportFile(_("tasks.csv"), $data, true);
+            $injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))->exportFile(_("tasks.csv"), $data, true);
             exit;
 
         case Horde_Data::EXPORT_ICALENDAR:
@@ -140,15 +138,16 @@ case Horde_Data::IMPORT_FILE:
 }
 
 if (!$error) {
-    $data = Horde_Data::singleton($import_format);
-    if (is_a($data, 'PEAR_Error')) {
-        $notification->push(_("This file format is not supported."), 'horde.error');
-        $next_step = Horde_Data::IMPORT_FILE;
-    } else {
+    try {
+        $data = $injector->getInstance('Horde_Data')->getOb($import_format, array('cleanup' => '_cleanupData'));
         $next_step = $data->nextStep($actionID, $param);
-        if (is_a($next_step, 'PEAR_Error')) {
-            $notification->push($next_step->getMessage(), 'horde.error');
+    } catch (Horde_Data_Exception $e) {
+        if ($data) {
+            $notification->push($e, 'horde.error');
             $next_step = $data->cleanup();
+        } else {
+            $notification->push(_("This file format is not supported."), 'horde.error');
+            $next_step = Horde_Data::IMPORT_FILE;
         }
     }
 }
index f886f0d..ecbc60b 100644 (file)
@@ -125,12 +125,12 @@ class ExportCDRForm extends SearchCDRForm
         switch($this->_vars->get('format')) {
         case Horde_Data::EXPORT_CSV:
             $ext = 'csv';
-            $fmt = Horde_Data::singleton('csv');
+            $fmt = $GLOBALS['injector']->getInstance('Horde_Data')->getOb('Csv');
             break;
 
         case Horde_Data::EXPORT_TSV:
             $ext = 'tsv';
-            $fmt = Horde_Data::singleton('tsv');
+            $fmt = $GLOBALS['injector']->getInstance('Horde_Data')->getOb('Tsv');
             break;
 
         default:
index c5470ae..6d05f4d 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 require_once dirname(__FILE__) . '/lib/base.php';
-require_once 'Horde/Data.php';
 
 if (!$conf['menu']['export']) {
     header('Location: ' . Horde::applicationUrl('list.php', true));
@@ -159,13 +158,11 @@ case 'export':
 
     switch (Horde_Util::getFormData('exportID')) {
     case EXPORT_CSV:
-        $csv = &Horde_Data::singleton('csv');
-        $csv->exportFile(_("class.csv"), $data, (Horde_Util::getFormData('student') == 'all'));
+        $injector->getInstance('Horde_Data')->getOb('Csv')->exportFile(_("class.csv"), $data, (Horde_Util::getFormData('student') == 'all'));
         exit;
 
     case EXPORT_TSV:
-        $tsv = &Horde_Data::singleton('tsv');
-        $tsv->exportFile(_("class.tsv"), $data, (Horde_Util::getFormData('student') == 'all'));
+        $injector->getInstance('Horde_Data')->getOb('Tsv')->exportFile(_("class.tsv"), $data, (Horde_Util::getFormData('student') == 'all'));
         exit;
 
     }
index 42e4930..7680be5 100644 (file)
  * @author Jan Schneider <jan@horde.org>
  */
 
-function _cleanup()
+function _cleanupData()
 {
-    global $import_step;
-    $import_step = 1;
+    $GLOBALS['import_step'] = 1;
     return Horde_Data::IMPORT_FILE;
 }
 
@@ -310,27 +309,25 @@ case 'export':
 
     switch ($exportType) {
     case Horde_Data::EXPORT_CSV:
-        $csv = Horde_Data::singleton('csv');
-        $csv->exportFile(_("contacts.csv"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))->exportFile(_("contacts.csv"), $data, true);
         exit;
 
     case Horde_Data::EXPORT_OUTLOOKCSV:
-        $csv = Horde_Data::singleton('outlookcsv');
-        $csv->exportFile(_("contacts.csv"), $data, true, array_flip($outlook_mapping));
+        $injector->getInstance('Horde_Data')->getOb('Outlookcsv', array('cleanup' => '_cleanupData'))->exportFile(_("contacts.csv"), $data, true, array_flip($outlook_mapping));
         exit;
 
     case Horde_Data::EXPORT_TSV:
-        $tsv = Horde_Data::singleton('tsv');
-        $tsv->exportFile(_("contacts.tsv"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Tsv', array('cleanup' => '_cleanupData'))->exportFile(_("contacts.tsv"), $data, true);
         exit;
 
     case Horde_Data::EXPORT_VCARD:
     case 'vcard30':
-        $vcard = Horde_Data::singleton('vcard');
-        $vcard->exportFile(_("contacts.vcf"), $data, true);
+        $injector->getInstance('Horde_Data')->getOb('Vcard', array('cleanup' => '_cleanupData'))->exportFile(_("contacts.vcf"), $data, true);
         exit;
 
     case 'ldif':
+        // TODO
+        //$injector->getInstance('Horde_Data')->getOb('Csv', array('cleanup' => '_cleanupData'))
         $ldif = Horde_Data::singleton(array('turba', 'ldif'));
         $ldif->exportFile(_("contacts.ldif"), $data, true);
         exit;
@@ -381,6 +378,7 @@ case Horde_Data::IMPORT_DATETIME:
 }
 
 if (!$error && !empty($import_format)) {
+    // TODO
     if ($import_format == 'ldif') {
         $data = Horde_Data::singleton(array('turba', $import_format));
     } else {
index dd4b04b..eb04895 100644 (file)
@@ -38,9 +38,9 @@ if (!$object->hasPermission(Horde_Perms::READ)) {
     exit;
 }
 
-$vcard = Horde_Data::singleton('vcard');
 $filename = str_replace(' ', '_', $object->getValue('name'));
 if (!$filename) {
     $filename = _("contact");
 }
-$vcard->exportFile($filename . '.vcf', array($driver->tovCard($object, '2.1', null, true)), Horde_Nls::getCharset());
+
+$injector->getInstance('Horde_Data')->getOb('Vcard')->exportFile($filename . '.vcf', array($driver->tovCard($object, '2.1', null, true)), Horde_Nls::getCharset());