From 9c41ba3c9ebbb14d01abe961c420f71f9463e61a Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Thu, 19 Sep 2013 11:56:14 -0400
Subject: [PATCH] Allow sysadmins to define static responses which are immutable for the user

---
 skins/larry/templates/responseedit.html   |    2 
 program/steps/settings/responses.inc      |    8 ++-
 skins/larry/settings.css                  |    4 ++
 program/include/rcmail.php                |   15 +++++++
 skins/classic/settings.css                |    5 ++
 skins/classic/templates/responseedit.html |    2 
 program/steps/settings/edit_response.inc  |   19 ++++-----
 program/js/app.js                         |    2 
 config/defaults.inc.php                   |    6 +++
 9 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/config/defaults.inc.php b/config/defaults.inc.php
index 2a51b08..a5bf344 100644
--- a/config/defaults.inc.php
+++ b/config/defaults.inc.php
@@ -586,6 +586,12 @@
 // Setting it to 0, disables the feature.
 $config['undo_timeout'] = 0;
 
+// A static list of canned responses which are immutable for the user
+$config['compose_responses_static'] = array(
+//  array('name' => 'Canned Response 1', 'text' => 'Static Response One'),
+//  array('name' => 'Canned Response 2', 'text' => 'Static Response Two'),
+);
+
 // ----------------------------------
 // ADDRESSBOOK SETTINGS
 // ----------------------------------
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index f58235c..4a07e0b 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -351,11 +351,24 @@
    * These are stored in local config and user preferences.
    *
    * @param boolean True to sort the list alphabetically
+   * @param boolean True if only this user's responses shall be listed
    * @return array List of the current user's stored responses
    */
