Add initial support for adding/listing/editing devices.
authorBen Klang <ben@alkaloid.net>
Wed, 23 Dec 2009 20:36:58 +0000 (20:36 +0000)
committerBen Klang <ben@alkaloid.net>
Wed, 23 Dec 2009 20:36:58 +0000 (20:36 +0000)
Various fixes within the Sql and Ldap drivers.

git-svn-id: https://svn.alkaloid.net/gpl/shout/trunk@504 06cd67b6-e706-0410-b29e-9de616bca6e9

devices.php [new file with mode: 0644]
extensions.php
lib/Driver.php
lib/Driver/Ldap.php
lib/Driver/Sql.php
lib/Forms/DeviceForm.php [new file with mode: 0644]
lib/Forms/ExtensionForm.php
lib/Shout.php
templates/devices/edit.inc [new file with mode: 0644]
templates/devices/list.inc [new file with mode: 0644]

diff --git a/devices.php b/devices.php
new file mode 100644 (file)
index 0000000..a34aa62
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright 2009 Ben Klang <ben@alkaloid.net>
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+@define('SHOUT_BASE', dirname(__FILE__));
+require_once SHOUT_BASE . '/lib/base.php';
+require_once SHOUT_BASE . '/lib/Forms/DeviceForm.php';
+
+$action = Horde_Util::getFormData('action');
+$devices = $shout_devices->getDevices($context);
+$devid = Horde_Util::getFormData('devid');
+$vars = Horde_Variables::getDefaultVariables();
+
+//$tabs = Shout::getTabs($context, $vars);
+
+$RENDERER = new Horde_Form_Renderer();
+
+$section = 'devices';
+$title = _("Devices: ");
+
+switch ($action) {
+    case 'save':
+        print_r($vars);
+        $Form = new DeviceDetailsForm($vars);
+        print_r($Form);
+        // Show the list if the save was successful, otherwise back to edit.
+        $success = ($Form->isSubmitted() && $Form->isValid());
+        if ($success) {
+            $notification->push(_("Device settings saved."));
+            $action = 'list';
+            break;
+        } else {
+            $action = 'edit';
+        }
+    case 'add':
+    case 'edit':
+        if ($action == 'add') {
+            $title .= _("New Device");
+            // Treat adds just like an empty edit
+            $action = 'edit';
+        } else {
+            $title .= sprintf(_("Edit Device %s"), $extension);
+
+        }
+
+        $FormName = 'DeviceDetailsForm';
+        $vars = new Horde_Variables($devices[$devid]);
+        $Form = new DeviceDetailsForm($vars);
+
+        $Form->open($RENDERER, $vars, Horde::applicationUrl('devices.php'), 'post');
+
+        break;
+    
+
+    case 'delete':
+        $notification->push("Not supported.");
+        break;
+    case 'list':
+    default:
+        $action = 'list';
+        $title .= _("List Users");
+}
+
+require SHOUT_TEMPLATES . '/common-header.inc';
+require SHOUT_TEMPLATES . '/menu.inc';
+
+$notification->notify();
+
+//echo $tabs->render($section);
+
+require SHOUT_TEMPLATES . '/devices/' . $action . '.inc';
+
+require $registry->get('templates', 'horde') . '/common-footer.inc';
\ No newline at end of file
index b1dd05d..29f3a82 100644 (file)
@@ -27,22 +27,21 @@ $title = _("Extensions: ");
 
 switch ($action) {
     case 'add':
-        $title .= _("Add Extension");
-
-        # Treat adds just like an empty edit
-        $action = 'edit';
-
     case 'edit':
-        $title .= sprintf(_("Edit Extension %s"), $extension);
+        if ($action == 'add') {
+            $title .= _("New Extension");
+            // Treat adds just like an empty edit
+            $action = 'edit';
+        } else {
+            $title .= sprintf(_("Edit Extension %s"), $extension);
+
+        }
 
         $FormName = 'UserDetailsForm';
         $vars = new Horde_Variables($extensions[$extension]);
         $Form = &Horde_Form::singleton($FormName, $vars);
 
-        $Form->open($RENDERER, $vars, 'index.php', 'post');
-        $Form->preserveVarByPost($vars, 'extension');
-        $Form->preserveVarByPost($vars, 'context');
-        $Form->preserveVarByPost($vars, 'section');
+        $Form->open($RENDERER, $vars, Horde::applicationUrl('extensions.php'), 'post');
 
         break;
     case 'save':
@@ -54,46 +53,28 @@ switch ($action) {
         $FormValid = $Form->validate($vars, true);
 
         if (!$FormValid || !$Form->isSubmitted()) {
-            require SHOUT_BASE . '/usermgr/edit.php';
+            $notification->push("FIXME: Redirect to re-edit");
         } else {
-            # Form is Valid and Submitted
+            // Form is Valid and Submitted
             $extension = $vars->get('extension');
 
-            $limits = $shout->getLimits($context, $extension);
-
             # FIXME: Input Validation (Text::??)
-            $userdetails = array(
+            $details = array(
                 "newextension" => $vars->get('newextension'),
                 "name" => $vars->get('name'),
                 "mailboxpin" => $vars->get('mailboxpin'),
                 "email" => $vars->get('email'),
-                "uid" => $vars->get('uid'),
             );
 
-            $userdetails['telephonenumber'] = array();
-            $telephonenumber = $vars->get("telephonenumber");
-            if (!empty($telephonenumber) && is_array($telephonenumber)) {
-                $i = 1;
-                while ($i <= $limits['telephonenumbersmax']) {
-                    if (!empty($telephonenumber[$i])) {
-                        $userdetails['telephonenumber'][] = $telephonenumber[$i++];
-                    } else {
-                        $i++;
-                    }
-                }
+            try {
+                $res = $shout_extensions->saveUser($context,
+                                                   $extension, $details);
+            } catch (Exception $e) {
+                $notification->push($e);
             }
-
-            $userdetails['dialopts'] = array();
-
-            $res = $shout->saveUser($context, $extension, $userdetails);
-            if (is_a($res, 'PEAR_Error')) {
-                $notification->push($res);
-            } else {
-                $notification->push(_("User information updated."),
+            $notification->push(_("User information updated."),
                                       'horde.success');
-            }
-
-        }
+         }
 
         break;
     case 'delete':
index d5278e0..421afd3 100644 (file)
@@ -139,8 +139,8 @@ class Shout_Driver {
 
         if (is_null($params)) {
             if ($GLOBALS['conf'][$class]['params']['driverconfig'] == 'horde') {
-                $params = array_merge($GLOBALS['conf'][$class]['params'],
-                                      Horde::getDriverConfig('storage', $driver));
+                $params = array_merge(Horde::getDriverConfig('storage', $driver),
+                                      $GLOBALS['conf'][$class]['params']);
             } else {
                 $params = $GLOBALS['conf'][$class]['params'];
             }
index c432417..36f6d87 100644 (file)
@@ -148,52 +148,49 @@ class Shout_Driver_Ldap extends Shout_Driver
     }
 
     /**
-     * Get a context's properties
+     * Get a list of destinations valid for this extension.
+     * A destination is either a telephone number, a VoIP device or an
+     * Instant Messaging address (a special case of VoIP).
      *
-     * @param string $context Context to get properties for
-     *
-     * @return integer Bitfield of properties valid for this context
+     * @param string $context    Context for the extension
+     * @param string $extension  Extension for which to return destinations
      */
-    public function getContextProperties($context)
+    function getDestinations($context, $extension)
     {
+        // FIXME: LDAP filter injection
+        $filter = '(&(AstContext=%s)(AstVoicemailMailbox=%s))';
+        $filter = sprintf($filter, $context, $extension);
 
-        $res = @ldap_search($this->_LDAP,
-            SHOUT_ASTERISK_BRANCH.','.$this->_params['basedn'],
-            "(&(objectClass=asteriskObject)(context=$context))",
-            array('objectClass'));
-        if(!$res) {
-            return PEAR::raiseError(_("Unable to get properties for $context"));
-        }
+        $attrs = array('telephoneNumber', 'AstExtensions');
 
-        $res = ldap_get_entries($this->_LDAP, $res);
+        $res = ldap_search($this->_LDAP, $this->_params['basedn'],
+                           $filter, $attrs);
 
-        $properties = 0;
-        if ($res['count'] != 1) {
-            return PEAR::raiseError(_("Incorrect number of properties found
-for $context"));
+        if ($res === false) {
+            $msg = sprintf('Error while searching LDAP.  Code %s; Message "%s"',
+                           ldap_errno($this->_LDAP), ldap_error($this->_LDAP));
+            Horde::logMessage($msg, __FILE__, __LINE__, PEAR_LOG_ERR);
+            throw new Shout_Exception(_("Internal error searching the directory."));
         }
 
-        foreach ($res[0]['objectclass'] as $objectClass) {
-            switch ($objectClass) {
-                case "vofficeCustomer":
-                    # FIXME What does this objectClass really do for us?
-                    $properties = $properties | SHOUT_CONTEXT_CUSTOMERS;
-                    break;
-
-                case "asteriskExtensions":
-                    $properties = $properties | SHOUT_CONTEXT_EXTENSIONS;
-                    break;
+        $res = ldap_get_entries($this->_LDAP, $res);
 
-                case "asteriskMusicOnHold":
-                    $properties = $properties | SHOUT_CONTEXT_MOH;
-                    break;
+        if ($res === false) {
+            $msg = sprintf('Error while searching LDAP.  Code %s; Message "%s"',
+                           ldap_errno($this->_LDAP), ldap_error($this->_LDAP));
+            Horde::logMessage($msg, __FILE__, __LINE__, PEAR_LOG_ERR);
+            throw new Shout_Exception(_("Internal error searching the directory."));
+        }
 
-                case "asteriskMeetMe":
-                    $properties = $properties | SHOUT_CONTEXT_CONFERENCE;
-                    break;
-            }
+        if ($res['count'] != 1) {
+            $msg = sprintf('Error while searching LDAP.  Code %s; Message "%s"',
+                           ldap_errno($this->_LDAP), ldap_error($this->_LDAP));
+            Horde::logMessage($msg, __FILE__, __LINE__, PEAR_LOG_ERR);
+            throw new Shout_Exception(_("Wrong number of entries found for this search."));
         }
-        return $properties;
+
+        return array('numbers' => $res['telephonenumbers'],
+                     'devices' => $res['astextensions']);
     }
 
     /**
index 12166ac..3e34308 100644 (file)
@@ -61,41 +61,52 @@ class Shout_Driver_Sql extends Shout_Driver
     /**
      * Get a list of devices for a given context
      *
-     * @param string $context    Context in which to search for devices
-     * @param string $extension  Extension in which to search for devices
+     * @param string $context    Context in which to search for devicess
      *
      * @return array  Array of devices within this context with their information
      *
      * @access private
      */
-    public function getDevices($context, $extension)
+    public function getDevices($context)
     {
-        $sql = 'SELECT id, name, callerid, context, host, permit, nat, ' .
-               'secret, disallow, allow FROM %s WHERE mailbox = ?';
+        $sql = 'SELECT id, name, alias, callerid, context, mailbox, host, permit, ' .
+               'nat, secret, disallow, allow FROM %s WHERE accountcode = ?';
         $sql = sprintf($sql, $this->_params['table']);
-        $args = array($extension . '@' . $context);
-
+        $args = array($context);
         $result = $this->_db->query($sql, $args);
-        if (is_a($result instanceof PEAR_Error)) {
-            throw Shout_Exception($result);
+        if ($result instanceof PEAR_Error) {
+            throw new Shout_Exception($result);
         }
 
         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
         if ($row instanceof PEAR_Error) {
-            throw Shout_Exception($row);
+            throw new Shout_Exception($row);
         }
 
         $devices = array();
         while ($row && !($row instanceof PEAR_Error)) {
-            /* Add this new foo to the $_foo list. */
-            $devices[] = $row;
+            // Asterisk uses the "name" field to indicate the registration
+            // identifier.  We use the field "alias" to put a friendly name on
+            // the device.  Thus devid -> name and name => alias
+            $devid = $row['name'];
+            $row['devid'] = $devid;
+            $row['name'] = $row['alias'];
+            unset($row['alias']);
+
+            // Trim off the context from the mailbox number
+            list($row['mailbox']) = explode('@', $row['mailbox']);
+
+            // Hide the DB internal ID from the front-end
+            unset($row['id']);
+
+            $devices[$devid] = $row;
 
             /* Advance to the new row in the result set. */
             $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
         }
 
         $result->free();
-
+        return $devices;
     }
 
     /**
diff --git a/lib/Forms/DeviceForm.php b/lib/Forms/DeviceForm.php
new file mode 100644 (file)
index 0000000..04a75b1
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * $Id: ExtensionForm.php 502 2009-12-21 04:01:12Z bklang $
+ *
+ * Copyright 2005-2009 Ben Klang <ben@alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (GPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/gpl.php.
+ *
+ * @package Shout
+ */
+
+class DeviceDetailsForm extends Horde_Form {
+
+    function __construct(&$vars)
+    {
+        parent::__construct($vars);
+        global $shout_extensions;
+        $context = $vars->get('context');
+        if ($vars->exists('devid')) {
+            $formtitle = "Edit Device";
+            $devid = $vars->get('devid');
+        } else {
+            $formtitle = "Add Device";
+        }
+
+        parent::__construct($vars, _("$formtitle - Context: $context"));
+        $this->addHidden('', 'action', 'text', true);
+        $vars->set('action', 'save');
+        $this->addHidden('', 'devid', 'int', true);
+        $this->addVariable(_("Device Name"), 'name', 'text', true);
+        $this->addVariable(_("Mailbox"), 'mailbox', 'int', true);
+        $this->addVariable(_("CallerID"), 'callerid', 'text', false);
+
+
+        return true;
+    }
+
+}
\ No newline at end of file
index 1fdf8f7..00a9bc7 100644 (file)
  * @package Shout
  */
 
-// {{{
 class UserDetailsForm extends Horde_Form {
 
-    function UserDetailsForm(&$vars)
+    function __construct(&$vars)
     {
         global $shout_extensions;
         $context = $vars->get('context');
index 1ceae10..8eed4aa 100644 (file)
@@ -35,6 +35,7 @@ class Shout
         $menu = new Horde_Menu(HORDE_MENU_MASK_ALL);
 
         $menu->add(Horde::applicationUrl('extensions.php'), _("Extensions"), "user.png");
+        $menu->add(Horde::applicationUrl('devices.php'), _("Devices"), "shout.png");
         $menu->add(Horde::applicationUrl('routes.php'), _("Call Paths"));
 
 
diff --git a/templates/devices/edit.inc b/templates/devices/edit.inc
new file mode 100644 (file)
index 0000000..a95682f
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+$RENDERER->beginActive($Form->getTitle());
+$RENDERER->renderFormActive($Form, $vars);
+$RENDERER->submit();
+$RENDERER->end();
+$Form->close($RENDERER);
\ No newline at end of file
diff --git a/templates/devices/list.inc b/templates/devices/list.inc
new file mode 100644 (file)
index 0000000..49516c0
--- /dev/null
@@ -0,0 +1,40 @@
+<div class="header">
+    Context: <?php echo $context; ?>
+</div>
+
+<div id="userList" class="userList">
+    <table width="100%" cellspacing="0">
+        <tr>
+            <td class="uheader">Device ID</td>
+            <td class="uheader">Mailbox</td>
+            <td class="uheader">CallerID</td>
+        </tr>
+        <?php
+            $line = 0;
+            foreach ($devices as $devid => $info) {
+
+                $url = Horde::applicationUrl("devices.php");
+                $url = Horde_Util::addParameter($url,
+                    array(
+                        'devid' => $devid,
+                    )
+                );
+                $editurl = Horde_Util::addParameter($url, 'action', 'edit');
+                $deleteurl = Horde_Util::addParameter($url, 'action', 'delete');
+        ?>
+        <tr class="item">
+            <td style="width: 20%">
+                <?php echo Horde::link($editurl); echo $devid; ?></a>
+            </td>
+            <td style="width: 35%;">
+                <?php echo $info['mailbox']; ?>
+            </td>
+            <td style="width: 45%">
+                <?php echo $info['callerid']; ?>
+            </td>
+        </tr>
+        <?php
+            }
+        ?>
+    </table>
+</div>