From 0cbf1d97d75253102bb056eff5b338556be0700e Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Fri, 2 Nov 2012 11:32:55 -0400
Subject: [PATCH] Refactored SMS code for greater flexibility; added some new
 SMS configuration options.

---
 config/vufind/sms.ini                         | 15 ++-
 module/VuFind/config/module.config.php        |  2 +-
 .../src/VuFind/Controller/AbstractRecord.php  |  7 +-
 .../src/VuFind/Controller/AjaxController.php  |  9 +-
 module/VuFind/src/VuFind/SMS/AbstractBase.php | 84 +++++++++++++++++
 module/VuFind/src/VuFind/SMS/Factory.php      | 72 ++++++++++++++
 .../VuFind/{Mailer/SMS.php => SMS/Mailer.php} | 93 +++++++++----------
 module/VuFind/src/VuFind/SMS/SMSInterface.php | 69 ++++++++++++++
 themes/blueprint/templates/record/sms.phtml   |  8 +-
 9 files changed, 302 insertions(+), 57 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/SMS/AbstractBase.php
 create mode 100644 module/VuFind/src/VuFind/SMS/Factory.php
 rename module/VuFind/src/VuFind/{Mailer/SMS.php => SMS/Mailer.php} (60%)
 create mode 100644 module/VuFind/src/VuFind/SMS/SMSInterface.php

diff --git a/config/vufind/sms.ini b/config/vufind/sms.ini
index 9676917a861..14fa29dd765 100644
--- a/config/vufind/sms.ini
+++ b/config/vufind/sms.ini
@@ -1,7 +1,18 @@
-; This file defines the list of carriers and their domain names for the SMS service
+[General]
+; Set smsType to Mailer to use VuFind's internal mailer for SMS (default).
+;smsType = Mailer
+
+; This refers to phone number style for validation.  At present, only "US" is
+; supported (default setting); any other setting will disable validation.
+validation = US
+
+; These characters will be filtered from user input phone numbers prior to texting
+filter = "-.() "
+
+; This section defines the list of carriers and their domain names for the SMS service
 ; The format is: unique_identifier = carrier.domain.name:Display Name
 ;
-;For additional carriers, you may find it useful to refer to http://www.txt2day.com
+; For additional carriers, you may find it useful to refer to http://www.txt2day.com.
 [Carriers]
 ; Carriers in the US
 virgin = vmobl.com:"Virgin Mobile"
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 00fb2e21279..267aae7b9b1 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -351,6 +351,7 @@ $config = array(
                 $logger->setConfig(\VuFind\Config\Reader::getConfig());
                 return $logger;
             },
