php8
[web.mtrack] / MTrackWeb / Ticket.php
index 5de9e28..7170d20 100644 (file)
@@ -33,18 +33,24 @@ class MTrackWeb_Ticket extends MTrackWeb
         }
         $this->masterTemplate = 'ticket.html';
         $this->id = $pi ?  $pi: (isset($_GET['id']) ? $_GET['id'] : 0);
-         $this->id  = (int) $this->id;
-        
-    
-        // -- load issue..
+        $this->id  = (int) $this->id;
+        $this->loadIssue();
+        $this->initEditForm();
 
+    }
+    
+   function loadIssue( )
+   {
+     
+        // -- load issue.. we should share this code with ticketedit really..
+        //DB_DataObject::debugLevel(1);
         $this->issue = DB_DataObject::factory('mtrack_ticket');
-
+        $this->issue->autoJoin();
         if (!$this->id ||  !$this->issue->get($this->id)) {
             $this->jerr("no such ticket");
         }
         
-        if ($this->ticket->project_id != $this->currentProject()) {
+        if ($this->issue->project_id != $this->currentProject()) {
             $this->jerr("not in current project");
         }
         
@@ -62,15 +68,14 @@ class MTrackWeb_Ticket extends MTrackWeb
         if (!$this->id && !$this->hasPerm('MTrack.Issue','A')) {
             return HTML_FlexyFramework::run('Noperm');
         }
-        if ($this->id &&  (
-                !$this->hasPerm('MTrack.Issue','S')  
-            )) {
-            return HTML_FlexyFramework::run('Noperm');
+        
+        if ($this->id &&  (  !$this->hasPerm('MTrack.Issue','S')    )) {
+            $this->jerr('no permission');
         }
         
-         $this->editable = !$this->hasPerm('MTrack.Issue','E') ;
+        $this->editable = !$this->hasPerm('MTrack.Issue','E') ;
          
-        $this->issue->milestoneURL = $this->baseURL.'/Milestone'; // fix me later..
+        //$this->issue->milestoneURL = $this->baseURL.'/Milestone'; // fix me later..
     
         $this->showEditBar = false;
          
@@ -78,249 +83,177 @@ class MTrackWeb_Ticket extends MTrackWeb
             $this->showEditBar = true;
         }
          
-        $this->initEditForm();
+        $this->issue->images = $this->issue->images();
         
       
     }
    
-    function post($pi=0) // handle the post...
+    function post() // handle the post...
     {
-        die("TODO");
-       $this->get($pi);
-       
-        if (isset($_POST['cancel'])) {
-            header("Location: {$$this->baseURL}/Ticket/$this->issue->nsident");
-            exit;
-          }
-          
-          if (!MTrack_Captcha::check('ticket')) {
-            $this->error[] = "CAPTCHA failed, please try again";
-          }
-          $this->preview = isset($_POST['preview']) ? true : false;
-
-          $comment = '';
-          try {
-            if (!$this->id) {
-              MTrackACL::requireAllRights("Tickets", 'create');
-            } else {
-              MTrackACL::requireAllRights("ticket:" . $this->issue->tid, 'modify');
-            }
-          } catch (Exception $e) {
-            $this->error[] = $e->getMessage();
-          }
-          
-          if (!$this->id) {
-            $comment = empty($_POST['comment']) ? '' : $_POST['comment'];
-          }
+        
+        $this->id = empty($_POST['id']) ? 0 : $_POST['id'];
+        $this->loadIssue();
+        $old = clone($this->issue);
+         
+        //  $this->preview = isset($_POST['preview']) ? true : false;
+        if (!$this->hasPerm('MTrack.Issue','E') ) {
+            $this->jerr("permission denied");
+        }
           
-          if (!strlen($comment)) {
-            $comment = $_POST['summary'];
-          }
-          try {
-            $CS = MTrackChangeset::begin("ticket:X", $comment);
-          } catch (Exception $e) {
-            $this->error[] = $e->getMessage();
-            $CS = null;
-          }
-          if (!$this->id) {
-            // compute next id number.
-            // We don't use auto-number, because we allow for importing multiple
-            // projects with their own ticket sequence.
-            // During "normal" user-driven operation, we do want plain old id numbers
-            // so we compute it here, under a transaction
-            $db = MTrackDB::get();
-            
-            
-            
-            switch($db->getAttribute(PDO::ATTR_DRIVER_NAME)) {
-                case 'pgsql':
-                    // Some versions of postgres don't like that we have "abc123" for
-                    // identifiers, so match on the bigest number nsident fields only
-                    $max = "select max(cast(nsident as integer)) + 1 from tickets where nsident ~ '^\\\\d+$'";
-                    break;
-                
-                case 'mysql':
-                    $max = "select max(cast(nsident as UNSIGNED)) + 1 from tickets";
-                    break;
-                
-                default:
-                    $max = 'select max(cast(nsident as integer)) + 1 from tickets';   
-                    break;
-            }
-            
-            
-             
-            list($this->issue->nsident) = MTrackDB::q($max)->fetchAll(PDO::FETCH_COLUMN, 0);
-            if ($this->issue->nsident === null) {
-              $this->issue->nsident = 1;
-            }
-          }
+           
+        $comment = empty($_POST['comment']) ? '' : $_POST['comment'];
+         
+        
+        //    $CS = MTrackChangeset::begin("ticket:X", $comment);
+           
 
-          if (isset($_POST['action']) && !$this->preview) {
-            $act= explode('_', $_POST['action'] , 2);
+        $act= explode('_', $_POST['status'] , 2);
             //var_dump($act);exit;
-            switch ($act[0]) {
-              case 'leave':
-                break;
-              case 'reopen':
-                $this->issue->reOpen();
-                break;
-              case 'fixed':
-                $this->issue->resolution = 'fixed';
-                $this->issue->close();
-                $_POST['estimated'] = $this->issue->estimated;
-                break;
+            // input type='radio' id='none' name='status' value='{issue.status}' checked='checked'> 
+            //   <label for='accept'>Assign this ticket to <b style="color:red">ME</b></label><br>
+            // <input type='radio' id='ticketstate_{cid}' name='status' value='change_{cid}' flexy:ignore="yes"> 
+            //           <input type='radio' id='resolution_{cid}' name='status' value='resolution_{cid}'  flexy:ignore="yes"> 
+               
+        switch ($act[0]) {
+          
                 
               
-              case 'accept':
+            case 'accept':
                 // will be applied to the issue further down
-                $_POST['owner'] = MTrackAuth::whoami();
-                if ($this->issue->status == 'new') {
-                  $this->issue->status = 'open';
+                $this->issue->owner_id = $this->authUser->id;
+                if ($this->issue->status_name == 'new') {
+                    $d = DB_DataObject::factory('core_enum');
+                    $d->etype = 'ticketstate';
+                    $d->name = 'open'; // assigned?
+                    $d->find(true); 
+                    $this->issue->status = $d->id;
                 }
                 break;
                 
                 
-              case 'resolve':
+              case 'resolution':
                 //$this->issue->resolution = $_POST['resolution'];
-                $this->issue->resolution = $act[1];
-                $this->issue->close();
-                $_POST['estimated'] = $this->issue->estimated;
+                $this->issue->resolution_id = $act[1];
+                $d = DB_DataObject::factory('core_enum');
+                $d->etype = 'ticketstate';
+                $d->name = 'closed'; // assigned?
+                $d->find(true);
+                $this->issue->status = $d->id;
+                //$this->issue->close();
+                //$_POST['estimated'] = $this->issue->estimated;
                 break;  
                 
-              case 'change':
+            case 'change':
                 $this->issue->status = $act[1];
                 break;
+            
+            // default leave - stays tehe same..
+        }
+        
+        // things that we should not allow..
+        foreach(array(
+            'estimated', 'effort', 'owner_id',
+        ) as $k) {
+            if (isset($_POST[$k])) {
+                $this->issue->setFrom(array($k => $_POST[$k]));
             }
-          }
-
-          $fields = array(
-            'summary',
-            'description',
-            'classification',
-            'priority',
-            'severity',
-            'changelog',
-            'owner',
-            'cc',
-          );
-
-          $this->issue->applyPOSTData($_POST);
-
+        }
          
-          
-          foreach ($fields as $fieldname) {
-            if (isset($_POST[$fieldname]) && strlen($_POST[$fieldname])) {
-              $this->issue->$fieldname = $_POST[$fieldname];
-            } else {
-              $this->issue->$fieldname = null;
-            }
-          }
-
-          $kw = $this->issue->getKeywords();
-          $kill = array_values($kw);
-          foreach (preg_split('/[ \t,]+/', $_POST['keywords']) as $w) {
-            if (!strlen($w)) {
-              continue;
-            }
-            $x = array_search($w, $kw);
-            if ($x === false) {
-              $k = MTrackKeyword::loadByWord($w);
-              if ($k === null) {
-                $k = new MTrackKeyword;
-                $k->keyword = $w;
-                $k->save($CS);
-              }
-              $this->issue->assocKeyword($k);
-            } else {
-              $w = array_search($w, $kill);
-              if ($w !== false) {
-                unset($kill[$w]);
-              }
-            }
-          }
-          foreach ($kill as $w) {
-            $this->issue->dissocKeyword($w);
-          }
-
-          $ms = $this->issue->getMilestones();
-          $kill = $ms;
-          if (isset($_POST['milestone']) && is_array($_POST['milestone'])) {
-            foreach ($_POST['milestone'] as $mid) {
-              $this->issue->assocMilestone($mid);
-              unset($kill[$mid]);
-            }
-          }
-          foreach ($kill as $mid) {
-            $this->issue->dissocMilestone($mid);
-          }
-
-          $ms = $this->issue->getComponents();
-          $kill = $ms;
-          if (isset($_POST['component']) && is_array($_POST['component'])) {
-            foreach ($_POST['component'] as $mid) {
-              $this->issue->assocComponent($mid);
-              unset($kill[$mid]);
-            }
-          }
-          foreach ($kill as $mid) {
-            $this->issue->dissocComponent($mid);
-          }
-          
-            if (!empty($_POST['comment'])) {
-               $this->issue->addComment($_POST['comment']);
-            }
-          
-          $this->issue->addEffort(
-            empty($_POST['spent']) ? 0 : $_POST['spent'], 
-            empty($_POST['estimate']) ? 0 : $_POST['estimate']
-        );
-
-          if (!count($this->error)) {
-            try {
-              $this->issue->save($CS);
-              
-              // make sure everyone is watching it!!!!
-                if($this->issue->owner && $this->issue->tid) {
-                  // make sure owner is tracking it...
-                    MTrackWatch::watch_object('ticket', $this->issue->tid,  $this->issue->owner);
-                }
+        //  $this->issue->addEffort(
+        //    empty($_POST['spent']) ? 0 : $_POST['spent'], 
+        //    empty($_POST['estimate']) ? 0 : $_POST['estimate']
+        //);
+        
+        // we should really use begin/commit to determin if something has changed..
+        // and produce an error..
+        
+        
+        $CS = DB_DataObject::factory('mtrack_change');
+        $CS->begin($this->issue, empty($_POST['comment']) ? '' : $_POST['comment']);
+            
+        
+        //if (!empty($_POST['comment'])) {
+            // create a comment CS..
+            
+        //}
+        $CS->add($this->issue, $old);
+        $this->issue->updated = $CS->id;
+        $this->issue->update($old);
+        
+        
+        
+        
+        if (!empty($_FILES['attachments'])) {
+            foreach ($_FILES['attachments']['name'] as $fileid => $name) {
+                $i = DB_DataObject::factory('Images');
+                $i->object($this->issue);
+                $i->ontable = $this->issue->tableName();
+                $i->onid = $this->issue->id;
+                $i->created_by = $this->authUser->id;
+                $i->mimetype = $_FILES['attachments']["type"][$fileid];
+                $i->createFrom($_FILES['attachments']['tmp_name'][$fileid],$_FILES['attachments']['name'][$fileid]);
                 
-                if ($this->id == 'new') {
-                    MTrackWatch::watch_object('ticket', $this->issue->tid,  MTrackAuth::whoami());
-                }
-              
-              
-              $CS->setObject("ticket:" . $this->issue->tid);
-            } catch (Exception $e) {
-              $this->error[] = $e->getMessage();
-            }
-        }
-
-        if (!count($this->error)) {
-            if (!empty($_FILES['attachments'])) {
-                require_once 'MTrack/Attachment.php';
-                foreach ($_FILES['attachments']['name'] as $fileid => $name) {
-                      
-                    MTrackAttachment::add("ticket:{$this->issue->tid}",
-                        $_FILES['attachments']['tmp_name'][$fileid],
-                        $_FILES['attachments']['name'][$fileid],
-                        $CS
-                    );
-                }
+                //    MTrackAttachment::add("ticket:{$this->issue->tid}",
+                //        $_FILES['attachments']['tmp_name'][$fileid],
+                //        $_FILES['attachments']['name'][$fileid],
+                //        $CS
+                //    );
+                //}
             }
         }
+        /*
         if (!count($this->error) && $this->id != 'new') {
             require_once 'MTrack/Attachment.php';
             MTrackAttachment::process_delete("ticket:{$this->issue->tid}", $CS);
-        }
-
-        if (isset($_POST['apply']) && !count($this->error)) {
-          $CS->commit();
-          header("Location: {$this->baseURL}/Ticket/{$this->issue->nsident}");
-          exit;
-        }
+        } 
+        */
+        
+        
+        
+        
+        
+        $notify_query = "
+                (ontable='mtrack_ticket' and onid = {$this->issue->id})
+                 OR
+                 (ontable='Projects' and onid = {$this->issue->project_id})
+                 ";
+         $w = DB_DataObject::factory('core_watch');
+        $w->ensureNotify(  'mtrack_ticket' ,
+                            $this->issue->id,
+                            $this->authUser->id,
+                        $notify_query
+            );
+        
+        $w->ensureNotify(  'mtrack_ticket' ,
+                            $this->issue->id,
+                            $this->issue->owner_id,
+                        $notify_query
+            );
+        
+         $w->ensureNotify(  'mtrack_ticket' ,
+                            $this->issue->id,
+                            $this->issue->developer_id,
+                        $notify_query
+            );
+        //DB_DataObject::debugLevel(1);
+        // who to notify..
+        // who to notify.. -- originall did not send to issuer..
+        // we should probably make this configurable..
+        $w->notify( 'mtrack_ticket' , $this->issue->id,
+                    $notify_query 
+                /* " ( $notify_query )
+                    AND
+                    (person_id != {$this->authUser->id})   "   */
+        );
+        
+        
+        
+        // if the owner has changed.. then we should add them to the watch list...
+        // MTrackWatch::watch_object('ticket', $this->issue->tid,  $this->issue->owner);
+        
+        $this->jok("OK");
+        
     }
       
          
@@ -331,102 +264,57 @@ class MTrackWeb_Ticket extends MTrackWeb
         $this->elements = array();
         
         
-        
-        foreach(array( 'classification', 'priority', 'severity', 'resolution' ) as $c)  {
-            $d = DB_DataObject::factory('core_enum');
-            $d->etype = $c;
-            $d->orderBy('seqid ASC, name ASC');
-            if (!$d->count()) {
-                $d->createBaseEntries();
-                
-            }
-            $this->elements[$c] = new HTML_Template_Flexy_Element('select');
-            $this->elements[$c]->setOptions($d->fetchAll('id','name'));
-            
-        }
-        
-        if ($this->issue->project_id) {
-            $d = DB_DataObject::factory('mtrack_project_component');
-            $d->project_id = $this->issue->project_id;
-            $d->orderBy('name');
-            $d->whereAdd('deleted != 1');
-            $this->elements['component[]'] = new HTML_Template_Flexy_Element('select');
-            $this->elements['component[]']->setOptions($d->fetchAll('id', 'name'));
-            $ar = $this->issue->components();
-            $this->elements['component[]']->setValue(array_keys($ar));
-        
-        }
-        if ($this->issue->project_id) {
-            $d = DB_DataObject::factory('mtrack_milestone');
-            $d->project_id = $this->issue->project_id;
-            $d->orderBy('(case when duedate is null then 1 else 0 end), duedate, name');
-            $d->whereAdd('completed != 1');
-            $d->whereAdd('deleted != 1');
-            $this->elements['milestone[]'] = new HTML_Template_Flexy_Element('select');
-            $this->elements['milestone[]']->setOptions($d->fetchAll('id', 'name'));
-            $ar = $this->issue->milestones();
-            $this->elements['milestone[]']->setValue(array_keys($ar));
-        }
-        
+         
         // FIX ME - need to determine who the owner is..
         // for a new issue it's the person who created it.
         // later on it's an assignement???
+      //  DB_DataObject::debugLevel(1);
+        $pd = DB_DataObject::factory('ProjectDirectory');
+        $pd->project_id = $this->currentProject();
+        $pd->whereAdd("ProjectDirectory.role != ''");
+        $pd->joinAdd(DB_DataObject::factory('core_person'), 'LEFT');
+        $pd->selectAdd();
+        $pd->selectAdd("distinct(Person.id) as id ,  CONCAT(Person.name , '<', Person.email , '>') as name");
+        $pd->groupBy('Person.id, Person.name');
+        $pd->orderBy('Person.name');
+        $users = $pd->fetchAll('id', 'name');
+        
         
-        $users = array();
+        //$users = array();
          
-        $this->elements['owner'] = new HTML_Template_Flexy_Element('select');
-        $this->elements['owner']->setOptions($users);
+        $this->elements['owner_id'] = new HTML_Template_Flexy_Element('select');
+        $this->elements['owner_id']->setOptions($users);
         
         
         
         // keywords -- in toArray...
         // milestone 
           
-          
-          $this->change_status = array();
-          $this->resolve_status = array();
-          if ($this->id) {
-         
-            // for coder's they can only change this ticke to certian states
-            
-            //print_r($groups);
-            // Nasty - I really do not like the acl code in this ...
-            require_once 'MTrack/TicketState.php';
+    
+    
+        foreach(array(  'resolution', 'ticketstate' ) as $c)  {
+            $d = DB_DataObject::factory('core_enum');
+            $d->etype = $c;
+            $d->orderBy('seqid ASC, name ASC');
+            if (!$d->count()) {
+                $d->createBaseEntries();
+                
+            }
+            $this->{$c} =  $d->fetchAll('id','name');
             
-            $ST = new MTrackTicketState;
-            $ST = $ST->enumerate();
-            //print_r($ST);
-            unset($ST['closed']);
-            unset($ST[$this->issue->status]);
+        }
+        
+    
            
-            $this->change_status = empty($ST) ? array() : array_keys($ST);
-            
-            $ac = MTrackAuth::getUserClass($this->authUser->userid);
-            //var_dump($ac);exit;
-// KLUDGE! - remove later...
-            if ($ac == 'admin') {
-                
-                $this->resolve_status= array('fixed');
-                $R = new MTrackResolution;
-                $resolutions = $R->enumerate();
-                unset($resolutions['fixed']);
-                
-                $this->resolve_status= array_keys($resolutions);
-                array_unshift($this->resolve_status, 'fixed');
-               // $html .= $this->mtrack_chg_status('action', 'resolve', 'Resolve as:', 'resolution', $resolutions, $this->issue );
-            } 
-
-           // } else {
-           //   $html .= mtrack_radio('action', 'reopen', $_POST['action']);
-           //   $html .= " <label for='reopen'>Reopen ticket</label><br>\n";
-           // }
+        //    unset($ST['closed']);
+        //    unset($ST[$this->issue->status]);
            
-        }
-        $this->elements = HTML_Template_Flexy_Factory::fromArray($this->issue->toArray(), $this->elements);
-        if (!empty($_POST)) {
-            $this->elements = HTML_Template_Flexy_Factory::fromArray($_POST, $this->elements);
-        }
+        //    $this->change_status = empty($ST) ? array() : array_keys($ST);
         
+        // admin can only change to 'fixed'?
+             
+        $this->elements = HTML_Template_Flexy_Factory::fromArray($this->issue->toArray(), $this->elements);