-  public function get_compose_responses($sorted = false)
+  public function get_compose_responses($sorted = false, $user_only = false)
   {
     $responses = array();
+
+    if (!$user_only) {
+      foreach ($this->config->get('compose_responses_static', array()) as $response) {
+        if (empty($response['key']))
+          $response['key'] = substr(md5($response['name']), 0, 16);
+        $response['static'] = true;
+        $response['class'] = 'readonly';
+        $k = $sorted ? '0000-' . strtolower($response['name']) : $response['key'];
+        $responses[$k] = $response;
+      }
+    }
+
     foreach ($this->config->get('compose_responses', array()) as $response) {
       if (empty($response['key']))
         $response['key'] = substr(md5($response['name']), 0, 16);
diff --git a/program/js/app.js b/program/js/app.js
index abe267a..5943ad0 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -447,7 +447,7 @@
           this.responses_list = new rcube_list_widget(this.gui_objects.responseslist, {multiselect:false, draggable:false, keyboard:false});
           this.responses_list.addEventListener('select', function(list){
             var win, id = list.get_single_selection();
-            p.enable_command('delete', !!id);
+            p.enable_command('delete', !!id && $.inArray(id, p.env.readonly_responses) < 0);
             if (id && (win = p.get_frame_window(p.env.contentframe))) {
               p.set_busy(true);
               p.location_href({ _action:'edit-response', _key:id, _framed:1 }, win);
diff --git a/program/steps/settings/edit_response.inc b/program/steps/settings/edit_response.inc
index 26f7e6e..4985677 100644
--- a/program/steps/settings/edit_response.inc
+++ b/program/steps/settings/edit_response.inc
@@ -24,8 +24,6 @@
 // edit-response
 if (($key = get_input_value('_key', RCUBE_INPUT_GPC))) {
     foreach ($responses as $i => $response) {
-        if (empty($response['key']))
-            $response['key'] = substr(md5($response['name']), 0, 16);
         if ($response['key'] == $key) {
             $RESPONSE_RECORD = $response;
             $RESPONSE_RECORD['index'] = $i;
@@ -35,12 +33,9 @@
 }
 
 // save response
-if ($RCMAIL->action == 'save-response' && isset($_POST['_name'])) {
+if ($RCMAIL->action == 'save-response' && isset($_POST['_name']) && !$RESPONSE_RECORD['static']) {
     $name = trim(get_input_value('_name', RCUBE_INPUT_POST));
     $text = trim(get_input_value('_text', RCUBE_INPUT_POST));
-
-    if (!empty($_REQUEST['_framed']))
-        $RCMAIL->output->framed = 1;
 
     if (!empty($name) && !empty($text)) {
         $dupes = 0;
@@ -62,9 +57,11 @@
             $responses[] = $response;
         }
 
-        if ($RCMAIL->user->save_prefs(array('compose_responses' => $responses))) {
+        $responses = array_filter($responses, function($item){ return empty($item['static']); });
+        if ($RCMAIL->user->save_prefs(array('compose_responses' => array_values($responses)))) {
             $RCMAIL->output->show_message('successfullysaved', 'confirmation');
-            $RCMAIL->output->command('update_response_row', $response, $key);
+            $RCMAIL->output->command('parent.update_response_row', $response, $key);
+            $RCMAIL->overwrite_action('edit-response');
             $RESPONSE_RECORD = $response;
         }
     }
@@ -79,6 +76,7 @@
     global $RCMAIL, $OUTPUT, $RESPONSE_RECORD;
 
     // Set form tags and hidden fields
+    $disabled = !empty($RESPONSE_RECORD['static']);
     $key = $RESPONSE_RECORD['key'];
     list($form_start, $form_end) = get_form_tags($attrib, 'save-response', $key, array('name' => '_key', 'value' => $key));
     unset($attrib['form'], $attrib['id']);
@@ -90,10 +88,10 @@
     $label = rcube_label('responsename');
 
     $table->add('title', html::label('ffname', Q(rcube_label('responsename'))));
-    $table->add(null, rcube_output::get_edit_field('name', $RESPONSE_RECORD['name'], array('id' => 'ffname', 'size' => $attrib['size']), 'text'));
+    $table->add(null, rcube_output::get_edit_field('name', $RESPONSE_RECORD['name'], array('id' => 'ffname', 'size' => $attrib['size'], 'disabled' => $disabled), 'text'));
 
     $table->add('title', html::label('fftext', Q(rcube_label('responsetext'))));
-    $table->add(null, rcube_output::get_edit_field('text', $RESPONSE_RECORD['text'], array('id' => 'fftext', 'size' => $attrib['textareacols'], 'rows' => $attrib['textarearows']), 'textarea'));
+    $table->add(null, rcube_output::get_edit_field('text', $RESPONSE_RECORD['text'], array('id' => 'fftext', 'size' => $attrib['textareacols'], 'rows' => $attrib['textarearows'], 'disabled' => $disabled), 'textarea'));
 
     $out .= $table->show($attrib);
     $out .= $form_end;
@@ -101,6 +99,7 @@
     return $out;
 }
 
+$OUTPUT->set_env('readonly', !empty($RESPONSE_RECORD['static']));
 $OUTPUT->add_handler('responseform', 'rcube_response_form');
 $OUTPUT->set_pagetitle(rcube_label(($RCMAIL->action=='add-response' ? 'savenewresponse' : 'editresponse')));
 
diff --git a/program/steps/settings/responses.inc b/program/steps/settings/responses.inc
index 330b4fd..cfc4148 100644
--- a/program/steps/settings/responses.inc
+++ b/program/steps/settings/responses.inc
@@ -26,7 +26,7 @@
 
     if (!empty($name) && !empty($text)) {
         $dupes = 0;
-        $responses = $RCMAIL->get_compose_responses();
+        $responses = $RCMAIL->get_compose_responses(false, true);
         foreach ($responses as $resp) {
             if (strcasecmp($name, preg_replace('/\s\(\d+\)$/', '', $resp['name'])) == 0)
                 $dupes++;
@@ -54,7 +54,7 @@
 
 if ($RCMAIL->action == 'delete-response') {
     if ($key = get_input_value('_key', RCUBE_INPUT_GPC)) {
-        $responses = $RCMAIL->get_compose_responses();
+        $responses = $RCMAIL->get_compose_responses(false, true);
         foreach ($responses as $i => $response) {
             if (empty($response['key']))
                 $response['key'] = substr(md5($response['name']), 0, 16);
@@ -67,7 +67,7 @@
     }
 
     if ($deleted) {
-        $RCMAIL->output->command('display_message', rcube_label('successfullydeleted'), 'confirmation');
+        $RCMAIL->output->command('display_message', rcube_label('deletedsuccessfully'), 'confirmation');
         $RCMAIL->output->command('remove_response', $key);
     }
 
@@ -99,6 +99,8 @@
 
     // set client env
     $OUTPUT->add_gui_object('responseslist', $attrib['id']);
+    $OUTPUT->set_env('readonly_responses', array_values(array_map(function($rec){ return $rec['key']; },
+      array_filter($plugin['list'], function($item){ return !empty($item['static']); }))));
 
     return $out;
 }
diff --git a/skins/classic/settings.css b/skins/classic/settings.css
index 0e4f796..acd0b9f 100644
--- a/skins/classic/settings.css
+++ b/skins/classic/settings.css
@@ -34,6 +34,11 @@
   height: 18px;
 }
 
+#identities-table tbody tr.readonly td
+{
+  font-style: italic;
+}
+
 #subscription-table tr.virtual td
 {
   color: #666;
diff --git a/skins/classic/templates/responseedit.html b/skins/classic/templates/responseedit.html
index fbc5f66..67ba35b 100644
--- a/skins/classic/templates/responseedit.html
+++ b/skins/classic/templates/responseedit.html
@@ -15,7 +15,7 @@
 
   <div id="formfooter">
     <div class="footerindent">
-      <roundcube:button command="save" type="input" class="button mainaction" label="save" />
+      <roundcube:button command="save" type="input" class="button mainaction" label="save" condition="!env:readonly" />
     </div>
   </div>
 </div>
diff --git a/skins/larry/settings.css b/skins/larry/settings.css
index 8deb247..920376a 100644
--- a/skins/larry/settings.css
+++ b/skins/larry/settings.css
@@ -194,6 +194,10 @@
 	text-overflow: ellipsis;
 }
 
+#identities-table tbody tr.readonly td {
+	font-style: italic;
+}
+
 #folder-details,
 #identity-details {
 	position: absolute;
diff --git a/skins/larry/templates/responseedit.html b/skins/larry/templates/responseedit.html
index d2f031b..8f180fe 100644
--- a/skins/larry/templates/responseedit.html
+++ b/skins/larry/templates/responseedit.html
@@ -13,7 +13,7 @@
 </div>
 
 <div class="footerleft formbuttons">
-	<roundcube:button command="save" type="input" class="button mainaction" label="save" />
+	<roundcube:button command="save" type="input" class="button mainaction" label="save" condition="!env:readonly" />
 </div>
 
 <roundcube:include file="/includes/footer.html" />

--
Gitblit v1.9.1