php8
[web.mtrack] / MTrackWeb.php
index 4012258..03e3c3c 100644 (file)
@@ -10,15 +10,195 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     var $priorities = array();
     var $severities = array();
     var $link = false; // the link handler..
+    var $authUser;
+    var $currentProject;
     
     function hasPerm($what, $cando) {
-        throw new Exception ("not supported yet");
-        return MTrackACL::hasAnyRights($what, $cando);
+        // our whole perm logic sits in here....
+        
+        // here's how it works
+        // a) anonymous users - not authenticated.
+        // - can see projects that are in *PUBLIC project "MTrack.Repos", "S"
+        // - can see bugs that are in *PUBLIC project "MTrack.Issue", "S"
+        // - can see bugs that are in *PUBLIC project "MTrack.Wiki", "S"
+        if (!$this->authUser) {
+            if ($cando == 'S' &&
+                    in_array( $what , array( 'MTrack.Repos', 'MTrack.Issue', 'MTrack.Wiki'))) {
+                
+                return true; // not a diffinative answer...
+            }
+            return false;
+        }
+        
+        return $this->authUser->hasPerm($what, $cando); 
+    }
+    
+    function projectPerm($project_id, $what, $cando)
+    {
+        if (!$project_id) {
+            return false;
+        }
+        $p = DB_DataObject::factory('core_project');
+        $p->get($project_id);
+        if (!$this->authUser) {
+            if ($p->code != '*PUBLIC') {
+                return false; // only public projects
+            }
+            if ($cando != 'S') {
+                return false;
+            }
+            // all permissions to view public stuff.
+            return true;
+        }
+        if (!$this->authUser->hasPerm($what, $cando)) {
+            echo "NO PERMS $what $cando";
+            echo '<PRE>'; print_r($this->authUser->getPerms());
+            return false;
+        }
+        // membership rules?
+        //echo "COMPTYPE " . $this->authUser->company()->comptype ;
+        if ($this->authUser->company()->comptype == 'OWNER') {
+                
+            if ($this->authUser->hasPerm('Core.Projects_All', $cando)) { // they can do what they like on all projects.
+               return true;
+            }
+           // return $p->hasPerm($what, $cando);
+        }
+        // otherwise they have to be a team member of that project.
+        
+        $pd = DB_DataObject::factory('ProjectDirectory');
+        $pd->project_id = $project_id;
+        $pd->user_id = $this->authUser->id;
+        $pd->whereAdd("role != ''");
+        
+        if (!$pd->count()) {
+            return false;
+        }
+        return true;
+         
+    }
+    /**
+     * currentProject:
+     *
+     * @param {int} $val set the current project (optional)
+     * @return {int} The current project id.
+     * 
+     * 
+     *
+     */
+    
+    
+    function currentProject($val = false)
+    {
+        // we do need the option for me to look at all projects...
+        
+        
+        static $currentProject = false;
+        if (empty($_SESSION[__CLASS__])) {
+            $_SESSION[__CLASS__] = array();
+        }
+        
+        if (isset($_SESSION[__CLASS__]['active_project_id'])) {
+            $currentProject = $_SESSION[__CLASS__]['active_project_id']; 
+        }
+        
+        if ($val !== false) {
+            // attempt to set it..
+            $_SESSION[__CLASS__]['active_project_id'] = $val ;
+            $currentProject = $val ; 
+            // reset to ensure not cached..
+        }
+        
+        
+        
+        
+        $ar = $this->userProjects();
+         
+        if (!isset($ar[$currentProject])) {
+            $currentProject = false;
+            $_SESSION[__CLASS__]['active_project_id'] = false;
+        }
+        if ($currentProject !== false) {
+          // var_dump($currentProject);
+            return $currentProject;
+        }
+         
+        //print_r($ar);
+        
+        if (empty($currentProject))    {
+            
+        
+            //$p = DB_DataObject::factory('core_project');
+            //$p->get('code', '*PUBLIC');
+            $id = 0;
+            foreach($ar as $k=>$v) {
+                $id= $k;
+                break;
+            }
+            
+        
+            $_SESSION[__CLASS__]['active_project_id'] = $id;
+            $currentProject = $_SESSION[__CLASS__]['active_project_id'];
+            return $id; // always allowed..
+        }
+        //var_dump($currentProject);
+        $currentProject = $_SESSION[__CLASS__]['active_project_id'];
+        return $_SESSION[__CLASS__]['active_project_id'];
+        
+        
+    }
+    
+    
+    function userProjects()
+    {
+        
+        $p = DB_DataObject::factory('core_project');
+        if (!$this->authUser) {
+            $p->code = '*PUBLIC';
+           
+            $ar = $p->fetchAll('id', 'name');
+        } else {
+            
+           // DB_DAtaObject::debugLevel(1);
+            $p->applyFilters(array(), $this->authUser, $this);
+            if (!$this->authUser->hasPerm('Core.Projects_All', 'S')) { 
+                $p->whereAdd("Projects.id in (SELECT ProjectDirectory.project_id FROM ProjectDirectory WHERE
+                        person_id = ". $this->authUser->id . " and role != '')");
+            }
+            /*
+             * SOME PROJECTS MIGHT NOT HAVE REPO's...
+            $p->whereAdd('id in (SELECT distinct(project_id) FROM mtrack_repos)');
+            */
+            // $pd->whereAdd("role != ''");
+            
+            $p->orderBy('core_project.name ASC');
+            unset($p->client_id); // default projects serach enforces this..
+            $ar = $p->fetchAll('id', 'name');
+        }
+        return $ar;
+        
     }
     