+            'VuFind\SMS' => 'VuFind\SMS\Factory',
             'VuFind\Translator' => function ($sm) {
                 $factory = new \Zend\I18n\Translator\TranslatorServiceFactory();
                 $translator = $factory->createService($sm);
@@ -376,7 +377,6 @@ $config = array(
             'VuFind\RecordLoader' => 'VuFind\Record\Loader',
             'VuFind\SearchSpecsReader' => 'VuFind\Config\SearchSpecsReader',
             'VuFind\SessionManager' => 'Zend\Session\SessionManager',
-            'VuFind\SMS' => 'VuFind\Mailer\SMS',
             'VuFind\WorldCatConnection' => 'VuFind\Connection\WorldCat',
             'VuFind\WorldCatUtils' => 'VuFind\Connection\WorldCatUtils',
         ),
diff --git a/module/VuFind/src/VuFind/Controller/AbstractRecord.php b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
index 5cb48f9f6b9..a0176ad9df0 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractRecord.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
@@ -373,6 +373,7 @@ class AbstractRecord extends AbstractBase
         $sms = $this->getServiceLocator()->get('VuFind\SMS');
         $view = $this->createViewModel();
         $view->carriers = $sms->getCarriers();
+        $view->validation = $sms->getValidationType();
 
         // Process form submission:
         if ($this->params()->fromPost('submit')) {
@@ -382,9 +383,11 @@ class AbstractRecord extends AbstractBase
 
             // Attempt to send the email and show an appropriate flash message:
             try {
-                $sms->textRecord(
-                    $view->provider, $view->to, $driver, $this->getViewRenderer()
+                $body = $this->getViewRenderer()->partial(
+                    'Email/record-sms.phtml',
+                    array('driver' => $driver, 'to' => $view->to)
                 );
+                $sms->text($view->provider, $view->to, null, $body);
                 $this->flashMessenger()->setNamespace('info')
                     ->addMessage('sms_success');
                 return $this->redirectToRecord();
diff --git a/module/VuFind/src/VuFind/Controller/AjaxController.php b/module/VuFind/src/VuFind/Controller/AjaxController.php
index cf1e7b435ed..b5397c0e90e 100644
--- a/module/VuFind/src/VuFind/Controller/AjaxController.php
+++ b/module/VuFind/src/VuFind/Controller/AjaxController.php
@@ -938,9 +938,12 @@ class AjaxController extends AbstractBase
                 $this->params()->fromPost('id'),
                 $this->params()->fromPost('source', 'VuFind')
             );
-            $this->getServiceLocator()->get('VuFind\SMS')->textRecord(
-                $this->params()->fromPost('provider'),
-                $this->params()->fromPost('to'), $record, $this->getViewRenderer()
+            $to = $this->params()->fromPost('to');
+            $body = $this->getViewRenderer()->partial(
+                'Email/record-sms.phtml', array('driver' => $record, 'to' => $to)
+            );
+            $this->getServiceLocator()->get('VuFind\SMS')->text(
+                $this->params()->fromPost('provider'), $to, null, $body
             );
             return $this->output(
                 $this->translate('sms_success'), self::STATUS_OK
diff --git a/module/VuFind/src/VuFind/SMS/AbstractBase.php b/module/VuFind/src/VuFind/SMS/AbstractBase.php
new file mode 100644
index 00000000000..984f9d6edfd
--- /dev/null
+++ b/module/VuFind/src/VuFind/SMS/AbstractBase.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Base class to enable sharing of common methods between SMS subclasses
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2009.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+namespace VuFind\SMS;
+
+/**
+ * Base class to enable sharing of common methods between SMS subclasses
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+abstract class AbstractBase implements SMSInterface
+{
+    /**
+     * SMS configuration
+     *
+     * @var \Zend\Config\Config
+     */
+    protected $smsConfig;
+
+    /**
+     * Constructor
+     *
+     * @param \Zend\Config\Config $config  SMS configuration
+     * @param array               $options Additional options
+     */
+    public function __construct(\Zend\Config\Config $config, $options = array())
+    {
+        $this->smsConfig = $config;
+    }
+
+    /**
+     * Filter bad characters from a phone number
+     *
+     * @param string $num Phone number to filter
+     *
+     * @return string
+     */
+    protected function filterPhoneNumber($num)
+    {
+        $filter = isset($this->smsConfig->General->filter)
+            ? $this->smsConfig->General->filter : '-.() ';
+        return str_replace(str_split($filter), '', $num);
+    }
+
+    /**
+     * Get validation type for phone numbers
+     *
+     * @return string
+     */
+    public function getValidationType()
+    {
+        // Load setting from config; at present, only US is implemented in templates
+        return isset($this->smsConfig->General->validation)
+            ? $this->smsConfig->General->validation : 'US';
+    }
+}
diff --git a/module/VuFind/src/VuFind/SMS/Factory.php b/module/VuFind/src/VuFind/SMS/Factory.php
new file mode 100644
index 00000000000..1decbf4f023
--- /dev/null
+++ b/module/VuFind/src/VuFind/SMS/Factory.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Factory for instantiating SMS objects
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2009.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+namespace VuFind\SMS;
+use VuFind\Config\Reader as ConfigReader,
+    Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Factory for instantiating SMS objects
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+class Factory implements \Zend\ServiceManager\FactoryInterface
+{
+    /**
+     * Create service
+     *
+     * @param ServiceLocatorInterface $sm Service manager
+     *
+     * @return mixed
+     */
+    public function createService(ServiceLocatorInterface $sm)
+    {
+        // Load configurations:
+        $mainConfig = ConfigReader::getConfig();
+        $smsConfig = ConfigReader::getConfig('sms');
+
+        // Determine SMS type:
+        $type = isset($smsConfig->General->smsType)
+            ? $smsConfig->General->smsType : 'Mailer';
+
+        // Initialize object based on requested type:
+        switch (strtolower($type)) {
+        case 'mailer':
+            $options = array('mailer' => $sm->get('VuFind\Mailer'));
+            if (isset($mainConfig->Site->email)) {
+                $options['defaultFrom'] = $mainConfig->Site->email;
+            }
+            return new Mailer($smsConfig, $options);
+        default:
+            throw new \Exception('Unrecognized SMS type: ' . $type);
+        }
+    }
+}
diff --git a/module/VuFind/src/VuFind/Mailer/SMS.php b/module/VuFind/src/VuFind/SMS/Mailer.php
similarity index 60%
rename from module/VuFind/src/VuFind/Mailer/SMS.php
rename to module/VuFind/src/VuFind/SMS/Mailer.php
index 1428012a765..5cff33f43a2 100644
--- a/module/VuFind/src/VuFind/Mailer/SMS.php
+++ b/module/VuFind/src/VuFind/SMS/Mailer.php
@@ -20,26 +20,29 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * @category VuFind2
- * @package  Mailer
+ * @package  SMS
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/system_classes Wiki
  */
-namespace VuFind\Mailer;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\Mail as MailException;
+namespace VuFind\SMS;
 
 /**
  * VuFind Mailer Class for SMS messages
  *
  * @category VuFind2
- * @package  Mailer
+ * @package  SMS
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/system_classes Wiki
  */
-class SMS extends \VuFind\Mailer
+class Mailer extends AbstractBase
 {
-    // Defaults, usually overridden by contents of sms.ini:
+    /**
+     * Default carriers, usually overridden by contents of web/conf/sms.ini.
+     *
+     * @var array
+     */
     protected $carriers = array(
         'virgin' => array('name' => 'Virgin Mobile', 'domain' => 'vmobl.com'),
         'att' => array('name' => 'AT&T', 'domain' => 'txt.att.net'),
@@ -51,38 +54,53 @@ class SMS extends \VuFind\Mailer
         'Cricket' => array('name' => 'Cricket', 'domain' => 'mms.mycricket.com')
     );
 
-    // Default "from" address:
+    /**
+     * Default "from" address
+     *
+     * @var string
+     */
     protected $defaultFrom;
 
     /**
-     * Constructor
+     * VuFind Mailer object
      *
-     * Sets up SMS carriers and other settings from sms.ini.
+     * @var \VuFind\Mailer
+     */
+    protected $mailer;
+
+    /**
+     * Constructor
      *
-     * @param \Zend\Mail\Transport\TransportInterface $transport Mail transport
-     * object (we'll build our own if none is provided).
-     * @param \Zend\Config\Config                     $config    VuFind configuration
-     * object (we'll auto-load if none is provided).
+     * @param \Zend\Config\Config $config  SMS configuration
+     * @param array               $options Additional options: defaultFrom (optional)
+     * and mailer (must be a \VuFind\Mailer object)
      */
-    public function __construct($transport = null, $config = null)
+    public function __construct(\Zend\Config\Config $config, $options = array())
     {
         // Set up parent object first:
-        parent::__construct($transport, $config);
+        parent::__construct($config, $options);
 
-        // if using sms.ini, then load the carriers from it
-        // otherwise, fall back to the default list of US carriers
-        $smsConfig = ConfigReader::getConfig('sms');
-        if (isset($smsConfig->Carriers) && count($smsConfig->Carriers) > 0) {
+        // If found, use carriers from SMS configuration; otherwise, fall back to the
+        // default list of US carriers.
+        if (isset($config->Carriers) && count($config->Carriers) > 0) {
             $this->carriers = array();
-            foreach ($smsConfig->Carriers as $id=>$settings) {
+            foreach ($config->Carriers as $id=>$settings) {
                 list($domain, $name) = explode(':', $settings, 2);
                 $this->carriers[$id] = array('name'=>$name, 'domain'=>$domain);
             }
         }
 
         // Load default "from" address:
-        $this->defaultFrom = isset($this->config->Site->email)
-            ? $this->config->Site->email : '';
+        $this->defaultFrom
+            = isset($options['defaultFrom']) ? $options['defaultFrom'] : '';
+
+        // Make sure mailer dependency has been injected:
+        if (!isset($options['mailer'])
+            || !($options['mailer'] instanceof \VuFind\Mailer)
+        ) {
+            throw new \Exception('$options["mailer"] must be a \VuFind\Mailer');
+        }
+        $this->mailer = $options['mailer'];
     }
 
     /**
@@ -105,8 +123,8 @@ class SMS extends \VuFind\Mailer
      * @param string $from     The email address to use as sender
      * @param string $message  The message to send
      *
-     * @throws MailException
-     * @return mixed           PEAR error on error, boolean true otherwise
+     * @throws \VuFind\Exception\Mail
+     * @return void
      */
     public function text($provider, $to, $from, $message)
     {
@@ -115,31 +133,10 @@ class SMS extends \VuFind\Mailer
             throw new MailException('Unknown Carrier');
         }
 
-        $badChars = array('-', '.', '(', ')', ' ');
-        $to = str_replace($badChars, '', $to);
-        $to = $to . '@' . $this->carriers[$provider]['domain'];
+        $to = $this->filterPhoneNumber($to)
+            . '@' . $this->carriers[$provider]['domain'];
         $from = empty($from) ? $this->defaultFrom : $from;
         $subject = '';
-        return $this->send($to, $from, $subject, $message);
-    }
-
-    /**
-     * Send a text message representing a record.
-     *
-     * @param string                                $provider Target SMS provider
-     * @param string                                $to       Recipient phone number
-     * @param \VuFind\RecordDriver\AbstractBase     $record   Record being emailed
-     * @param \Zend\View\Renderer\RendererInterface $view     View object (used to
-     * render email templates)
-     *
-     * @throws MailException
-     * @return void
-     */
-    public function textRecord($provider, $to, $record, $view)
-    {
-        $body = $view->partial(
-            'Email/record-sms.phtml', array('driver' => $record, 'to' => $to)
-        );
-        return $this->text($provider, $to, null, $body);
+        return $this->mailer->send($to, $from, $subject, $message);
     }
 }
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/SMS/SMSInterface.php b/module/VuFind/src/VuFind/SMS/SMSInterface.php
new file mode 100644
index 00000000000..c15910d3391
--- /dev/null
+++ b/module/VuFind/src/VuFind/SMS/SMSInterface.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Interface for SMS classes.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2009.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+namespace VuFind\SMS;
+
+/**
+ * Interface for SMS classes.
+ *
+ * @category VuFind2
+ * @package  SMS
+ * @author   Ronan McHugh <vufind-tech@lists.sourceforge.net>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/system_classes Wiki
+ */
+interface SMSInterface
+{
+    /**
+     * Get validation type for phone numbers
+     *
+     * @return string
+     */
+    public function getValidationType();
+
+    /**
+     * Get a list of carriers supported by the module.  Returned as an array of
+     * associative arrays indexed by carrier ID and containing "name" and "domain"
+     * keys.
+     *
+     * @return array
+     */
+    public function getCarriers();
+
+    /**
+     * Send a text message to the specified provider.
+     *
+     * @param string $provider The provider ID to send to
+     * @param string $to       The phone number at the provider
+     * @param string $from     The email address to use as sender
+     * @param string $message  The message to send
+     *
+     * @throws \VuFind\Exception\Mail
+     * @return void
+     */
+    public function text($provider, $to, $from, $message);
+}
diff --git a/themes/blueprint/templates/record/sms.phtml b/themes/blueprint/templates/record/sms.phtml
index 683c2c06cc8..1884747fc38 100644
--- a/themes/blueprint/templates/record/sms.phtml
+++ b/themes/blueprint/templates/record/sms.phtml
@@ -14,7 +14,13 @@
   <input id="sms_to" type="text" name="to" value="<?=isset($this->to) ? $this->to : $this->transEsc('sms_phone_number')?>" 
         onfocus="if (this.value=='<?=$this->transEsc('sms_phone_number')?>') this.value=''" 
         onblur="if (this.value=='') this.value='<?=$this->transEsc('sms_phone_number')?>'"
-        class="<?=$this->jqueryValidation(array('required'=>'This field is required', 'phoneUS'=>'Invalid phone number.'))?>"/>
+        class="<?
+            $options = array('required'=>'This field is required');
+            if ($this->validation == 'US') {
+                $options['phoneUS'] = 'Invalid phone number.';
+            }
+            echo $this->jqueryValidation($options);
+        ?>"/>
   <br/>
   <? if (is_array($this->carriers) && count($this->carriers) > 1): ?>
     <label class="span-2" for="sms_provider"><?=$this->transEsc('Provider')?>:</label>
-- 
GitLab