php8
[web.mtrack] / MTrackWeb / Browse.php
index fa95247..e8ce02b 100644 (file)
@@ -40,6 +40,11 @@ class MTrackWeb_Browse extends MTrackWeb
   
     var $up = '';
     var $jump = '';
+    var $pi;
+    var $basename;
+    var $crumbs;
+    var $dirname;
+    var $repos;
     
     function getAuth() 
     {
@@ -49,12 +54,12 @@ class MTrackWeb_Browse extends MTrackWeb
   
     }
  
-    function get($pi)
+    function get($pi='', $args = array())
     {
-         $this->pi =  $pi . (strlen($pi) ? $this->bootLoader->ext : '');
+        $this->pi =  $pi . (strlen($pi) ? $this->bootLoader->ext : '');
        
         if (!isset($_REQUEST['ajax_body'])) {
-            $this->title =  $this->pi;
+            $this->title = "Browse: " . $this->pi;
             return;
         }
         $this->masterTemplate = 'tree.html';
@@ -68,6 +73,11 @@ class MTrackWeb_Browse extends MTrackWeb
         if (!$this->repo->id) {
             $this->repo = false;
         }
+        // if we have an active project.. enforce it..
+        if ($this->currentProject() && $this->repo &&  $this->repo->project_id != $this->currentProject()) {
+            $this->repo =  false; // no repo..
+        }
+        
         
         $this->object = null;
         $this->ident = null;
@@ -103,10 +113,9 @@ class MTrackWeb_Browse extends MTrackWeb
 
         $this->basename  = basename($file);
         $location = '';
-        $crumbs = explode('/', dirname($file));
-        if (strlen($file)) {
-            array_unshift($crumbs, ''); // add empty at front..
-        }
+        $crumbs = !strlen($file) || dirname($file) == '.' || !strlen(dirname($file)) ? array() :
+            explode('/', dirname($file));
+        
         
         $this->crumbs = array();
         
@@ -118,7 +127,7 @@ class MTrackWeb_Browse extends MTrackWeb
         {
              
             $c = new StdClass;
-            $c->name = strlen($path) ? $path : '[root]';
+            $c->name =   $path ;
             $location .=  strlen($location) ? '/' : '';
             $location .=  strlen($path)  ?  urlencode($path)  : '';
             $c->location = $location;
@@ -254,6 +263,10 @@ class MTrackWeb_Browse extends MTrackWeb
         } else {
             $do->orderBy("shortname ASC");
         }
+        
+        if ($this->currentProject()) {
+            $do->project_id = $this->currentProject();
+        }
 // FIXME -> permissions on repositories goes here.. 
         //$do->ensurePerm($this->authUser); 
         //$do->fetchAll();
@@ -277,7 +290,7 @@ class MTrackWeb_Browse extends MTrackWeb
 
 
 // static..?
-    function getBrowseData($repo, $pi, $object, $ident)
+    function getBrowseData($repo, $pi, $object, $ident, $hashes = false)
     {
          $data = new StdClass;
         $data->dirs = array();
@@ -305,17 +318,24 @@ class MTrackWeb_Browse extends MTrackWeb
         }
         $files = array();
         $dirs = array();
-       
+        
+        $needLog = array();
         if ($repo) {
             //try {
-                $ents = $repo->readdir($pi, $object, $ident);
-            //} catch (Exception $e) {
-                  // Typically a freshly created repo
-              //    $ents = array();
-                //  $data->err = $e->getMessage();
-            //}
-           // echo '<PRE>' ; var_dump($ents); echo '</PRE>' ;
+            $ents = $repo->readdir($pi, $object, $ident);
+            if ($hashes === false) { 
+                $ents = $this->cachedChangeEvent($ents);
+            } else {
+                // we are filling the cache..
+                return $this->cachedChangeEventFill($ents, $hashes);
+                 
+            }
+            
             foreach ($ents as $file) {
+                if (isset($file->hash)) {
+                    $needLog[] = $file->hash;
+                }
+                
                 $basename = basename($file->name);
                 if ($file->is_dir) {
                     $dirs[$basename] = $file;
@@ -327,38 +347,152 @@ class MTrackWeb_Browse extends MTrackWeb
         uksort($files, 'strnatcmp');
         uksort($dirs, 'strnatcmp');
 
-        $data->files = array();
-        $data->dirs = array();
-
-        //$urlbase    = $this->baseURL . '/browse.php';
-        //$pathbase   = '/' . $repo->getBrowseRootName();
+         
+        $data->dirs  = array_values($dirs);
+        $data->files = array_values($files);
         
-        foreach ($dirs as $basename => $file) {
-            
-            $ent = $file->getChangeEvent(); //MTrackSCMEvent
-            // let's copy extra stuff into the event..
-            //$ent->url = $urlbase . $pathbase . '/' . $file->name;
-            $ent->basename = $basename;
-            $ent->changelogOne = $ent->changelogOneToHtml();
+        $this->repopath = $this->repo->displayName();
+        $this->needLog = $needLog;
+        // gather list 
+        
+        return $data;
+    }
+    /**
+     * New version of Directory listing
+     * Basically fetching the last change is very slow...
+     *  - 1st run through -> fetch all the change events that we have
+     *  for ones we do not have, fetch them later..
+     *
+     */
+    function cachedChangeEvent($ar)
+    {
+        // fetch a list of hashes...
+        // build a map...
+        $map = array();
+        foreach($ar as $e) {
+            $e->basename = basename($e->name);
+            // remove e->rev as it's not valid..
+            $e->rev = false;
+            $map[$e->hash] = $e;
             
-            $data->dirs[] = $ent;
         }
         
-        foreach ($files as $basename => $file) {
-            $ent = $file->getChangeEvent();
-            if (!$ent) { // skips broken files..
+        $q = DB_DataObject::factory('mtrack_clcache');
+        $q->whereAddIn('rev', array_keys($map), 'string');
+        $q->repo_id = $this->repo->id;
+        $revs = $q->fetchAll('rev', 'sobject');
+        $impl = $this->repo->impl();
+        
+        foreach($revs as $hash => $sobject) {
+            $event = $impl->commitLogToEvent($sobject);
+            // add something??? 
+            if (!$event) {
                 continue;
             }
-            // needed?
-            $ent->basename = $basename;
+            $event->is_dir = $map[$hash]->is_dir;
+            $event->name = $map[$hash]->name;
+            $event->basename = $map[$hash]->basename;
+        
+            $map[$hash] =  $event; // this was previous only done for directories??? why???
+        }
+        return array_values($map);
+    }
+    
+    function cachedChangeEventFill($ar,$hashes)
+    {
+        $map = array();
+        $impl = $this->repo->impl();
+                
+        foreach($ar as $e) {
+            if (!in_array($e->hash,$hashes)) {
+                continue;
+            }
+            
+            // there is a small chance that concurrent users are looking for the same info..
+            $q = DB_DataObject::factory('mtrack_clcache');
+            $q->rev = $e->hash;
+            $q->repo_id = $this->repo->id;
+            
+            if ($q->find(true)) {
+                $event = $impl->commitLogToEvent($q->sobject);
+            } else { 
+                $ent = $this->repo->history($e->name, 1, 'rev', $e->rev);
+                
+                
+                if (!$ent) {
+                    continue;
+                }
+                $event = $ent[0];
+                // cache it..
+                $q = DB_DataObject::factory('mtrack_clcache');
+                $q->rev = $e->hash;
+                $q->repo_id = $this->repo->id;
+                $q->sobject = $event->commit;
+                $q->insert();
+            }
+            
+            // only copy a few essentials from ent, as we will send it back via json.
+            // these all need escaoing..
+            $add = new stdClass;
+            $add->changelog = $event->changelogOneToHtml($this->link);
+            $add->age = $event->ctimeToHtml($this->link);
+            $add->basename = basename($e->name);
+            $add->changeby = htmlspecialchars($event->changeby); 
+            $add->rev = '<a class="changesetlink browse-link"  href="'. 
+                        htmlspecialchars($this->baseURL) .
+                        '/Changeset/' .
+                        htmlspecialchars($this->repo->displayName()). 
+                        '/'.
+                        htmlspecialchars($event->rev) .
+                        '">'.
+                        htmlspecialchars($event->rev) .
+                        '</a>';
+            
+            $map[$e->hash] = $add;
+            
             
-            $data->files[] = $ent;
         }
-
-        return $data;
+        return $map;
+        
+        
+    
+    }
+    function post($pi)
+    {
+        $this->pi =  $pi . (strlen($pi) ? $this->bootLoader->ext : '');
+       
+         
+         
+        $this->repo = DB_DataObject::factory('mtrack_repos');
+        $file = $this->repo->loadFromPath($this->pi);
+        if (!$this->repo->id) {
+            $this->jerr("INVALID URL");
+        }
+        
+        $this->object = null;
+        $this->ident = null;
+        
+        if (isset($_GET['jump']) && strlen($_GET['jump'])) {
+            list($this->object, $this->ident) = explode(':', $_GET['jump'], 2);
+        }
+        
+        if (!$this->repo) {
+            $this->jerr("INVALID URL");
+        }
+        if (!$this->projectPerm($this->repo->project_id, 'MTrack.Repos', 'S')) {
+            $this->jerr("INVALID URL");
+        }
+        if (empty($_POST['hashes'])) {
+            $this->jerr("INVALID URL");
+        }
+        
+        $ar =  $this->getBrowseData($this->repo, $file, $this->object, $this->ident, explode(',', $_POST['hashes']));
+        $this->jdata($ar);
+        exit;
+        
+        
     }
     
-     
     
 }