+    
+    function loadProjectList()
+    {
+       // DB_DataObject::debugLevel(1);
+
+        $ar = $this->userProjects();
+         
+        $this->elements['active_project_id'] = new HTML_Template_Flexy_Element();
+        $this->elements['active_project_id']->setOptions($ar);
+         
+        $this->elements['active_project_id']->setValue($this->currentProject());
+   
+        
+        
+    }
+    
+    
     function getAuthUser()
     {
-        $u = DB_DataObject::factory('Person');
+        $u = DB_DataObject::factory('core_person');
         if (!$u->isAuth()) {
             return false;
         }
@@ -30,7 +210,8 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     
     function getAuth()
     {
-        $this->registerClasses();
+        $this->registerClasses(); // to be destroyed??
+        
         $ff = HTML_FlexyFramework::get();
         if ($ff->cli) {
             return true;
@@ -44,18 +225,31 @@ class MTrackWeb extends HTML_FlexyFramework_Page
         
         //MTrackConfig::boot(); // eak.. .remove me...
       
-        $this->authUser = DB_DataObject::factory('Person')->getAuthUser();
+        $this->authUser = DB_DataObject::factory('core_person')->getAuthUser();
+        
+        $this->loadProjectList();
+        
+        
+        $p = DB_DataObject::factory('core_project');
+        $p->get($this->currentProject());
+        $this->currentProject = $p; /// mix up?
+        
+        
+        
         if (!$this->authUser) {
             return true; // we do allow people in this far..
         }
-        
+        // very public??
+        $this->authUserArray = $this->authUser->toArray();
+        unset($this->authUserArray['passwd']);
          
         // timezone setting... -- this may be a good addon to our core person class.
         
         if (!empty($this->authUser->timezone)) {
             date_default_timezone_set($this->authUser->timezone);
-            return;
         }
+        
+         
          
         /// fixme...
         //$this->authUser = 
@@ -64,20 +258,30 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     function get($loc='')
     {
         // 
+        
+        
+        HTML_FlexyFramework::get()->generateDataobjectsCache();
+
+        
         if (!empty($loc)) {
             die ("invalid location". htmlspecialchars($loc));
         }
+        
+        
+        
         if (!$this->authUser) {
-            die("wiki todo");
-            return HTML_FlexyFramework::run('Wiki'); 
+             return HTML_FlexyFramework::run('Wiki'); 
         }
+        
+        
+        
         return HTML_FlexyFramework::run('Wiki/Today'); 
  
     }
-    function post()
+    function post($request)
     {
         header("Status: 404 Not Found");
-        die("not valid");
+        die("invalid post request? ");
     }
     
     
@@ -100,67 +304,14 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     
     function registerClasses()
     {
-        require_once 'MTrack/Wiki.php';
-        require_once 'MTrack/Wiki/Item.php';
-        require_once 'MTrack/Milestone.php';
-        //require_once 'MTrack/Report.php';
-        require_once 'MTrack/ACL.php';
-        require_once 'MTrack/SearchDB.php';
-        require_once 'MTrack/Watch.php'; 
-        require_once 'MTrack/CommitChecker.php'; 
-        //require_once 'MTrack/Repo.php';
-        //require_once 'MTrack/SCM/Git/Repo.php';
-        //require_once 'MTrack/SCM/Svn.php';
-        //require_once 'MTrack/SCM/Hg.php';
+        // wiki rendering is done client side...
+        // require_once 'MTrack/Wiki/HTMLFormatter.php';
         require_once 'MTrackWeb/LinkHandler.php';
-         require_once 'MTrack/Wiki/HTMLFormatter.php';
-        
         $this->link = new MTrackWeb_LinkHandler();
-        MTrack_Wiki_HTMLFormatter::registerLinkHandler($this->link);
-        
-        //MTrackRepo::registerSCM('git', 'MTrack_SCM_Git_Repo');
-        //MTrackRepo::registerSCM('svn', 'MTrackSCMSVN');
-        //MTrackRepo::registerSCM('hg', 'MTrackSCMHg');
-
-        $r = DB_DataObject::factory('mtrack_repos');
-        $r->get('shortname', 'wiki'); // default wiki?
-        MTrack_Wiki_Item::$repo = $r->impl();
-        MTrack_Wiki::register_macro('MilestoneSummary', array('MTrack_Milestone', 'macro_MilestoneSummary'));
-        MTrack_Wiki::register_macro('BurnDown', array('MTrack_Milestone', 'macro_BurnDown'));
-        //MTrack_Wiki::register_macro('RunReport', array('MTrack_Report', 'macro_RunReport')); << fixme how are we to hanlde this..
-        MTrack_Wiki::register_macro('TicketQuery', array('MTrack_Report', 'macro_TicketQuery'));
-        MTrack_Wiki::register_macro('IncludeWikiPage', array('MTrack_Wiki', 'macro_IncludeWiki'));
-        MTrack_Wiki::register_macro('IncludeHelpPage', array('MTrack_Wiki', 'macro_IncludeHelp'));
-        MTrack_Wiki::register_macro('Comment', array('MTrack_Wiki', 'macro_comment'));
-        MTrack_Wiki::register_processor('comment', array('MTrack_Wiki', 'processor_comment'));
-        MTrack_Wiki::register_processor('html', array('MTrack_Wiki', 'processor_html'));
-        MTrack_Wiki::register_processor('dataset', array('MTrack_Wiki', 'processor_dataset'));
-
-
-        MTrackACL::registerAncestry('milestone', 'Roadmap');
-        MTrackACL::registerAncestry('report', 'Reports');
-        MTrackACL::registerAncestry('snippet', 'Snippets');
-        MTrackACL::registerAncestry('repo', 'Browser');
-        MTrackACL::registerAncestry('enum',     'Enumerations');
-        MTrackACL::registerAncestry("component", 'Components');
-        MTrackACL::registerAncestry("project",  'Projects');
-        MTrackACL::registerAncestry("ticket",   "Tickets");
-        MTrackACL::registerAncestry('wiki', array('MTrack_Wiki_Item', '_get_parent_for_acl'));
-
-        MTrackSearchDB::register_indexer('ticket', array('MTrackIssue', 'index_issue'));
-        MTrackSearchDB::register_indexer('wiki', array('MTrack_Wiki_Item', 'index_item'));
-
-
-
-        MTrackWatch::registerEventTypes('ticket', array( 'ticket' => 'Tickets' ));
-        MTrackWatch::registerEventTypes('milestone', array( 'ticket' => 'Tickets', 'changeset' => 'Code changes' ));
-        MTrackWatch::registerEventTypes('repo', array( 'ticket' => 'Tickets', 'changeset' => 'Code changes' ));
-
-        // should this get registered here??
-        MTrackCommitChecker::addCheck('Wiki');
-        
-        
-        
+        //MTrack_Wiki_HTMLFormatter::registerLinkHandler($this->link);
+        return;
    }
     
     function favicon()
@@ -179,6 +330,7 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     
   function attachmentsToHtml($object)
   {
+    return 'TODO';
     if (is_object($object)) {
         $object = $object->toIdString(); // eg. ticket:1
     }
@@ -223,6 +375,157 @@ class MTrackWeb extends HTML_FlexyFramework_Page
     $html .= "</ul></div>";
     return $html;
   }
+    function jerr($str, $errors=array()) // standard error reporting..
+    {
+        require_once 'Services/JSON.php';
+        $json = new Services_JSON();
+        
+        // log all errors!!!
+        //$this->addEvent("ERROR", false, $str);
+        
+        if ((isset($_SERVER['CONTENT_TYPE']) && preg_match('#multipart/form-data#i', $_SERVER['CONTENT_TYPE']))) {
+            header('Content-type: text/html');
+            echo "<HTML><HEAD></HEAD><BODY>";
+            echo  $json->encodeUnsafe(array(
+                    'success'=> false, 
+                    'message' => $str, // compate with exeption / loadexception.
+
+                    'errors' => $errors ? $errors : true, // used by forms to flag errors.
+                    'authFailure' => !empty($errors['authFailure']),
+                ));
+            echo "</BODY></HTML>";
+            exit;
+        }
+        
+        echo $json->encode(array(
+            'success'=> false, 
+            'data'=> array(), 
+            'message' => $str, // compate with exeption / loadexception.
+            'errors' => $errors ? $errors : true, // used by forms to flag errors.
+            'authFailure' => !empty($errors['authFailure']),
+        ));
+        exit;
+        
+    }
+    function jok($str)
+    {
+        
+        require_once 'Services/JSON.php';
+        $json = new Services_JSON();
+        
+        if ( (isset($_SERVER['CONTENT_TYPE']) && preg_match('#multipart/form-data#i', $_SERVER['CONTENT_TYPE']))
+        
+        ) {
+            header('Content-type: text/html');
+            echo "<HTML><HEAD></HEAD><BODY>";
+            echo  $json->encodeUnsafe(array('success'=> true, 'data' => $str));
+            echo "</BODY></HTML>";
+            exit;
+        }
+        
+        
+        echo  $json->encode(array('success'=> true, 'data' => $str));
+        exit;
+        
+    }
+    /**
+     * output data for grids or tree
+     * @ar {Array} ar Array of data
+     * @total {Number|false} total number of records (or false to return count(ar)
+     * @extra {Array} extra key value list of data to pass as extra data.
+     * 
+     */
+    function jdata($ar,$total=false, $extra=array())
+    {
+        // should do mobile checking???
+        if ($total == false) {
+            $total = count($ar);
+        }
+        $extra=  $extra ? $extra : array();
+        require_once 'Services/JSON.php';
+        $json = new Services_JSON();
+        echo $json->encode(array('success' =>  true, 'total'=> $total, 'data' => $ar) + $extra);    
+        exit;
+        
+        
+    }
+    
+    /**
+     * ---------------- Logging ---------------   
+     */
+    
+    /**
+     * addEventOnce:
+     * Log an action (only if it has not been logged already.
+     * 
+     * @param {String} action  - group/name of event
+     * @param {DataObject|false} obj - dataobject action occured on.
+     * @param {String} any remarks 
+     */
+    
+    function addEventOnce($act, $obj = false, $remarks = '') 
+    {
+        $au = $this->getAuthUser();
+        $e = DB_DataObject::factory('Events');
+        $e->init($act,$obj,$remarks); 
+        if ($e->find(true)) {
+            return;
+        }
+        $this->addEvent($act, $obj, $remarks);
+    }
+    /**
+     * addEvent:
+     * Log an action.
+     * 
+     * @param {String} action  - group/name of event
+     * @param {DataObject|false} obj - dataobject action occured on.
+     * @param {String} any remarks 
+     */
+    
+    function addEvent($act, $obj = false, $remarks = '') 
+    {
+        $au = $this->getAuthUser();
+        $e = DB_DataObject::factory('Events');
+        $e->init($act,$obj,$remarks); 
+         
+        $e->event_when = date('Y-m-d H:i:s');
+        
+        $eid = $e->insert();
+        $ff  = HTML_FlexyFramework::get();
+        if (empty($ff->Pman['event_log_dir'])) {
+            return;
+        }
+        $file = $ff->Pman['event_log_dir']. date('/Y/m/d/'). $eid . ".php";
+        if (!file_exists(dirname($file))) {
+            mkdir(dirname($file),0700,true);
+        }
+        file_put_contents($file, var_export(array(
+            'REQUEST_URI' => empty($_SERVER['REQUEST_URI']) ? 'cli' : $_SERVER['REQUEST_URI'],
+            'GET' => empty($_GET) ? array() : $_GET,
+            'POST' => empty($_POST) ? array() : $_POST,
+        ), true));
+        
+        
+        
+    }
+
+     function packJS($dir)
+    {
+       
+        // target has to be 'aliased'
+        // target filename can be an md5..
+        
+        require_once 'Pman/Core/JsCompile.php';
+        $x = new Pman_Core_JsCompile();
+        $x->packScript(dirname(__FILE__).'/MTrackWeb/templates/images',
+                       array($dir),
+                       $this->rootURL . '/MTrackWeb/templates/images',
+                       false // do not compile
+                       );
+                        //);
+        
+        
+    }