From f826189b4f962bd0277f56a70c578dc81476b4f7 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Fri, 21 Aug 2015 10:16:13 -0500
Subject: [PATCH] =?UTF-8?q?lock:=20Add=20option=20of=20old=20semantics=20?=
 =?UTF-8?q?=E2=80=94=20lock=20on=20view?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 include/ajax.config.php                |  2 +-
 include/ajax.tickets.php               |  2 +-
 include/class.config.php               |  6 ++++++
 include/class.lock.php                 |  4 ++++
 include/staff/settings-tickets.inc.php | 17 +++++++++++++++++
 include/staff/ticket-view.inc.php      |  2 ++
 scp/js/ticket.js                       | 22 +++++++++++++++-------
 7 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/include/ajax.config.php b/include/ajax.config.php
index 0bf0a4420..132da3daf 100644
--- a/include/ajax.config.php
+++ b/include/ajax.config.php
@@ -38,7 +38,7 @@ class ConfigAjaxAPI extends AjaxController {
         list($primary_sl, $primary_locale) = explode('_', $primary);
 
         $config=array(
-              'lock_time'       => ($cfg->getLockTime()*60),
+              'lock_time'       => $cfg->getTicketLockMode() == Lock::MODE_DISABLED ? 0 : ($cfg->getLockTime()*60),
               'html_thread'     => (bool) $cfg->isRichTextEnabled(),
               'date_format'     => $cfg->getDateFormat(true),
               'lang'            => $lang,
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 30a8b74d7..31457ec4f 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -92,7 +92,7 @@ class TicketsAjaxAPI extends AjaxController {
     function acquireLock($tid) {
         global $cfg, $thisstaff;
 
-        if(!$cfg || !$cfg->getLockTime())
+        if(!$cfg || !$cfg->getLockTime() || $cfg->getTicketLockMode() == Lock::MODE_DISABLED)
             Http::response(418, $this->encode(array('id'=>0, 'retry'=>false)));
 
         if(!$tid || !is_numeric($tid) || !$thisstaff)
diff --git a/include/class.config.php b/include/class.config.php
index 984a83c16..b3c75485c 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -176,6 +176,7 @@ class OsticketConfig extends Config {
         'verify_email_addrs' => 1,
         'client_avatar' => 'gravatar.mm',
         'agent_avatar' => 'gravatar.mm',
+        'ticket_lock' => 2, // Lock on activity
     );
 
     function OsticketConfig($section=null) {
@@ -424,6 +425,10 @@ class OsticketConfig extends Config {
         return $this->get('autolock_minutes');
     }
 
+    function getTicketLockMode() {
+        return $this->get('ticket_lock');
+    }
+
     function getAgentNameFormat() {
         return $this->get('agent_name_format');
     }
@@ -1204,6 +1209,7 @@ class OsticketConfig extends Config {
             'show_related_tickets'=>isset($vars['show_related_tickets'])?1:0,
             'hide_staff_name'=>isset($vars['hide_staff_name'])?1:0,
             'allow_client_updates'=>isset($vars['allow_client_updates'])?1:0,
+            'ticket_lock' => $vars['ticket_lock'],
         ));
     }
 
diff --git a/include/class.lock.php b/include/class.lock.php
index d1c5bc365..e5da2f048 100644
--- a/include/class.lock.php
+++ b/include/class.lock.php
@@ -38,6 +38,10 @@ class Lock extends VerySimpleModel {
         ),
     );
 
+    const MODE_DISABLED = 0;
+    const MODE_ON_VIEW = 1;
+    const MODE_ON_ACTIVITY = 2;
+
     function getId() {
         return $this->lock_id;
     }
diff --git a/include/staff/settings-tickets.inc.php b/include/staff/settings-tickets.inc.php
index 8edf21818..4fe241476 100644
--- a/include/staff/settings-tickets.inc.php
+++ b/include/staff/settings-tickets.inc.php
@@ -145,6 +145,23 @@ if(!($maxfileuploads=ini_get('max_file_uploads')))
                 <span class="error"><?php echo $errors['default_help_topic']; ?></span>
             </td>
         </tr>
+        <tr>
+            <td width="180"><?php echo __('Lock Semantics'); ?>:</td>
+            <td>
+                <select name="ticket_lock" <?php if ($cfg->getLockTime() == 0) echo 'disabled="disabled"'; ?>>
+<?php foreach (array(
+    Lock::MODE_DISABLED => __('Disabled'),
+    Lock::MODE_ON_VIEW => __('Lock on view'),
+    Lock::MODE_ON_ACTIVITY => __('Lock on activity'),
+) as $v => $desc) { ?>
+                <option value="<?php echo $v; ?>" <?php
+                    if ($config['ticket_lock'] == $v) echo 'selected="selected"';
+                    ?>><?php echo $desc; ?></option>
+<?php } ?>
+                </select>
+                <div class="error"><?php echo $errors['ticket_lock']; ?></div>
+            </td>
+        </tr>
         <tr>
             <td><?php echo __('Maximum <b>Open</b> Tickets');?>:</td>
             <td>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 6ec03ae89..156b2c323 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -16,6 +16,8 @@ $user  = $ticket->getOwner(); //Ticket User (EndUser)
 $team  = $ticket->getTeam();  //Assigned team.
 $sla   = $ticket->getSLA();
 $lock  = $ticket->getLock();  //Ticket lock obj
+if (!$lock && $cfg->getTicketLockMode() == Lock::MODE_ON_VIEW)
+    $lock = $ticket->acquireLock($thisstaff->getId());
 $mylock = ($lock && $lock->getStaffId() == $thisstaff->getId()) ? $lock : null;
 $id    = $ticket->getId();    //Ticket ID.
 
diff --git a/scp/js/ticket.js b/scp/js/ticket.js
index 61ba8c7b8..b16cc8ea3 100644
--- a/scp/js/ticket.js
+++ b/scp/js/ticket.js
@@ -20,30 +20,29 @@
     if (!this.$element.data('lockObjectId'))
       return;
     this.objectId = this.$element.data('lockObjectId');
-    this.lockId = options.lockId || this.$element.data('lockId') || undefined;
     this.fails = 0;
     this.disabled = false;
     getConfig().then(function(c) {
       if (c.lock_time)
-        this.setup();
+        this.setup(options.lockId || this.$element.data('lockId') || undefined);
     }.bind(this));
   }
 
   Lock.prototype = {
     constructor: Lock,
+    registry: [],
 
-    setup: function() {
+    setup: function(lockId) {
       // When something inside changes or is clicked which requires a lock,
       // attempt to fetch one (lazily)
       $(':input', this.$element).on('keyup, change', this.acquire.bind(this));
       $(':submit', this.$element).click(this.ensureLocked.bind(this));
-      $(document).on('pjax:start', this.shutdown.bind(this));
 
       // If lock already held, assume full time of lock remains, but warn
       // user about pending expiration
-      if (this.lockId) {
+      if (lockId) {
         getConfig().then(function(c) {
-          this.lockTimeout(c.lock_time - 20);
+          this.update({id: lockId, time: c.lock_time - 10});
         }.bind(this));
       }
     },
@@ -126,12 +125,20 @@
         type: 'POST',
         url: 'ajax.php/lock/{0}/release'.replace('{0}', this.lockId),
         data: 'delete',
-        async: false,
         cache: false,
+        success: this.clearAll.bind(this),
         complete: this.destroy.bind(this)
       });
     },
 
+    clearAll: function() {
+      // Clear all other current locks with the same ID as this
+      $.each(Lock.prototype.registry, function(i, l) {
+        if (l.lockId && l.lockId == this.lockId)
+          l.shutdown();
+      }.bind(this));
+    },
+
     shutdown: function() {
       clearTimeout(this.warning);
       clearTimeout(this.retryTimer);
@@ -159,6 +166,7 @@
         // Set up release on away navigation
         $(document).off('.exclusive');
         $(document).on('pjax:click.exclusive', $.proxy(this.release, this));
+        Lock.prototype.registry.push(this);
       }
 
       this.lockId = lock.id;
-- 
GitLab