Extended the Locking plugin with cron specification fo locks.
authorNik Okuntseff <support@anuko.com>
Fri, 1 Apr 2016 16:56:58 +0000 (16:56 +0000)
committerNik Okuntseff <support@anuko.com>
Fri, 1 Apr 2016 16:56:58 +0000 (16:56 +0000)
WEB-INF/lib/ttTeamHelper.class.php
WEB-INF/lib/ttUser.class.php
WEB-INF/templates/footer.tpl
WEB-INF/templates/locking.tpl
dbinstall.php
locking.php
mysql.sql

index 1cf71d8..8cc9660 100644 (file)
@@ -723,6 +723,7 @@ class ttTeamHelper {
     $tracking_mode_part = '';
     $record_type_part = '';
     $plugins_part = '';
+    $lock_spec_part = '';
     
     if (isset($fields['address'])) $addr_part = ', address = '.$mdb2->quote($fields['address']);
     if (isset($fields['currency'])) $currency_part = ', currency = '.$mdb2->quote($fields['currency']);
@@ -735,9 +736,11 @@ class ttTeamHelper {
     if (isset($fields['tracking_mode'])) $tracking_mode_part = ', tracking_mode = '.intval($fields['tracking_mode']);
     if (isset($fields['record_type'])) $record_type_part = ', record_type = '.intval($fields['record_type']);
     if (isset($fields['plugins'])) $plugins_part = ', plugins = '.$mdb2->quote($fields['plugins']);
+    if (isset($fields['lock_spec'])) $lock_spec_part = ', lock_spec = '.$mdb2->quote($fields['lock_spec']);
 
     $sql = "update tt_teams set $name_part $addr_part $currency_part $locktime_part $lang_part $decimal_mark_part
-      $date_format_part $time_format_part $week_start_part $tracking_mode_part $record_type_part $plugins_part where id = $team_id";
+      $date_format_part $time_format_part $week_start_part $tracking_mode_part $record_type_part
+      $plugins_part $lock_spec_part where id = $team_id";
     $affected = $mdb2->exec($sql);
     
     if (is_a($affected, 'PEAR_Error')) {
index a14f7cd..a6731a4 100644 (file)
@@ -49,6 +49,7 @@ class ttUser {
   var $custom_logo = 0;     // Whether to use a custom logo for team.
   var $address = null;      // Address for invoices.
   var $lock_interval = 0;   // Lock interval in days for time records.
+  var $lock_spec = null;    // Cron specification for record locking.
   var $rights = 0;          // A mask of user rights.
 
   // Constructor.
@@ -61,7 +62,8 @@ class ttUser {
     $mdb2 = getConnection();
 
     $sql = "SELECT u.id, u.login, u.name, u.team_id, u.role, u.client_id, u.email, t.name as team_name, 
-      t.address, t.currency, t.locktime, t.lang, t.decimal_mark, t.date_format, t.time_format, t.week_start, t.tracking_mode, t.record_type, t.plugins, t.custom_logo
+      t.address, t.currency, t.locktime, t.lang, t.decimal_mark, t.date_format, t.time_format, t.week_start,
+      t.tracking_mode, t.record_type, t.plugins, t.lock_spec, t.custom_logo
       FROM tt_users u LEFT JOIN tt_teams t ON (u.team_id = t.id) WHERE ";
     if ($id)
       $sql .= "u.id = $id";
@@ -94,6 +96,7 @@ class ttUser {
       $this->address = $val['address'];
       $this->currency = $val['currency'];
       $this->plugins = $val['plugins'];
+      $this->lock_spec = $val['lock_spec'];
       $this->custom_logo = $val['custom_logo'];
       $this->lock_interval = $val['locktime'];
 
@@ -176,7 +179,9 @@ class ttUser {
   // isDateLocked checks whether a specifc date is locked for modifications.
   function isDateLocked($date)
   {
-    if ($this->isPluginEnabled('lk')) {
+    if ($this->isPluginEnabled('lk') && $this->lock_spec) {
+      // This is legacy code...
+      /*
       // Determine lock date. Entries earlier than lock date cannot be created or modified.
       $lockdate = 0;
       if ($this->lock_interval > 0) {
@@ -185,6 +190,18 @@ class ttUser {
       }
       if($lockdate && $date->before($lockdate))
         return true;
+      */
+
+      // New code with cron specification.
+      require_once(LIBRARY_DIR.'/tdcron/class.tdcron.php');
+      require_once(LIBRARY_DIR.'/tdcron/class.tdcron.entry.php');
+
+      // Calculate the last occurrence of a lock.
+      $last = tdCron::getLastOccurrence($this->lock_spec, mktime());
+      $lockdate = new DateAndTime(DB_DATEFORMAT, strftime('%Y-%m-%d', $last));
+      if ($date->before($lockdate)) {
+        return true;
+      }
     }
     return false;
   }
index d18884c..ab87a97 100644 (file)
@@ -12,7 +12,7 @@
       <br>
       <table cellspacing="0" cellpadding="4" width="100%" border="0">
         <tr>
-          <td align="center">&nbsp;Anuko Time Tracker 1.9.21.3467 | Copyright &copy; <a href="https://www.anuko.com/lp/tt_3.htm" target="_blank">Anuko</a> |
+          <td align="center">&nbsp;Anuko Time Tracker 1.9.22.3468 | Copyright &copy; <a href="https://www.anuko.com/lp/tt_3.htm" target="_blank">Anuko</a> |
             <a href="https://www.anuko.com/lp/tt_4.htm" target="_blank">{$i18n.footer.credits}</a> |
             <a href="https://www.anuko.com/lp/tt_5.htm" target="_blank">{$i18n.footer.license}</a> |
             <a href="https://www.anuko.com/lp/tt_7.htm" target="_blank">{$i18n.footer.improve}</a>
index 94e706a..177f591 100644 (file)
@@ -4,8 +4,8 @@
     <td>
       <table cellspacing="1" cellpadding="2" border="0">
         <tr>
-          <td align="right" nowrap>{$i18n.label.lock_interval}:</td>
-          <td>{$forms.lockingForm.lock_interval.control}</td>
+          <td align="right">{$i18n.label.cron_schedule}:</td>
+          <td>{$forms.lockingForm.lock_spec.control} <a href="https://www.anuko.com/lp/tt_6.htm" target="_blank">{$i18n.label.what_is_it}</a></td>
         </tr>
         <tr>
           <td colspan="2">&nbsp;</td>
index b6ddb1e..1429a24 100644 (file)
@@ -516,6 +516,7 @@ if ($_POST) {
     setChange("ALTER TABLE tt_invoices ADD COLUMN status tinyint(4) default '1'");
     setChange("DROP INDEX name_idx on tt_invoices");
     setChange("create unique index name_idx on tt_invoices(team_id, name, status)");
+    setChange("ALTER TABLE tt_teams ADD COLUMN lock_spec varchar(255) default NULL");
   }
 
   // The update_clients function updates projects field in tt_clients table.
index 09a7cf9..2383178 100644 (file)
@@ -36,22 +36,25 @@ if (!ttAccessCheck(right_manage_team)) {
   exit();
 }
 
-$cl_lock_interval = $request->isPost() ? $request->getParameter('lock_interval') : $user->lock_interval;
+$cl_lock_spec = $request->isPost() ? $request->getParameter('lock_spec') : $user->lock_spec;
 
 $form = new Form('lockingForm');
-$form->addInput(array('type'=>'text','maxlength'=>'10','name'=>'lock_interval','value'=>$cl_lock_interval));
+$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'lock_spec','style'=>'width: 250px;','value'=>$cl_lock_spec));
 $form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->getKey('button.save')));
 
 if ($request->isPost()) {
-  if ($cl_lock_interval == null || trim($cl_lock_interval) == '') $cl_lock_interval = 0;
+  // Validate user input.
+  if (!ttValidCronSpec($cl_lock_spec)) $err->add($i18n->getKey('error.field'), $i18n->getKey('label.cron_schedule'));
 
-  if (ttTeamHelper::update($user->team_id, array(
-    'name' => $user->team,
-    'locktime' => $cl_lock_interval))) {
-    header('Location: time.php');
-    exit();
-  } else {
-    $err->add($i18n->getKey('error.db'));
+  if ($err->no()) {
+    if (ttTeamHelper::update($user->team_id, array(
+      'name' => $user->team,
+      'lock_spec' => $cl_lock_spec))) {
+      header('Location: time.php');
+      exit();
+    } else {
+      $err->add($i18n->getKey('error.db'));
+    }
   }
 } // isPost
 
index e964ac7..5e66930 100644 (file)
--- a/mysql.sql
+++ b/mysql.sql
@@ -27,6 +27,8 @@ CREATE TABLE `tt_teams` (
   `tracking_mode` smallint(2) NOT NULL DEFAULT '1',      # tracking mode ("projects" or "projects and tasks")
   `record_type` smallint(2) NOT NULL DEFAULT '0',        # time record type ("start and finish", "duration", or both)
   `plugins` varchar(255) default NULL,                   # a list of enabled plugins for team
+  `lock_spec` varchar(255) default NULL,                 # Cron specification for record locking,
+                                                         # for example: "0 10 * * 1" for "weekly on Mon at 10:00".
   `custom_logo` tinyint(4) default '0',                  # whether to use a custom logo or not
   `status` tinyint(4) default '1',                       # team status
   PRIMARY KEY (`id`)