diff --git a/boost/boost.php b/boost/boost.php new file mode 100644 index 0000000..b0690ad --- /dev/null +++ b/boost/boost.php @@ -0,0 +1,15 @@ + diff --git a/boost/controlpanel.php b/boost/controlpanel.php new file mode 100644 index 0000000..f78f9b4 --- /dev/null +++ b/boost/controlpanel.php @@ -0,0 +1,34 @@ + +*/ + +$link[] = array( + 'label' => 'Student Legal Clinic Tracker 2.0', + 'restricted' => true, + 'url' => 'index.php?module=slc', + 'description' => 'Track statistics about visits', + 'image' => 'skeleton.png', + 'tab' => 'content' + ); + +?> diff --git a/boost/dependency.xml b/boost/dependency.xml new file mode 100644 index 0000000..d51005b --- /dev/null +++ b/boost/dependency.xml @@ -0,0 +1,9 @@ + + + + core + phpWebSite Core + 2.0.1 + http://phpwebsite.appstate.edu/downloads/modules/base/ + + diff --git a/boost/uninstall.sql b/boost/uninstall.sql new file mode 100644 index 0000000..ba5a60e --- /dev/null +++ b/boost/uninstall.sql @@ -0,0 +1,41 @@ +-- slc - phpwebsite module +-- @version $Id: $ +-- @author Adam Dixon + +DROP TABLE IF EXISTS slc_issue; + +DROP TABLE IF EXISTS slc_visit; + +DROP TABLE IF EXISTS slc_visit_issue_index; + +DROP TABLE IF EXISTS slc_visit_issue_date_index; + +DROP TABLE IF EXISTS slc_client; + +DROP TABLE IF EXISTS slc_visit_client_index; + +DROP TABLE IF EXISTS slc_issue_detail_index; + +DROP TABLE IF EXISTS slc_visit_detail_index; + +DROP TABLE IF EXISTS slc_client_detail_index; + +DROP TABLE IF EXISTS slc_detail; + +DROP TABLE IF EXISTS slc_landlord; + +DROP TABLE IF EXISTS slc_problem; + +DROP TABLE IF EXISTS slc_referral_type; + +DROP TABLE IF EXISTS slc_student_data; + +DROP TABLE IF EXISTS slc_visit_client_index_seq; +DROP TABLE IF EXISTS slc_visit_issue_index_seq; +DROP TABLE IF EXISTS slc_visit_seq; + +DROP TABLE IF EXISTS slc_issue_node; +DROP TABLE IF EXISTS slc_issue_report; +DROP TABLE IF EXISTS slc_issue_report_list; +DROP TABLE IF EXISTS slc_issue_selected_node; +DROP TABLE IF EXISTS slc_issue_seq; diff --git a/boost/update.php b/boost/update.php new file mode 100644 index 0000000..64b90a8 --- /dev/null +++ b/boost/update.php @@ -0,0 +1,131 @@ + + */ + +function slc_update(&$content, $current_version) { + switch(1) { + case version_compare($current_version, '2.0.3', '<'): + $content[] = '
';
+            
+            $db = new PHPWS_DB('slc_problem');
+            $db->addWhere('id', 16);
+            $db->addValue('description', 'Tenancy / Eviction');
+
+            if (PHPWS_Error::logIfError($db->update())) {
+                $content[] = 'Unable to change "Tenancy/Eviction" to "Tenancy / Eviction" in table slc_problem.';
+                return false;
+            } else {
+                $content[] = 'Changed "Tenancy/Eviction" to "Tenancy / Eviction" in table slc_problem';
+            }
+
+            slcUpdateFiles(array(   'class/ajax/GETReport.php',
+                                    'class/views/ViewReports.php',
+                                    'javascript/report/head.js',
+                                    'templates/Report.tpl',
+                                    'boost/install.sql',
+                                    'boost/boost.php',
+                                    'boost/update.php'), $content);
+
+            $content[] = '2.0.3 changes
+---------------
++ Added date selectors to all reports to limit data to a specific timespan.
++ Fixed the Landlord-Tenant report display issue in Firefox.
'; + + case version_compare($current_version, '2.0.4', '<'): + $content[] = '
';
+            
+            $db = new PHPWS_DB('slc_landlord');
+            $db->addWhere('id', 94);
+            $db->addValue('name', 'Other / Unspecified');
+            if (PHPWS_Error::logIfError($db->update())) {
+                $content[] = 'Unable to change "Other / Not Provided" to "Other / Unspecified" in table slc_landlord.';
+                return false;
+            }
+
+            $db->reset();
+            $db->addWhere('id', 70);
+            $db->addValue('name', 'Roger Pope');
+            if (PHPWS_Error::logIfError($db->update())) {
+                $content[] = 'Unable to move "Roger Pope" from id=95 to id=70';
+                return false;
+            }
+
+            $db->reset();
+            $db->addWhere('id', 95);
+            if (PHPWS_Error::logIfError($db->delete())) {
+                $content[] = 'Unable to delete Roger Pope\'s old id (95) from slc_landlord.';
+                return false;
+            }
+
+            $content[] = 'Successfully merged "Unknown" and "Other / Not Provided" into "Other / Unspecified" in table slc_landlord.';
+
+            $db = new PHPWS_DB('slc_issue');
+            $db->addWhere('landlord_id', 70);
+            $db->addValue('landlord_id', 94);
+            if (PHPWS_Error::logIfError($db->update())) {
+                $content[] = 'Unable to move issues assigned to landlord "Unknown" to landlord "Other / Unspecified".';
+                return false;
+            } else {
+                $content[] = 'Successfully moved issues assigned to landlord "Unknown" to landlord "Other / Unspecified".';
+            }
+
+            $db->reset();
+            $db->addWhere('landlord_id', 95);
+            $db->addValue('landlord_id', 70);
+            if (PHPWS_Error::logIfError($db->update())) {
+                $content[] = 'Unable to move issues assigned to landlord "Roger Pope" from his old id (95) to his new id (70).';
+                return false;
+            } else {
+                $content[] = 'Successfully moved issues assigned to landlord Roger Pope\'s old id (95) to his new id (70).';
+            }
+
+            slcUpdateFiles(array(   'boost/install.sql',
+                                    'boost/update.php',
+                                    'boost/boost.php',
+                                    'class/ajax/GETReport.php',
+                                    'class/ajax/POSTNewIssue.php'), $content);
+            
+            $content[] = '2.0.4 changes
+---------------
++ Merged "Unknown" and "Other / Not Provided" landlords into "Other / Unspecified".
++ Updated the reports and issue creation to reflect this merging.
';
+    
+        case version_compare($current_version, '2.0.5', '<'):
+            $content[] = '
';
+            slcUpdateFiles(array(   'boost/boost.php',
+                                    'boost/update.php',
+                                    'class/ajax/GETReport.php',
+                                    'class/views/ViewReports.php',
+                                    'javascript/report/head.js',
+                                    'templates/Report.tpl',
+                                    'class/ajax/ExportCSV.php'), $content);
+            $content[] = '2.0.5 changes
+---------------
++ Fixed some math issues in "Landlord/Tenant" and "Condition by Landlord" reports.
++ Added CSV export for the "Landlord/Tenant", "Condition by Landlord", and "Appointment Statistics" reports.
+
';
+        
+        case version_compare($current_version, '2.0.6', '<'):
+           $db = new PHPWS_DB;
+            $result = $db->importFile(PHPWS_SOURCE_DIR .
+                            'mod/slc/boost/updates/update_2_0_6.sql');
+            if(PHPWS_Error::logIfError($result)){
+                return $result;
+            } 
+    }
+    return true;
+}
+
+function slcUpdateFiles($files, &$content) {
+    if (PHPWS_Boost::updateFiles($files, 'checkin')) {
+        $content[] = '--- Updated the following files:';
+    } else {
+        $content[] = '--- Unable to update the following files:';
+    }
+    $content[] = "    " . implode("\n    ", $files);
+}
+
+?>
diff --git a/boost/updates/update_2_0_6.sql b/boost/updates/update_2_0_6.sql
new file mode 100644
index 0000000..c3af00f
--- /dev/null
+++ b/boost/updates/update_2_0_6.sql
@@ -0,0 +1,62 @@
+-- Drop empty/unused/never-referenced tables
+DROP TABLE  slc_client_detail_index,
+            slc_detail,
+            slc_issue_detail_index,
+            slc_visit_detail_index,
+            slc_visit_issue_date_index;
+
+-- Delete issue records with problem IDs that don't exist.
+DELETE slc_issue.*
+FROM slc_issue
+WHERE slc_issue.problem_id NOT IN (
+    SELECT slc_problem.id FROM slc_problem
+);
+
+-- Delete visit records with client IDs that don't exist.
+DELETE slc_visit.*
+FROM slc_visit
+WHERE slc_visit.c_id NOT IN (
+    SELECT id FROM slc_client
+);
+
+-- Delete slc_visit_issue_index records with issue IDs that don't exist.
+DELETE slc_visit_issue_index.*
+FROM slc_visit_issue_index
+WHERE slc_visit_issue_index.i_id NOT IN (
+    SELECT slc_issue.id FROM slc_issue
+);
+
+-- Delete slc_visit_issue_index records with visit IDs that don't exist.
+DELETE slc_visit_issue_index.*
+FROM slc_visit_issue_index
+WHERE slc_visit_issue_index.v_id NOT IN (
+    SELECT slc_visit.id FROM slc_visit
+);
+
+-- Delete visit records without an associated slc_visit_issue_index record.
+DELETE slc_visit.* 
+FROM slc_visit 
+WHERE slc_visit.id NOT IN (
+    SELECT v_id FROM slc_visit_issue_index
+);
+
+-- Delete issue records without an associated slc_visit_issue_index record.
+DELETE slc_issue.* 
+FROM slc_issue 
+WHERE slc_issue.id NOT IN (
+    SELECT i_id FROM slc_visit_issue_index
+);
+
+-- Then delete client records without associated visits.
+DELETE slc_client.*
+FROM slc_client
+WHERE slc_client.id NOT IN (
+    SELECT c_id FROM slc_visit
+);
+
+-- Merge all 'Criminal' sub-types into the main 'Criminal' type
+UPDATE slc_issue
+SET problem_id=998
+WHERE problem_id IN (
+    25,26,27,28,29,30,31,32,33,34,995
+);
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..8928f73
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,146 @@
+
+
+
+    
+
+    
+
+    
+    
+    
+
+    
+
+    
+        
+            
+                
+                
+            
+            
+            
+            
+            
+        
+    
+
+    
+        
+    
+
+    
+        
+        
+        
+        
+        
+        
+        
+        
+    
+
+    
+        
+            
+
+            
+                
+                
+            
+
+
+        
+    
+
+    
+        
+            
+            
+            
+        
+    
+
+    
+        
+            
+            
+            
+            
+        
+    
+
+    
+        
+            
+            
+            
+        
+    
+
+    
+        
+            
+            
+            
+            
+            
+        
+    
+
+    
+        
+            
+            
+        
+    
+
+    
+        
+            
+            
+            
+            
+        
+    
+
+    
+        
+            
+            
+            
+        
+    
+
+    
+        
+    
+
+    
+
+    
+
+    
+        
+            
+            
+            
+            
+            
+            
+        
+    
+
diff --git a/class/AJAXFactory.php b/class/AJAXFactory.php
new file mode 100644
index 0000000..a35261d
--- /dev/null
+++ b/class/AJAXFactory.php
@@ -0,0 +1,53 @@
+call = new $action();
+	}
+	
+	public function setData($data) {
+		$this->call->setData($data);
+	}
+	
+	public function execute() {
+		$this->call->execute();
+	}
+	
+	public function result() {
+		$this->result = $this->call->getResult();
+		return $this->result;
+	}
+	
+	
+}
+
+?>
diff --git a/class/Client.php b/class/Client.php
new file mode 100644
index 0000000..4575676
--- /dev/null
+++ b/class/Client.php
@@ -0,0 +1,20 @@
+id = $id;
+	}
+}
+
+?>
diff --git a/class/CommandContext.php b/class/CommandContext.php
new file mode 100644
index 0000000..b474f08
--- /dev/null
+++ b/class/CommandContext.php
@@ -0,0 +1,60 @@
+
+ * @package mod
+ * @subpackage slc
+ */
+
+class CommandContext {
+    private $params = array();
+    private $error = "";
+
+    function __construct() {
+        $this->params = $_REQUEST;
+    }
+
+    function addParam( $key, $val ) {
+        $this->params[$key]=$val;
+    }
+
+    function get( $key ) {
+        if(!isset($this->params[$key])){
+            throw new ParameterNotFoundException("Key: $key is not set");
+        }
+
+        return $this->params[$key];
+    }
+
+    function setError( $error ) {
+        $this->error = $error;
+    }
+
+    function getError() {
+        return $this->error;
+    }
+
+    function getParams() {
+        return $this->params;
+    }
+
+    function redirect($request){
+        $path = $_SERVER['SCRIPT_NAME'].'?module=slc';
+        foreach($request as $key=>$val) {
+            $path .= "&$key=$val";
+        }
+
+        header('HTTP/1.1 303 See Other');
+        header("Location: $path");
+        exit();
+    }
+}
+
+?>
diff --git a/class/Exceptions.php b/class/Exceptions.php
new file mode 100644
index 0000000..36f3d5b
--- /dev/null
+++ b/class/Exceptions.php
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/class/Issue.php b/class/Issue.php
new file mode 100644
index 0000000..aa6085a
--- /dev/null
+++ b/class/Issue.php
@@ -0,0 +1,25 @@
+id = $issueID;
+
+	}
+}
+
+?>
diff --git a/class/ViewFactory.php b/class/ViewFactory.php
new file mode 100644
index 0000000..4bae775
--- /dev/null
+++ b/class/ViewFactory.php
@@ -0,0 +1,37 @@
+
+ * @package mod
+ * @subpackage slc
+ */
+
+class ViewFactory {
+
+    public static function getView($view = 'Main'){
+        if ( preg_match( '/\W/', $view ) ) {
+            throw new Exception("Illegal characters in view");
+        }
+
+        $class = "View".$view;//UCFirst(strtolower($view));
+
+        $file = "{$class}.php";
+
+        if ( !PHPWS_Core::initModClass( 'slc', 'views/'.$file ) ) {
+            throw new ViewNotFoundException( "Could not find view '$file'" );
+        }
+
+        if ( ! class_exists( $class ) ) {
+            throw new ViewNotFoundException( "No view class '$class' located" );
+        }
+       
+        $view = new $class();
+        
+        return $view;
+    }
+}
+
+?>
diff --git a/class/Visit.php b/class/Visit.php
new file mode 100644
index 0000000..9ba3df6
--- /dev/null
+++ b/class/Visit.php
@@ -0,0 +1,18 @@
+issues[$issue->id] = $issue;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/class/ajax/AJAX.php b/class/ajax/AJAX.php
new file mode 100644
index 0000000..d716d60
--- /dev/null
+++ b/class/ajax/AJAX.php
@@ -0,0 +1,25 @@
+data = $data;
+	}
+	
+	public function getResult() {
+		return $this->result;
+	}
+	
+	protected function resetResult() {
+		$this->result = array();
+	}
+	
+	protected function addResult($r, $v) {
+		$this->result[$r] = $v;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/class/ajax/ExportCSV.php b/class/ajax/ExportCSV.php
new file mode 100644
index 0000000..116bc35
--- /dev/null
+++ b/class/ajax/ExportCSV.php
@@ -0,0 +1,393 @@
+
+ * @package SLC
+ */
+class ExportCSV extends AJAX {
+    public function execute() {
+        if (!isset($_REQUEST['report_type'])) {
+            $this->addResult("msg", "No Report Type Supplied");
+            return;
+        }
+
+        $csv;
+        $startdate = $_REQUEST['start_date'];
+        $enddate = $_REQUEST['end_date'];
+        $file = 'SLC' . $_REQUEST['report_type'] . ' ' . $startdate . ' to ' . $enddate . '.csv';   // output filename
+
+        $func = 'CSV' . $_REQUEST['report_type'];
+        if (method_exists("ExportCSV", $func)) {
+            $csv = call_user_func(array("ExportCSV", $func));
+        } else {
+            $csv = "The selected report is not available to be exported as a CSV file.";
+            echo $csv;
+            exit();
+        }
+
+        // Force the browser to open a 'save as' dialogue
+        header('Content-Type: text/csv');
+        header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
+        header('Pragma: public');
+        header('Expires: Mon, 17 Sep 2012 05:00:00 GMT'); // Date in the past
+        header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+        header('Content-Length: '.strlen($csv));
+        header('Content-Disposition: attachment; filename="' . $file . '";');
+
+        echo $csv;
+        exit();
+    }
+
+    /**
+     * Handles writing an array to a comma-separated string
+     * 
+     * @param Array $row Array of values to write
+     * @param char $delimiter
+     * @param char $enclosure
+     * @param char $eol
+     */
+    private static function sputcsv(Array $row, $delimiter = ',', $enclosure = '"', $eol = "\n")
+    {
+        static $fp = false;
+        if ($fp === false)
+        {
+            $fp = fopen('php://temp', 'r+'); // see http://php.net/manual/en/wrappers.php.php - yes there are 2 '.php's on the end.
+            // NB: anything you read/write to/from 'php://temp' is specific to this filehandle
+        }
+        else
+        {
+            rewind($fp);
+        }
+    
+        if (fputcsv($fp, $row, $delimiter, $enclosure) === false)
+        {
+            return false;
+        }
+    
+        rewind($fp);
+        $csv = fgets($fp);
+    
+        if ($eol != PHP_EOL)
+        {
+            $csv = substr($csv, 0, (0 - strlen(PHP_EOL))) . $eol;
+        }
+    
+        return $csv;
+    }
+    
+    /**
+     * Handles converting the 'Appointment Statistics' report to a CSV file
+     * Uses the same DB query as REPORTfollowupappts from GETReport.php
+     */
+    private function CSVfollowupappts() {
+        $initialVisits  = 0;
+        $clients        = 0;
+        $issues         = 0;
+        $followups      = 0;
+
+        // Get date range from user
+        $start_date = strtotime($_REQUEST['start_date']);
+        $end_date = strtotime($_REQUEST['end_date']) + 86400;   // +1 day to make date range inclusive
+        
+        // Get the array of all visits whose initial visit happened in the time period. Equivalent to this query:
+        // SELECT DISTINCT(id) FROM slc_visit WHERE initial_date >= $start_date AND initial_date < $end_date;
+        $db = new PHPWS_DB('slc_visit');
+        $db->addColumn('id', null, null, null, true);
+        $db->addWhere('initial_date', $start_date, '>=');
+        $db->addwhere('initial_date', $end_date, '<', 'AND');
+        $visitIds = $db->select('col');
+
+        // Get # of initial visits. Equivalent to this query: 
+        // SELECT COUNT(DISTINCT(v_id)) FROM slc_visit_issue_index
+        // WHERE v_id IN $visitIds;
+        $db = new PHPWS_DB('slc_visit_issue_index');
+        $db->addColumn('v_id', null, null, true, true);
+        $db->addWhere('v_id', $visitIds, 'IN', 'AND');
+        $initialVisits = $db->select('one');
+
+        // Get the array of different 'counts' greater than 1. Equivalent to this query:
+        // SELECT DISTINCT(counter) FROM slc_visit_issue_index WHERE counter>'1' ORDER BY counter DESC;
+        $db->reset();
+        $db->addColumn('counter', null, null, null, true);
+        $db->addWhere('counter', '1', '>');
+        $db->addOrder('counter desc');
+        $counters = $db->select('col');
+
+        //TODO: Make followups only count if they occured during the time period.
+        // As of 05/20/2013 this is impossible due to the structure of the DB. We need to track when each followup occured.
+        // For now we just count all followups for visits whose initial visit took place within the time period.
+
+        // Calculate the number of followup visits.
+        $visits = array();
+        $db = new PHPWS_DB('slc_visit_issue_index');
+        $db->addColumn('v_id', null, null, null, true);
+        foreach ($counters as $count) {
+            $db->addWhere('v_id', $visitIds, 'IN');
+
+            // Make sure you don't count visits with multiple issues if they've already been counted.
+            if (!empty($visits)) {
+                $db->addWhere('v_id', $visits, 'NOT IN', 'AND');
+            }
+
+            $db->addWhere('counter', $count, '=', 'AND');
+            $result = $db->select('col');
+            $visits = $visits + $result;
+            $followups += ($count-1) * count($result);
+            $db->resetWhere();
+        }
+
+        // Get # of clients. Equivalent to this query:
+        // SELECT COUNT(DISTINCT(id)) FROM slc_client
+        // WHERE first_visit >= $start_date AND first_visit < $end_date;
+        $db = new PHPWS_DB('slc_client');
+        $db->addColumn('id', null, null, true, true);
+        $db->addWhere('first_visit', $start_date, '>=');
+        $db->addWhere('first_visit', $end_date, '<', 'AND');
+        $clients = $db->select('one');
+
+        // Get # of issues. Equivalent to this query: 
+        // SELECT COUNT(DISTINCT(id)) FROM slc_issue
+        // JOIN slc_visit_issue_index ON slc_issue.id = slc_visit_issue_index.i_id
+        // WHERE slc_visit_issue_index.v_id IN $visitIds;
+        $db = new PHPWS_DB('slc_issue');
+        $db->addColumn('id', null, null, true, true);
+        $db->addTable('slc_visit_issue_index', 'svii');
+        $db->addWhere('slc_issue.id', 'svii.i_id');
+        $db->addWhere('svii.v_id', $visitIds, 'IN', 'AND');
+        $issues = $db->select('one');
+
+        // Put the data into the CSV.
+        $cols = array(  'Total Clients',
+                        'Total Issues',
+                        'Total Initial Visits',
+                        'Total Followups',
+                        'Issues per Visit (w/o Followups)',
+                        'Visits per Client (w/o Followups)',
+                        'Visits per Client (with Followups)',
+                        'Followups per Issue',
+                        'Followups per Visit');
+        $rows = array(  $clients,
+                        $issues,
+                        $initialVisits,
+                        $followups,
+                        ($clients == 0 ? 0 : round($issues / $initialVisits, 2)),
+                        ($clients == 0 ? 0 : round($initialVisits / $clients, 2)),
+                        ($clients == 0 ? 0 : round(($initialVisits + $followups) / $clients, 2)),
+                        ($clients == 0 ? 0 : round($followups / $issues, 2)),
+                        ($clients == 0 ? 0 : round($followups / $initialVisits, 2)));
+        $data = $this->sputcsv($cols);
+        $data .= $this->sputcsv($rows);
+
+        return $data;
+    }
+
+    /**
+     * Handles converting the 'Landlord/Tenant' report to a CSV file
+     * Uses the same DB query as REPORTlandlordtenant from GETReport.php
+     */
+    private function CSVlandlordtenant() {
+        // Get date range from user
+        $start_date = strtotime($_REQUEST['start_date']);
+        $end_date = strtotime($_REQUEST['end_date']) + 86400;   // +1 day to make date range inclusive
+
+        $landlords = "SELECT * FROM slc_landlord";
+        $db = new PHPWS_DB();
+        $landlords = $db->select(null, $landlords);
+        $landlordnames = array();
+        foreach( $landlords as $landlord )
+            $landlordnames[] = $landlord['name'];
+
+        $issues = "SELECT * FROM slc_problem WHERE tree LIKE '%Landlord-Tenant%' OR description LIKE 'Conditions' OR description LIKE 'Landlord-Tenant' "; // Covers generic landlord-tenant, too
+        $db = new PHPWS_DB();
+        $issues = $db->select(null, $issues);
+        $issuenames = array();
+        foreach( $issues as $issue )
+            $issuenames[] = $issue['description'];
+
+
+        // Get the issues listed ( all others 0 )
+        $db = new PHPWS_DB();
+        $db->addTable('slc_issue');
+        $db->addTable('slc_problem');
+        $db->addTable('slc_landlord');
+        $db->addTable('slc_visit');
+        $db->addTable('slc_visit_issue_index');
+        $db->addColumn('slc_problem.description');
+        $db->addColumn('slc_landlord.name');
+
+        // 1st Join set
+        // needs to be a left join to allow for landlord "not specified" which is recorded as NULL in DB
+        $db->addJoin('left', 'slc_issue', 'slc_landlord', 'landlord_id', 'id');
+
+        // 2nd Join set
+        $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id');
+        $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id');
+        $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id');
+        $db->addWhere('slc_visit.initial_date', $start_date, '>=');
+        $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND');
+        $results = $db->select();
+
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+
+        $theMatrix = $landlordnames;
+        foreach($landlordnames as $lname) {
+            $theMatrix[$lname] = $issuenames;
+            foreach($issuenames as $iname)
+                $theMatrix[$lname][$iname] = 0; // Populate with 0s 
+        }
+
+
+        foreach( $results as $r ) {
+            // If landlord name is NULL, set as "Other / Unspecified"
+            $name = isset($r['name']) ? $r['name'] : "Other / Unspecified";
+            $description = $r['description'];
+
+            if ( !array_key_exists($description,$theMatrix[$name]) )
+                    $theMatrix[$name][$description] = 0;
+
+            $theMatrix[$name][$description]++; // increment that value
+        }
+
+        // Create the final $data array
+        $data = $this->sputcsv(array_merge(array_merge(array(' '), $issuenames), array('Landlord Totals')));
+
+        $colTotals = array();
+        foreach ($landlordnames as $landlord) {
+            $row = array($landlord);
+            $accumulator = 0;
+            foreach ($issuenames as $issue) {
+                $value = $theMatrix[$landlord][$issue];
+                $row[] = $value;
+                $accumulator += $value;
+                if (!array_key_exists($issue, $colTotals)) {
+                    $colTotals[$issue] = 0;
+                }
+                $colTotals[$issue] += $value;
+            }
+            $row[] = $accumulator;
+            $data .= $this->sputcsv($row);
+        }
+        
+        $totalRow = array('Issue Totals');
+        $accumulator = 0;
+        foreach ($issuenames as $issue) {
+            if (array_key_exists($issue, $colTotals)) {
+                $totalRow[] = $colTotals[$issue];
+                $accumulator += $colTotals[$issue];
+            }
+        }
+        $totalRow[] = $accumulator;
+        $data .= $this->sputcsv($totalRow);
+
+        return $data;
+    }
+
+    /**
+     * Handles converting the 'Condition by Landlord' report to a CSV file
+     * Uses the same DB query as REPORTconditionbylandlord from GETReport.php
+     */
+    private function CSVconditionbylandlord() {
+        // Get date range from user
+        $start_date = strtotime($_REQUEST['start_date']);
+        $end_date = strtotime($_REQUEST['end_date']) + 86400;   // +1 day to make date range inclusive
+
+        $landlords = "SELECT * FROM slc_landlord";
+        $db = new PHPWS_DB();
+        $landlords = $db->select(null, $landlords);
+        $landlordnames = array();
+        foreach( $landlords as $landlord )
+            $landlordnames[] = $landlord['name'];
+
+        $issues = "SELECT * FROM slc_problem WHERE type LIKE 'Conditions' "; // Covers generic landlord-tenant, too
+        $db = new PHPWS_DB();
+        $issues = $db->select(null, $issues);
+        $issuenames = array();
+        foreach( $issues as $issue )
+            $issuenames[] = $issue['description'];
+        $issuenames[] = "Conditions";
+
+        // Get the issues listed ( all others 0 )
+        $db = new PHPWS_DB();
+        $db->addTable('slc_issue');
+        $db->addTable('slc_problem');
+        $db->addTable('slc_landlord');
+        $db->addTable('slc_visit');
+        $db->addTable('slc_visit_issue_index');
+        $db->addColumn('slc_problem.description');
+        $db->addColumn('slc_landlord.name');
+
+        // 1st Join set
+        // needs to be a left join to allow for landlord "not specified" which is recorded as NULL in DB
+        $db->addJoin('left', 'slc_issue', 'slc_landlord', 'landlord_id', 'id');
+
+        // 2nd Join set
+        $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id');
+        $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id');
+        $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id');
+
+        // WHERE (type LIKE "Conditions" OR description LIKE "Conditions") AND initial_date BETWEEN $start_date AND $end_date
+        $db->addWhere('slc_problem.type', 'Conditions', 'LIKE', NULL, 'conditions');
+        $db->addWhere('slc_problem.description', 'Conditions', 'LIKE', 'OR', 'conditions');
+        $db->addWhere('slc_visit.initial_date', $start_date, '>=', 'AND');
+        $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND');
+        $results = $db->select();
+
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+
+        $theMatrix = $landlordnames;
+        foreach($landlordnames as $lname) {
+            $theMatrix[$lname] = $issuenames;
+            foreach($issuenames as $iname)
+                $theMatrix[$lname][$iname] = 0; // Populate with 0s 
+        }
+
+        foreach( $results as $r ) {
+            // If landlord name is NULL, set as "Other / Unspecified"
+            $name = isset($r['name']) ? $r['name'] : "Other / Unspecified";
+            $description = $r['description'];
+
+            $theMatrix[$name][$description]++; // increment that value
+        }
+
+        // Create the final $data array
+        $data = $this->sputcsv(array_merge(array_merge(array(' '), $issuenames), array('Landlord Total')));
+
+        $colTotals = array();
+        foreach ($landlordnames as $landlord) {
+            $row = array($landlord);
+            $accumulator = 0;
+            foreach ($issuenames as $issue) {
+                $value = $theMatrix[$landlord][$issue];
+                $row[] = $value;
+                $accumulator += $value;
+                if (!array_key_exists($issue, $colTotals)) {
+                    $colTotals[$issue] = 0;
+                }
+                $colTotals[$issue] += $value;
+            }
+            $row[] = $accumulator;
+            $data .= $this->sputcsv($row);
+        }
+
+        $totalRow = array('Issue Totals');
+        $accumulator = 0;
+        foreach ($issuenames as $issue) {
+            if (array_key_exists($issue, $colTotals)) {
+                $totalRow[] = $colTotals[$issue];
+                $accumulator += $colTotals[$issue];
+            }
+        }
+        $totalRow[] = $accumulator;
+        $data .= $this->sputcsv($totalRow);
+
+        return $data;
+    }
+}
+?>
diff --git a/class/ajax/GETClientData.php b/class/ajax/GETClientData.php
new file mode 100644
index 0000000..616dc4d
--- /dev/null
+++ b/class/ajax/GETClientData.php
@@ -0,0 +1,104 @@
+addResult("msg", "No ID Supplied");
+//			throw new IDNotSuppliedException();
+			return;
+		}
+
+		$client = new Client();
+		
+		// check if it's already encoded
+		if ( !startsWith($_REQUEST['banner_id'], "$") ) {			
+			 
+	        unset($_SESSION['cname']);
+			
+			// Grab extra information from ASU Database
+	        $db = new PHPWS_DB('slc_student_data');
+			$db->addWhere("id", $_REQUEST['banner_id']);
+	        $results = $db->loadObject($tClient);
+	        
+	        if(PHPWS_Error::logIfError($results)){
+	            throw new DatabaseException();
+	        	$this->addResult("msg", "Database Exception");
+		        return;
+	        }
+	
+	        if ( !$results ) {
+	        	$this->addResult("msg", "Client not in ASU Database");
+	        	return;
+	        }
+	       
+	        
+	        // Store the name in session, as after the banner is encrypted, there's no way to get it
+	        $_SESSION['cname'] = serialize($tClient->fname . ' ' . $tClient->lname);
+	        
+	        // encode banner
+	        $_REQUEST['banner_id'] = encode($_REQUEST['banner_id']);
+		}
+			
+		$banner = $_REQUEST['banner_id'];
+		
+		//$client = new Client($banner);
+        $client->id = $banner;
+		
+       
+        
+		// check that client exists in database
+		$db = new PHPWS_DB($this->_table);
+        $results = $db->loadObject($client);
+        
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        	$this->addResult("msg", "Database Exception");
+	        return;
+        }
+
+        if ( !$results ) {
+        	$this->addResult("msg", "Client does not exist");
+       	
+        	// create new client
+        	$ajax = AjaxFactory::get("newClient");
+			$ajax->loadCall("POSTNewClient");
+			$ajax->setData(array("classification"=>$tClient->classification, "major"=>$tClient->major, "living_location"=>$tClient->living_location));
+			$ajax->execute();
+			$client = $ajax->result();
+		
+			$client = $client['client'];
+			$this->addResult('newFlag', true);
+        } else
+        	$this->addResult('newFlag', false);
+        $client->fname = $tClient->fname;
+        $client->lname = $tClient->lname;
+        $client->name = $client->fname . ' ' . $client->lname;
+       
+        // Check if existing client has referral set
+        if ( isset($client->referral) ) {
+        	// Add actual text of referral into client
+        	$query = 'SELECT * '.
+        			' FROM slc_referral_type '.
+        			' WHERE id=' . $client->referral;
+	        
+	        $db = new PHPWS_DB();
+	        //$db->setTestMode();
+	        $results = $db->select(null, $query);
+	        
+	        if(PHPWS_Error::logIfError($results)){
+	            throw new DatabaseException();
+	        }
+        	//test($results);
+        	$client->referralString = $results[0]["name"]; 
+        	$this->addResult('referralSet', true);
+        } else
+        	$this->addResult('referralSet', false);
+        
+        
+        $this->addResult("client", $client);
+        
+	}
+}
diff --git a/class/ajax/GETClientVisits.php b/class/ajax/GETClientVisits.php
new file mode 100644
index 0000000..2f9d2e9
--- /dev/null
+++ b/class/ajax/GETClientVisits.php
@@ -0,0 +1,98 @@
+addResult("msg", "No ID Supplied");
+//			throw new IDNotSuppliedException();
+			return;
+		}
+
+		$banner = $_REQUEST['banner_id'];
+		
+		$client = new Client($banner);
+		
+		// check that client exists in database, if not create
+		$db = new PHPWS_DB("slc_client");
+        $results = $db->loadObject($client);
+        
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+
+        if ( !$results ) {
+        	$this->addResult("msg", "Client does not exist");
+	        return;
+        }
+        
+        $query = 'SELECT v.id as "VISITID", v.initial_date as "INITIALDATE"'.
+        			' FROM slc_visit as v'.
+        			' WHERE v.c_id = "'.$client->id.'"';
+        
+        $db = new PHPWS_DB();
+		//$db->setTestMode();
+        $results = $db->select(null, $query);
+        
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+
+        $visits = null;
+        //test($results);
+        foreach( $results as $r ) { // visits
+        	$vid = $r['VISITID'];
+        	
+        	if (!isset($visits[$vid])) {
+        	//	test("Creating new visit for id: ".$vid);
+        		$visits[$vid] = new Visit();
+        	}
+        	
+        	$visit = $visits[$vid];
+        	$visit->id = $vid;
+        	$visit->initial_date = $r['INITIALDATE'];
+        	$visit->client_id = $client->id;
+        	
+        	        	
+        	
+        	// issues
+	        $query = 'SELECT vii.id AS "VIIID", p.description AS "ISSUENAME", l.name as "LANDLORDNAME", i.landlord_id as "LANDLORDID", i.problem_id as "PROBLEMID", vii.i_id AS "ISSUEID", vii.counter AS "COUNTER", vii.resolve_date AS "RESOLVEDATE", vii.last_access AS "LASTACCESS"'.
+	        			' FROM slc_visit_issue_index as vii'.
+						' INNER JOIN slc_issue i ON vii.i_id=i.id'.
+	        			' INNER JOIN slc_problem p ON i.problem_id=p.id'.
+	        			' LEFT JOIN (slc_landlord l) ON (i.landlord_id = l.id)'.
+						' WHERE vii.v_id = "'.$vid.'"';
+	        
+	        
+	        $db = new PHPWS_DB();
+			$iresults = $db->select(null, $query);
+	        
+	        if(PHPWS_Error::logIfError($results)){
+	            throw new DatabaseException();
+	        }
+        	
+        	foreach( $iresults as $ir ) { // visits
+        		// set up issue
+	        	$issue = new Issue($ir['ISSUEID']);
+	        	$issue->name = $ir['ISSUENAME'];
+	        	$issue->last_access = $ir['LASTACCESS'];
+				$issue->counter = $ir['COUNTER'];
+				$issue->resolution_date = $ir['RESOLVEDATE'];
+				$issue->visit_issue_id = $ir['VIIID'];
+				$issue->problem_id = $ir['PROBLEMID'];
+				$issue->landlord_id = $ir['LANDLORDID'];
+				$issue->landlord_name = (isset($issue->landlord_id)) ? " with ".$ir['LANDLORDNAME'] : null;
+
+	        	// add issue
+	        	$visit->addIssue($issue);
+        	}
+        	
+        	//test($visit);
+        	
+        	//$visits[$vid] = $visit;
+        }
+        
+        $this->addResult("visits", $visits);       
+	}
+}
+?>
diff --git a/class/ajax/GETReferralBox.php b/class/ajax/GETReferralBox.php
new file mode 100644
index 0000000..7a1a854
--- /dev/null
+++ b/class/ajax/GETReferralBox.php
@@ -0,0 +1,27 @@
+setTestMode();
+        $results = $db->select(null, $query);
+        
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+        
+		$rTypes = array();
+        foreach( $results as $r ) { // types
+        	$rTypes[] = array("REFERRAL_ID" => $r['id'], "NAME"=>$r['name']);
+        }
+		
+        $referralPicker = PHPWS_Template::process(array("referrals"=>$rTypes), 'slc', 'ReferralPicker.tpl');
+        
+	    $this->addResult("referral_picker", $referralPicker);    
+	}
+}
diff --git a/class/ajax/GETReport.php b/class/ajax/GETReport.php
new file mode 100644
index 0000000..4e7279d
--- /dev/null
+++ b/class/ajax/GETReport.php
@@ -0,0 +1,869 @@
+addResult("msg", "No Report Type Supplied");
+			// throw new ReportTypeNotSuppliedException();
+			return;
+		}
+		
+		$reportHTML = "";
+		
+		$func = 'REPORT'.$_REQUEST['report_type'];
+
+		if ( method_exists("GETReport", $func) )
+			$reportHTML .= call_user_func(array("GETReport", $func));
+		else 
+			$reportHTML .= "The selected report type (".$_REQUEST['report_type'].") is not yet implemented in this version";
+			
+		$this->addResult('report_html', $reportHTML);
+	}
+
+	function REPORTstudentsseen() {
+		$query = "SELECT "; 
+		$query .= "(SELECT COUNT(DISTINCT id) FROM slc_visit) AS visits, ";
+		$query .= "(SELECT COUNT(DISTINCT id) FROM slc_client) AS clients, ";
+		$query .= "(SELECT COUNT(DISTINCT id) FROM slc_issue) AS issues, ";
+		$query .= "(SELECT SUM(counter) FROM slc_visit_issue_index) AS followups ";
+		
+		$db = new PHPWS_DB();
+        //$db->setTestMode();
+        $results = $db->select(null, $query);
+        
+        if(PHPWS_Error::logIfError($results)){
+            throw new DatabaseException();
+        }
+        
+        $results = $results[0]; // since it's a count, should always return a number
+        $visits = $results['visits'];
+        $clients = $results['clients'];
+        $issues = $results['issues'];
+        $followups = $results['followups'] - $issues; // Every issue has at least one visit, so remove initial
+        
+        $bgcolor = array(0=>"#FFFFFF",1=>"#FFEC8B");
+        $r = 0;
+        
+        $html = "";
+        $html .= "";
+        $html .= "";
+        $html .= ""; $r = !$r;
+        $html .= ""; $r = !$r;
+        $html .= ""; $r = !$r;
+        $html .= ""; $r = !$r;
+        $html .= ""; $r = !$r;
+        $html .= ""; $r = !$r;
+        $html .= "
SituationRecord
Total Visits".$visits."
Total Clients".$clients."
Total Issues".$issues."
Visits per Client".(round($visits/$clients,2))."
Issues per Visit".(round($issues/$visits,2))."
Followups per Issue".(round($followups/$issues, 2))."
"; + + return $html; + } + + /** + * This method builds the Intake by Problem Type report. + */ + private function REPORTintakebyproblemtype() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + // Get the list of all Landlord-Tenant type problems + $db = new PHPWS_DB('slc_problem'); + $db->addColumn('description'); + $db->addWhere('type', 'Landlord-Tenant', 'LIKE'); + $landlord = $db->select(); + + if(PHPWS_Error::logIfError($landlord)){ + throw new DatabaseException(); + } + + // Get the list of all Conditions type problems + $db = new PHPWS_DB('slc_problem'); + $db->addColumn('description'); + $db->addWhere('type', 'Conditions', 'LIKE'); + $conditions = $db->select(); + + if(PHPWS_Error::logIfError($conditions)){ + throw new DatabaseException(); + } + + $db = new PHPWS_DB(); + $db->addTable('slc_issue'); + $db->addTable('slc_problem'); + $db->addTable('slc_visit'); + $db->addTable('slc_visit_issue_index'); + $db->addColumn('slc_issue.id', NULL, 'count', TRUE, TRUE); + $db->addColumn('slc_problem.description'); + $db->addJoin('inner', 'slc_issue', 'slc_problem', 'problem_id', 'id'); + $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id'); + $db->addJoin('inner', 'slc_visit', 'slc_visit_issue_index', 'id', 'v_id'); + $db->addWhere('slc_visit.initial_date', $start_date, '>='); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $db->addGroupBy('slc_issue.problem_id'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + /* + * Remove all Landlord-Tenant and Conditions type problems from the main + * results array, seperate them into individual arrays, and tally the + * number of problems recorded for each. Also grab the generic + * Landlord-Tenant and Conditions types, tally their occurences, and put + * them at the head of the proper set of results. + */ + $landlordCount = 0; + $conditionsCount = 0; + $landlordResults = array(array('description'=>'Landlord-Tenant', 'count'=>$landlordCount)); + $conditionsResults = array(array('description'=>'Conditions', 'count'=>$conditionsCount)); + + // Find generic problem types first and list them as the first sub-type + foreach($results as $key=>$r) { + if ($r['description'] == 'Landlord-Tenant') { // generic type + $r['description'] = 'Generic Landlord-Tenant'; + $landlordResults[] = $r; + $landlordCount += $r['count']; + unset($results[$key]); + } elseif ($r['description'] == 'Conditions') { // generic type + $r['description'] = 'Generic Condition'; + $conditionsResults[] = $r; + $conditionsCount += $r['count']; + unset($results[$key]); + } + } + + foreach($results as $key=>$r) { + if(in_array(array('description'=>$r['description']), $landlord, TRUE)) { + $landlordResults[] = $results[$key]; + $landlordCount += $r['count']; + unset($results[$key]); + } elseif (in_array(array('description'=>$r['description']), $conditions, TRUE)) { + $conditionsResults[] = $results[$key]; + $conditionsCount += $r['count']; + unset($results[$key]); + } + } + + // re-index the main results array now that we have removed all landlord and conditions results + $results = array_values($results); + + // If there are Conditions type problems, nest them in the Landlord-Tenant + // results and include their total occurences in the Landlord-Tenant count. + if ($conditionsCount > 0) { + $conditionsResults[0]['count'] = $conditionsCount; + + // Use the generic Conditions problem as the main line for all Conditions problems + $landlordResults[] = $conditionsResults[0]; + $landlordCount += $conditionsCount; + $landlordResults[0]['count'] = $landlordCount; + unset($conditionsResults[0]); + + // Indent all sub-types of Conditions problems + foreach ($conditionsResults as $r3) { + $string = "-> " . $r3['description']; + $landlordResults[] = array('description'=>$string, 'count'=>$r3['count']); + } + } + + // If there are Landlord-Tenant type problems, nest them in the main results array + if ($landlordCount > 0) { + $landlordResults[0]['count'] = $landlordCount; + + // Use the generic Landlord-Tenant problem as the main line for all Landlord-Tenant problems + $results[] = $landlordResults[0]; + unset($landlordResults[0]); + + // Indent all sub-types of Landlord-Tenant problems + foreach ($landlordResults as $r2) { + if (substr($r2['description'], 0, 2) === '->') { + // Don't add a second '-> ' to Conditions type problems + $string = "     " . $r2['description']; + } else { + $string = "-> " . $r2['description']; + } + $results[] = array('description'=>$string, 'count'=>$r2['count']); + } + } + + $html = ""; + + if (count($results) != 0) { // Return the empty string if there are no results + $html .= ""; + $html .= ""; + $bgcolor = array(0=>"#FFFFFF",1=>"#FFEC8B"); + $rc = 0; + $total = 0; + + foreach( $results as $r ) { + $count = $r['count']; + + // Don't include counts for sub-categories in the total count, we have already counted those. + if (strpos($r['description'], '->') === FALSE) { + $total += $count; + } + + $type = $r['description']; + + $html .= ""; + $rc = !$rc; + } + + // Add a final row with the total # of problems + $html .= ""; + $html .= "
SituationRecord
".$type."".$count."
Total Number Of Problems".$total."
"; + } + + return $html; + } + + private function REPORTlandlordtenant() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $landlords = "SELECT * FROM slc_landlord"; + $db = new PHPWS_DB(); + $landlords = $db->select(null, $landlords); + $landlordnames = array(); + foreach( $landlords as $landlord ) + $landlordnames[] = $landlord['name']; + + $issues = "SELECT * FROM slc_problem WHERE tree LIKE '%Landlord-Tenant%' OR description LIKE 'Conditions' OR description LIKE 'Landlord-Tenant' "; // Covers generic landlord-tenant, too + $db = new PHPWS_DB(); + $issues = $db->select(null, $issues); + $issuenames = array(); + foreach( $issues as $issue ) + $issuenames[] = $issue['description']; + + + // Get the issues listed ( all others 0 ) + $db = new PHPWS_DB(); + $db->addTable('slc_issue'); + $db->addTable('slc_problem'); + $db->addTable('slc_landlord'); + $db->addTable('slc_visit'); + $db->addTable('slc_visit_issue_index'); + $db->addColumn('slc_problem.description'); + $db->addColumn('slc_landlord.name'); + + // 1st Join set + // needs to be a left join to allow for landlord "not specified" which is recorded as NULL in DB + $db->addJoin('left', 'slc_issue', 'slc_landlord', 'landlord_id', 'id'); + + // 2nd Join set + $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id'); + $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id'); + $db->addWhere('slc_visit.initial_date', $start_date, '>='); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $theMatrix = $landlordnames; + foreach($landlordnames as $lname) { + $theMatrix[$lname] = $issuenames; + foreach($issuenames as $iname) + $theMatrix[$lname][$iname] = 0; // Populate with 0s + } + + + foreach( $results as $r ) { + // If landlord name is NULL, set as "Other / Unspecified" + $name = isset($r['name']) ? $r['name'] : "Other / Unspecified"; + $description = $r['description']; + + if ( !array_key_exists($description,$theMatrix[$name]) ) + $theMatrix[$name][$description] = 0; + + $theMatrix[$name][$description]++; // increment that value + } + + // Row Colors + $stripes = array(0=>"255,255,255",1=>"255,236,139"); + $zebra = 0; + + $html = ""; + + // Header Row + $html .= ""; + $col = 1; + foreach ($issuenames as $issue) { + $html .= ""; + } + $html .= ""; + + // Table Body + $colTotals = array(); + $row = 1; + foreach ($landlordnames as $landlord) { + $col = 0; + $html .= ""; + + $rowTotal = 0; + foreach ($issuenames as $issue) { + $value = $theMatrix[$landlord][$issue]; + $style = ($value == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + + $html .= ""; + $rowTotal += $value; + + // Increment the column total + if (array_key_exists($issue, $colTotals)) { + $colTotals[$issue] += $value; + } else { + $colTotals[$issue] = $value; + } + } + + $html .= ""; + + $row++; + $zebra = !$zebra; // flip the row color + } + + // Condition Totals Row + $html .= ""; + $col = 1; + $rowTotal = 0; + foreach ($colTotals as $val) { + $html .= ""; + $rowTotal += $val; + } + $html .= ""; + + + $html .= "
" . $issue . "Landlord Total
" . $landlord . "" . $value . "" . $rowTotal . "
Condition Total" . $val . "" . $rowTotal . "
"; + return $html; + } + + private function REPORTconditionbylandlord() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $landlords = "SELECT * FROM slc_landlord"; + $db = new PHPWS_DB(); + $landlords = $db->select(null, $landlords); + $landlordnames = array(); + foreach( $landlords as $landlord ) + $landlordnames[] = $landlord['name']; + + $issues = "SELECT * FROM slc_problem WHERE type LIKE 'Conditions' "; // Covers generic landlord-tenant, too + $db = new PHPWS_DB(); + $issues = $db->select(null, $issues); + $issuenames = array(); + foreach( $issues as $issue ) + $issuenames[] = $issue['description']; + $issuenames[] = "Conditions"; + + // Get the issues listed ( all others 0 ) + $db = new PHPWS_DB(); + $db->addTable('slc_issue'); + $db->addTable('slc_problem'); + $db->addTable('slc_landlord'); + $db->addTable('slc_visit'); + $db->addTable('slc_visit_issue_index'); + $db->addColumn('slc_problem.description'); + $db->addColumn('slc_landlord.name'); + + // 1st Join set + // needs to be a left join to allow for landlord "not specified" which is recorded as NULL in DB + $db->addJoin('left', 'slc_issue', 'slc_landlord', 'landlord_id', 'id'); + + // 2nd Join set + $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id'); + $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id'); + + // WHERE (type LIKE "Conditions" OR description LIKE "Conditions") AND initial_date BETWEEN $start_date AND $end_date + $db->addWhere('slc_problem.type', 'Conditions', 'LIKE', NULL, 'conditions'); + $db->addWhere('slc_problem.description', 'Conditions', 'LIKE', 'OR', 'conditions'); + $db->addWhere('slc_visit.initial_date', $start_date, '>=', 'AND'); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + $html = ""; + + $theMatrix = $landlordnames; + foreach($landlordnames as $lname) { + $theMatrix[$lname] = $issuenames; + foreach($issuenames as $iname) + $theMatrix[$lname][$iname] = 0; // Populate with 0s + } + + + foreach( $results as $r ) { + // If landlord name is NULL, set as "Other / Unspecified" + $name = isset($r['name']) ? $r['name'] : "Other / Unspecified"; + $description = $r['description']; + + $theMatrix[$name][$description]++; // increment that value + } + + // Row Colors + $stripes = array(0=>"255, 255, 255", 1=>"255, 236, 139"); + $zebra = 0; + + $html .= ""; + + // Header Row + $html .= ""; + $col = 1; + foreach ($issuenames as $issue) { + $html .= ""; + } + $html .= ""; + + // Table Body + $colTotals = array(); + $row = 1; + foreach ($landlordnames as $landlord) { + $col = 0; + $html .= ""; + + $rowTotal = 0; + foreach ($issuenames as $issue) { + $value = $theMatrix[$landlord][$issue]; + $style = ($value == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + + $html .= ""; + $rowTotal += $value; + + // Increment the column total + if (array_key_exists($issue, $colTotals)) { + $colTotals[$issue] += $value; + } else { + $colTotals[$issue] = $value; + } + } + + $html .= ""; + + $row++; + $zebra = !$zebra; // flip the row color + } + + // Condition Totals Row + $html .= ""; + $col = 1; + $rowTotal = 0; + foreach ($colTotals as $val) { + $html .= ""; + $rowTotal += $val; + } + $html .= ""; + + + $html .= "
" . $issue . "Landlord Total
" . $landlord . "" . $value . "" . $rowTotal . "
Condition Total" . $val . "" . $rowTotal . "
"; + return $html; + } + + private function REPORTproblembyyear() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $db = new PHPWS_DB(); + $db->addTable('slc_visit_issue_index'); + $db->addTable('slc_visit'); + $db->addTable('slc_client'); + $db->addTable('slc_issue'); + $db->addTable('slc_problem'); + $db->addColumn('slc_client.classification'); + $db->addColumn('slc_problem.description'); + $db->addColumn('slc_problem.tree'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id'); + $db->addJoin('inner', 'slc_visit', 'slc_client', 'c_id', 'id'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_issue', 'i_id', 'id'); + $db->addJoin('inner', 'slc_issue', 'slc_problem', 'problem_id', 'id'); + $db->addWhere('slc_visit.initial_date', $start_date, '>='); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + // return an "empty" message if $results is empty + if (count($results) == 0) { + $html = "There are no records for that time period."; + return $html; + } + + $html = ""; + + $theMatrix = array(); + $problems = array(); + $years = array(); + + /* + * For each row where the type is Conditions or Landlord-Tenant, change + * the type to a generic Landlord-Tenant problem. + */ + foreach ($results as $key=>$r) { + if (isset($r['description']) && ($r['description'] == 'Conditions')) { + $results[$key]['description'] = 'Landlord-Tenant'; + $results[$key]['tree'] = ''; + } + if (isset($r['tree']) && ($r['tree'] == 'Landlord-Tenant -> ' || $r['tree'] == 'Landlord-Tenant -> Condition -> ')) { + $results[$key]['description'] = 'Landlord-Tenant'; + $results[$key]['tree'] = ''; + } + } + + // Replace the 'FR' with 'Freshman', 'SO' with 'Sophomore', and so on + foreach ($results as $key=>$val) { + switch ($val['classification']) { + case 'FR': + $results[$key]['classification'] = 'Freshman'; + break; + case 'SO': + $results[$key]['classification'] = 'Sophomore'; + break; + case 'JR': + $results[$key]['classification'] = 'Junior'; + break; + case 'SR': + $results[$key]['classification'] = 'Senior'; + break; + case '': + $results[$key]['classification'] = 'Other'; + break; + default: + break; + } + } + + foreach( $results as $r ) { + if ( !in_array($r['classification'], $years) ) { + $years[] = $r['classification']; + } + } + + // Sort the 'years' array + $classes = array('Freshman', 'Sophomore', 'Junior', 'Senior', 'Other'); + $tempArray = array_intersect($classes, $years); + $years = array_unique(array_merge($tempArray, $years)); + + foreach( $results as $r ) { + + $description = isset($r['description']) && isset($r['tree']) ? $r['tree'].' '.$r['description'] : "not specified"; + $year = $r['classification']; + + if ( !in_array($description, $problems) ) + $problems[] = $description; + + if ( isset($theMatrix[$description]) ) { + $theMatrix[$description][$year]++; + } else { + $theMatrix[$description] = array(); + foreach ($years as $tempyear) { + $theMatrix[$description][$tempyear] = 0; + } + + $theMatrix[$description][$year] = 1; + } + } + + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 0; + + $html .= ""; + $html .= ""; + + // Total the columns + $totals = array_flip($years); + foreach ($totals as $key=>$val) { + $totals[$key] = 0; + } + + foreach ( $years as $year ) { + $html .= ""; + } + $html .= ""; + foreach ( $problems as $description ) { + $html .= ""; + $html .= ""; + $prevCount = 0; + foreach ( array_keys($theMatrix[$description]) as $year ) { + $html .= ""; + + if ($theMatrix[$description][$year] != 0) { + $totals[$year] += $theMatrix[$description][$year]; + } + } + + $html .= ""; + $rc = !$rc; + } + $html .= ""; + foreach ($totals as $total) { + $html .= ""; + } + $html .= ""; + $html .= "
Problem Type ".$year." 
".$description.""; + $html .= ($theMatrix[$description][$year] != 0) ? $theMatrix[$description][$year] : '0'; + $html .= "
Totals".$total."
"; + + return $html; + } + + /** + * This method builds the Appointment Statistics report. + */ + private function REPORTfollowupappts() { + $initialVisits = 0; + $clients = 0; + $issues = 0; + $followups = 0; + + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + // Get the array of all visits whose initial visit happened in the time period. Equivalent to this query: + // SELECT DISTINCT(id) FROM slc_visit WHERE initial_date >= $start_date AND initial_date < $end_date; + $db = new PHPWS_DB('slc_visit'); + $db->addColumn('id', null, null, null, true); + $db->addWhere('initial_date', $start_date, '>='); + $db->addwhere('initial_date', $end_date, '<', 'AND'); + $visitIds = $db->select('col'); + + // Get # of initial visits. Equivalent to this query: + // SELECT COUNT(DISTINCT(v_id)) FROM slc_visit_issue_index + // WHERE v_id IN $visitIds; + $db = new PHPWS_DB('slc_visit_issue_index'); + $db->addColumn('v_id', null, null, true, true); + $db->addWhere('v_id', $visitIds, 'IN', 'AND'); + $initialVisits = $db->select('one'); + + // Get the array of different 'counts' greater than 1. Equivalent to this query: + // SELECT DISTINCT(counter) FROM slc_visit_issue_index WHERE counter>'1' ORDER BY counter DESC; + $db->reset(); + $db->addColumn('counter', null, null, null, true); + $db->addWhere('counter', '1', '>'); + $db->addOrder('counter desc'); + $counters = $db->select('col'); + + //TODO: Make followups only count if they occured during the time period. + // As of 05/20/2013 this is impossible due to the structure of the DB. We need to track when each followup occured. + // For now we just count all followups for visits whose initial visit took place within the time period. + + // Calculate the number of followup visits. + $visits = array(); + $db = new PHPWS_DB('slc_visit_issue_index'); + $db->addColumn('v_id', null, null, null, true); + foreach ($counters as $count) { + $db->addWhere('v_id', $visitIds, 'IN'); + + // Make sure you don't count visits with multiple issues if they've already been counted. + if (!empty($visits)) { + $db->addWhere('v_id', $visits, 'NOT IN', 'AND'); + } + + $db->addWhere('counter', $count, '=', 'AND'); + $result = $db->select('col'); + $visits = $visits + $result; + $followups += ($count-1) * count($result); + $db->resetWhere(); + } + + // Get # of clients. Equivalent to this query: + // SELECT COUNT(DISTINCT(id)) FROM slc_client + // WHERE first_visit >= $start_date AND first_visit < $end_date; + $db = new PHPWS_DB('slc_client'); + $db->addColumn('id', null, null, true, true); + $db->addWhere('first_visit', $start_date, '>='); + $db->addWhere('first_visit', $end_date, '<', 'AND'); + $clients = $db->select('one'); + + // Get # of issues. Equivalent to this query: + // SELECT COUNT(DISTINCT(id)) FROM slc_issue + // JOIN slc_visit_issue_index ON slc_issue.id = slc_visit_issue_index.i_id + // WHERE slc_visit_issue_index.v_id IN $visitIds; + $db = new PHPWS_DB('slc_issue'); + $db->addColumn('id', null, null, true, true); + $db->addTable('slc_visit_issue_index', 'svii'); + $db->addWhere('slc_issue.id', 'svii.i_id'); + $db->addWhere('svii.v_id', $visitIds, 'IN', 'AND'); + $issues = $db->select('one'); + + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 0; + + $html = ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + if ($clients == 0) { // If $clients == 0, then all the statistics will be 0 + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + } else { + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + $html .= ""; + } + $html .= "
CategoryStatistic
Total Clients ".$clients."
Total Issues ".$issues."
Total Initial Visits ".$initialVisits."
Total Followups ".$followups."
Issues per Visit (w/o Followups)0
Visits per Client (w/o Followups)0
Visits per Client (with Followups)0
Followups per Issue 0
Followups per Visit 0
Issues per Visit (w/o Followups)" . round($issues / $initialVisits, 2) . "
Visits per Client (w/o Followups)" . round($initialVisits / $clients, 2) . "
Visits per Client (with Followups)" . round(($initialVisits + $followups) / $clients, 2) . "
Followups per Issue " . round($followups / $issues, 2) . "
Followups per Visit " . round($followups / $initialVisits, 2) . "
"; + + return $html; + } + + + private function REPORTtypeofcondition() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $db = new PHPWS_DB('slc_problem'); + $db->addColumn('slc_problem.description', NULL, 'descript'); + $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id'); + $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id'); + $db->addWhere('slc_problem.type', 'Conditions', 'LIKE'); + $db->addWhere('slc_visit.initial_date', $start_date, '>=', 'AND'); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + // return an "empty" message if $results is empty + if (count($results) == 0) { + $html = "There are no records for that time period."; + return $html; + } + + $conditions = array(); + + foreach ($results as $r) { + if ( !array_key_exists($r['descript'], $conditions) ) + $conditions[$r['descript']] = 1; + else + $conditions[$r['descript']]++; + } + + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 1; + + $html = ""; + $html .= ""; + + foreach($conditions as $k=>$c) + $html .= ""; + + $html .= "
CategoryStatistic
".$k."".$c."
"; + + return $html; + } + + + private function REPORTtypeofreferral() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $db = new PHPWS_DB('slc_referral_type'); + $db->addColumn('name'); + $db->addWhere('id', 'slc_client.referral'); + $db->addWhere('slc_client.first_visit', $start_date, '>=', 'AND'); + $db->addWhere('slc_client.first_visit', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + // return an "empty" message if $results is empty + if (count($results) == 0) { + $html = "There are no records for that time period."; + return $html; + } + + $referrals = array(); + + foreach ($results as $r) { + if ( $r['name'] != '') + if ( !array_key_exists($r['name'], $referrals) ) + $referrals[$r['name']] = 1; + else + $referrals[$r['name']]++; + } + + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 1; + + $html = ""; + $html .= ""; + + foreach($referrals as $k=>$c) + $html .= ""; + + $html .= "
Referral TypeStatistic
".$k."".$c."
"; + + return $html; + } + + + private function REPORTlawbyagency() { + // Get date range from user + $start_date = strtotime($_REQUEST['start_date']); + $end_date = strtotime($_REQUEST['end_date']) + 86400; // +1 day to make date range inclusive + + $db = new PHPWS_DB('slc_problem'); + $db->addColumn('slc_problem.description', NULL, 'agency'); + $db->addJoin('inner', 'slc_problem', 'slc_issue', 'id', 'problem_id'); + $db->addJoin('inner', 'slc_issue', 'slc_visit_issue_index', 'id', 'i_id'); + $db->addJoin('inner', 'slc_visit_issue_index', 'slc_visit', 'v_id', 'id'); + $db->addWhere('slc_problem.type', 'Law Enforcement Agency', 'LIKE'); + $db->addWhere('slc_visit.initial_date', $start_date, '>=', 'AND'); + $db->addWhere('slc_visit.initial_date', $end_date, '<', 'AND'); + $results = $db->select(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + // return an "empty" message if $results is empty + if (count($results) == 0) { + $html = "There are no records for that time period."; + return $html; + } + + $agencies = array(); + + foreach ($results as $r) { + if ( !array_key_exists($r['agency'], $agencies) ) + $agencies[$r['agency']] = 1; + else + $agencies[$r['agency']]++; + } + + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 1; + + $html = ""; + $html .= ""; + + foreach($agencies as $k=>$c) + $html .= ""; + + $html .= "
AgencyStatistic
".$k."".$c."
"; + + return $html; + } + +} diff --git a/class/ajax/GETReportBox.php b/class/ajax/GETReportBox.php new file mode 100644 index 0000000..d44fe51 --- /dev/null +++ b/class/ajax/GETReportBox.php @@ -0,0 +1,32 @@ + $v ) { // types + $rTypes[] = array("VALUE" => $r, "NAME"=>$v); + } + + $reportPicker = PHPWS_Template::process(array("reports"=>$rTypes), 'slc', 'ReportPicker.tpl'); + + $this->addResult("report_picker", $reportPicker); + } +} +?> diff --git a/class/ajax/GETReporthalfway.php b/class/ajax/GETReporthalfway.php new file mode 100644 index 0000000..d33bc62 --- /dev/null +++ b/class/ajax/GETReporthalfway.php @@ -0,0 +1,209 @@ +addResult("msg", "No Report Type Supplied"); + // throw new ReportTypeNotSuppliedException(); + return; + } + + $reportHTML = ""; + + $func = 'REPORT'.$_REQUEST['report_type']; + + if ( method_exists("GETReport", $func) ) + $reportHTML .= call_user_func(array("GETReport", $func)); + else + $reportHTML .= "The selected report type (".$_REQUEST['report_type'].") is not yet implemented in this version"; + + $this->addResult('report_html', $reportHTML); + } + + function REPORTstudentsseen() { + + $query = "SELECT "; + $query .= "(SELECT COUNT(DISTINCT id) FROM slc_visit) AS visits, "; + $query .= "(SELECT COUNT(DISTINCT id) FROM slc_client) AS clients, "; + $query .= "(SELECT COUNT(DISTINCT id) FROM slc_issue) AS issues, "; + $query .= "(SELECT SUM(counter) FROM slc_visit_issue_index) AS followups "; + + $db = new PHPWS_DB(); + //$db->setTestMode(); + $results = $db->select(null, $query); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $results = $results[0]; // since it's a count, should always return a number + $visits = $results['visits']; + $clients = $results['clients']; + $issues = $results['issues']; + $followups = $results['followups'] - $issues; // Every issue has at least one visit, so remove initial + + $bgcolor = array(0=>"#FFFFFF",1=>"#FFEC8B"); + $r = 0; + + $html = ""; + $html .= ""; + $html .= ""; + $html .= ""; $r = !$r; + $html .= ""; $r = !$r; + $html .= ""; $r = !$r; + $html .= ""; $r = !$r; + $html .= ""; $r = !$r; + $html .= ""; $r = !$r; + $html .= "
SituationRecord
Total Visits".$visits."
Total Clients".$clients."
Total Issues".$issues."
Visits per Client".(round($visits/$clients,2))."
Issues per Visit".(round($issues/$visits,2))."
Followups per Issue".(round($followups/$issues, 2))."
"; + + return $html; + } + + private function REPORTintakebyproblemtype() { + $query = "SELECT COUNT(DISTINCT i.id) as count, p.description FROM slc_issue i, slc_problem p WHERE i.problem_id = p.id GROUP BY problem_id"; + + $db = new PHPWS_DB(); + //$db->setTestMode(); + $results = $db->select(null, $query); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $html = ""; + $html .= ""; + $html .= ""; + $bgcolor = array(0=>"#FFFFFF",1=>"#FFEC8B"); + $rc = 0; + + foreach( $results as $r ) { + $count = $r['count']; + $type = $r['description']; + + $html .= ""; + $rc = !$rc; + } + + $html .= "
SituationRecord
".$type."".$count."
"; + + return $html; + } + + //' (SELECT COUNT(DISTINCT id) FROM landlord) AS landlords, '. + //' (SELECT COUNT(DISTINCT id) FROM issue WHERE landlord_id IS NOT NULL) AS issues"; + + private function REPORTlandlordtenant() { + $landlords = "SELECT * FROM slc_landlord"; + $db = new PHPWS_DB(); + $landlords = $db->select(null, $landlords); + $landlordnames = array(); + foreach( $landlords as $landlord ) + $landlordnames[] = $landlord['name']; + $landlordnames[] = "not specified"; // Create a "NULL" row + + $issues = "SELECT * FROM slc_problem WHERE tree LIKE '%Landlord-Tenant%' OR description LIKE 'Conditions' OR description LIKE 'Landlord-Tenant' "; // Covers generic landlord-tenant, too + $db = new PHPWS_DB(); + $issues = $db->select(null, $issues); + $issuenames = array(); + foreach( $issues as $issue ) + $issuenames[] = $issue['description']; + + + // Get the issues listed ( all others 0 ) + $query = 'SELECT p.description, l.name '. + ' FROM slc_issue i '. + ' LEFT JOIN slc_problem p ON i.problem_id = p.id '. + ' LEFT JOIN slc_landlord l ON i.landlord_id = l.id '; + + $db = new PHPWS_DB(); + //$db->setTestMode(); + $results = $db->select(null, $query); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $theMatrix = $landlordnames; + foreach($landlordnames as $lname) { + $theMatrix[$lname] = $issuenames; + foreach($issuenames as $iname) + $theMatrix[$lname][$iname] = 0; // Populate with 0s + } + + + foreach( $results as $r ) { + //if(!isset($r['name'])){ + // continue; + //} + + $name = isset($r['name']) ? $r['name'] : "not specified"; + $description = $r['description']; + + $theMatrix[$name][$description]++; // increment that value + } + + + $html = ""; + $html .= "
"; + $html .= ""; //#E3E3E3 + $html .= "";//"; + $html .= '"; + $html .= ""; + + // generate rows + $bgcolor = array(0=>"255,255,255",1=>"255,236,139"); + $rc = 0; + $colTotals = array(); + $landlordHTML = ""; + foreach( $landlordnames as $landlord) { // ROWS! + $html .= ""; + $html .= "
 
'; + // generate issue headers + foreach( $issuenames as $issue ) { + $html .= ""; + } + $html .= "
$issueLandlord Total
"; + $html .= ""; + $rowtotal = 0; + + foreach ($issuenames as $issue) { // COLUMNS! + + $value = $theMatrix[$landlord][$issue]; + $vStyle = ($value == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + + $html .= ""; + $rowtotal += $value; + $colTotals[$issue] += $value; + } + + $vStyle = ($rowtotal == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + $html .= ""; + $html .= ""; + $rc = !$rc; // flip color + } + + $html .= ""; + $html .= ""; + $html .= ""; + foreach ($issuenames as $issue) { // COLUMNS! + $vStyle = ($colTotals[$issue] == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + $html .= ""; + $rowtotal += $colTotals[$issue]; + } + + $vStyle = ($rowtotal == 0) ? "color:#ABABAB;" : "color:#000000; font-weight:bold;"; + $html .= ""; + $html .= ""; + $html .= "
".$landlord.""; + $landlordHTML .= "
".$landlord."
 ".$value."".$rowtotal."
Issue Totals ".$colTotals[$issue]."".$rowtotal."
"; + + //$landlordHTML = "
".$landlordHTML."
"; + //$html .= $landlordHTML; + + return $html; // for current table + } + +// private function REPORTconditionbylandlord() { + +// } +} diff --git a/class/ajax/GETVisits.php b/class/ajax/GETVisits.php new file mode 100644 index 0000000..8e5af03 --- /dev/null +++ b/class/ajax/GETVisits.php @@ -0,0 +1,49 @@ +addResult("msg", "No ID Supplied"); +// throw new IDNotSuppliedException(); + return; + } + + // Encode the banner id right off -- use this from now on + $banner = encode($_REQUEST['banner_id']); + + // check that client exists in database, if not create + $db = new PHPWS_DB($this->_table); + $db->addWhere("id", $banner); + $results = $db->count(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + if ( $results == 0 ) { + $af = AJAXFactory::get("POSTNewClient"); + $af->loadCall("POSTNewClient"); // using the original since it will be encoded + $af->execute(); + if ( !$af->result() ) { + $this->addResult("msg", "Unable to add client"); + return; + } + } + + $this->result = array(); + + $db = new PHPWS_DB($this->_table); + $client = new Client($banner); + $results = $db->loadObject($client); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $this->addResult("client", $client); + $this->addResult("msg", $results); + + } +} +?> diff --git a/class/ajax/POSTIncrementVisit.php b/class/ajax/POSTIncrementVisit.php new file mode 100644 index 0000000..c32198c --- /dev/null +++ b/class/ajax/POSTIncrementVisit.php @@ -0,0 +1,55 @@ +addResult("msg", "No Visit_Issue ID Supplied"); +// throw new IDNotSuppliedException(); + return; + } + + $db = new PHPWS_DB($this->_table); + $db->addWhere('id', $_REQUEST['visit_issue_id']); + $results = $db->count(); + + if(PHPWS_Error::logIfError($results)){ + //throw new DatabaseException(); + $this->addResult("msg", "No Visit_Issue ID Supplied"); + return; + } + + if ( $results == 0 ) { + // Row does not exist + $this->addResult("msg", "Row does not exist"); + return; + } + + $visitIssue = new VisitIssue(); + $results = $db->loadObject($visitIssue); // load + + if(PHPWS_Error::logIfError($results)){ + //throw new DatabaseException(); + $this->addResult("msg", "No Visit_Issue ID Supplied"); + return; + } + + $visitIssue->counter++; // increment counter + $visitIssue->last_access = timestamp(); // TODO: Current Timestamp + + $results = $db->saveObject($visitIssue); // save + + if(PHPWS_Error::logIfError($results)){ + //throw new DatabaseException(); + $this->addResult("msg", "No Visit_Issue ID Supplied"); + return; + } + + $this->addResult("msg", $results); + $this->addResult("count", $visitIssue->counter); + } + +} + +?> diff --git a/class/ajax/POSTNewClient.php b/class/ajax/POSTNewClient.php new file mode 100644 index 0000000..2016e33 --- /dev/null +++ b/class/ajax/POSTNewClient.php @@ -0,0 +1,58 @@ +addResult("msg", "No ID Supplied"); +// throw new IDNotSuppliedException(); + return; + } + + // Encode the banner id right off -- use this from now on + $banner = $_REQUEST['banner_id']; + + // double check that client does not exist in database + $db = new PHPWS_DB($this->_table); + $db->addWhere("id", $banner); + $results = $db->count(); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + if ( $results > 0 ) { + $this->addResult("msg", "Client already exists"); +// throw new ClientAlreadyExistsException(); + return; + } + + //$this->data = array(); + //$this->data['classification'] = $_REQUEST['classification']; + //$this->data['living_location'] = $_REQUEST['living_location']; + //$this->data['major'] = $_REQUEST['major']; + + $client = new Client($banner); + + $client->classification = (isset($this->data['classification']) ) ? $this->data['classification'] : "Unknown"; + $client->living_location = (isset($this->data['living_location']) ) ? $this->data['living_location'] : "Unknown"; + $client->major = (isset($this->data['major']) ) ? $this->data['major'] : "Unknown"; + + $client->first_visit = timestamp(); + + $db->reset(); + $db->setTable($this->_table); + $results = $db->saveObject($client); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $this->addResult("msg", $results); + $this->addResult("client", $client); + } + +} + +?> diff --git a/class/ajax/POSTNewIssue.php b/class/ajax/POSTNewIssue.php new file mode 100644 index 0000000..d47fa41 --- /dev/null +++ b/class/ajax/POSTNewIssue.php @@ -0,0 +1,61 @@ +addResult("msg", "No Visit ID Supplied"); + throw new Exception('Missing visit ID.'); + return; + } + + if ( !isset($_REQUEST['problem_id']) ) { + $this->addResult("msg", "No Problem ID Supplied"); + throw new Exception('Missing problem ID.'); + return; + } + + // INSERT INTO ISSUE + $db = new PHPWS_DB("slc_issue"); + $i = new Issue(); + $i->problem_id = $_REQUEST['problem_id']; + + if ($_REQUEST['landlord_id'] != -1) { + // If $_REQUEST['landlord_id'] is set, use that for $i->landlord_id + $i->landlord_id = $_REQUEST['landlord_id']; + } elseif (($_REQUEST['problem_id'] >= 1 && $_REQUEST['problem_id'] <= 24) || $_REQUEST['problem_id'] == 47) { + // If $_REQUEST['landlord_id'] is not set, but the problem specified by $_REQUEST['problem_id'] + // is in the Landlord-Tenant tree, use id 94 which is 'Other / Unspecified' in the database. + $i->landlord_id = 94; + } else { + // If $_REQUEST['landlord_id'] is not set, and the problem specified by $_REQUEST['problem_id'] + // is not in the Landlord_Tenant tree, use null because the problem is not linked with a landlord. + $i->landlord_id = null; + } + + $results = $db->saveObject($i); + + $this->addResult("createdIssue", $results); + + // $results will be index + // INSERT INTO VISIT_ISSUE_INDEX + $db = new PHPWS_DB("slc_visit_issue_index"); + $vi = new VisitIssue(); + $vi->v_id = $_REQUEST['visit_id']; + $vi->i_id = $results; + $vi->counter = 1; + $vi->last_access = timestamp(); + $results = $db->saveObject($vi); + + if(PHPWS_Error::logIfError($results)){ + // throw new DatabaseException(); + } + + $this->addResult("msg", $results); + } + +} + +?> diff --git a/class/ajax/POSTNewVisit.php b/class/ajax/POSTNewVisit.php new file mode 100644 index 0000000..1267c90 --- /dev/null +++ b/class/ajax/POSTNewVisit.php @@ -0,0 +1,39 @@ +addResult("msg", "No Banner ID Supplied"); +// throw new IDNotSuppliedException(); + return; + } + + $visit = new Visit(); + $visit->initial_date = timestamp(); // TOOD: Use current timestamp as int + $visit->c_id = $_REQUEST['banner_id']; + + //test($visit); + + // Save the Visit + $db = new PHPWS_DB($this->_table); + $results = $db->saveObject($visit); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + } + + $visitID = $results; + + $html = ''; + + + $this->addResult("msg", $results); + $this->addResult("html", $html); + $this->addResult("visitID", $visitID); + } + +} + +?> diff --git a/class/ajax/POSTReferralType.php b/class/ajax/POSTReferralType.php new file mode 100644 index 0000000..1f885d2 --- /dev/null +++ b/class/ajax/POSTReferralType.php @@ -0,0 +1,33 @@ +addResult("avail_vars", $_REQUEST); + + if ( !isset($_REQUEST['banner_id']) ) { + $this->addResult("msg", "No Banner ID Supplied"); +// throw new IDNotSuppliedException(); + return; + } + + if ( !isset($_REQUEST['referral_type']) ) { + $this->addResult("msg", "No Refferal ID Supplied"); +// throw new ReferralIDNotSuppliedException(); + return; + } + + $qry = "UPDATE slc_client SET referral=".$_REQUEST['referral_type']." WHERE id='".$_REQUEST['banner_id']."'"; + + $results = PHPWS_DB::query($qry); + + if(PHPWS_Error::logIfError($results)){ + $this->addResult("error", "Database Exception"); + //throw new DatabaseException(); + return; + } + + $this->addResult("msg", $results); + } +} diff --git a/class/indexes/VisitClient.php b/class/indexes/VisitClient.php new file mode 100644 index 0000000..d94db82 --- /dev/null +++ b/class/indexes/VisitClient.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/class/indexes/VisitIssue.php b/class/indexes/VisitIssue.php new file mode 100644 index 0000000..b1d1d91 --- /dev/null +++ b/class/indexes/VisitIssue.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/class/views/View.php b/class/views/View.php new file mode 100644 index 0000000..aec81c4 --- /dev/null +++ b/class/views/View.php @@ -0,0 +1,19 @@ + diff --git a/class/views/ViewClient.php b/class/views/ViewClient.php new file mode 100644 index 0000000..709001f --- /dev/null +++ b/class/views/ViewClient.php @@ -0,0 +1,100 @@ +loadCall("GETClientData"); + $ajax->execute(); + + $result = $ajax->result(); + + if (isset($result['msg']) && $result['msg'] == "Client not in ASU Database" ) { + $HTMLcontent .= "Client not in ASU Database
This could be due to the client being a non-student or the database not being updated."; + return parent::useTemplate($HTMLcontent); // Insert into the accessible div + } + + $client = $result['client']; + + // Test for new client creation + $newClient = $result['newFlag'] || !$result['referralSet']; + //test($result); + + if ( $newClient ) { + $ajax = AjaxFactory::get("referral"); + $ajax->loadCall("GETReferralBox"); + $ajax->execute(); + + $result = $ajax->result(); + $r = $result['referral_picker']; + + $referral = "

 Referred By: ".$r."

"; + } else { + $referral = "

 Referred By: ".$client->referralString."

"; + } + + + $banner = $client->id; + + $content = array(); + $tpl = new PHPWS_Template('slc'); + $tpl->setFile('ClientVisits.tpl'); + $content['CLIENT_ID'] = $client->id; + $content['CLIENT_NAME'] = unserialize($_SESSION['cname']);//$client->name; + $content['CLIENT_INFO'] = $client->classification." - ".$client->major." Major"; + $content['FIRST_VISIT'] = prettyTime($client->first_visit); + + + + // Get visits + $ajax = AjaxFactory::get("visits"); + $ajax->loadCall("GETClientVisits"); + $ajax->execute(); + $visits = $ajax->result(); + $visits = $visits['visits']; + + if(!empty($visits)){ + foreach ($visits as $visit) { + //print_r($visit); + $visitTpl['VISITID'] = $visit->id; + $visitTpl['VISIT_DATE'] = prettyTime($visit->initial_date); + $visitTpl['NEW_ISSUE'] = "NEW ISSUE"; + + + // foreach issue per visit, keep array with array pointer + foreach ($visit->issues as $issue) { + //print_r($issue); + $issueTpl['ISSUEID'] = $issue->id; + $issueTpl['ISSUE'] = $issue->name; + $issueTpl['VISITCOUNT'] = $issue->counter; + $issueTpl['FOLLOWUP'] = "Follow Up"; + $issueTpl['LASTACCESS'] = prettyTime($issue->last_access)." (".prettyAccess($issue->last_access).")"; + $issueTpl['VISSITISSUEID'] = $issue->visit_issue_id; + $issueTpl['LANDLORD'] = $issue->landlord_name; + + $tpl->setCurrentBlock("issues"); + $tpl->setData($issueTpl); + $tpl->parseCurrentBlock(); + } + + $tpl->setCurrentBlock("visits"); + $tpl->setData($visitTpl); + $tpl->parseCurrentBlock(); + + } + } + + $content['CLIENT_VISITS'] = $tpl->get(); + $content['CLIENT_BANNER'] = $banner; + $content['REFERRAL'] = $referral; + + javascriptMod('slc', 'viewClient'); + + $HTMLcontent .= PHPWS_Template::process($content, 'slc', 'Client.tpl'); + + return parent::useTemplate($HTMLcontent); // Insert into the accessible div + } +} +?> diff --git a/class/views/ViewMain.php b/class/views/ViewMain.php new file mode 100644 index 0000000..51d4328 --- /dev/null +++ b/class/views/ViewMain.php @@ -0,0 +1,22 @@ +addHidden('module', 'slc'); + $form->addHidden('view','Client'); + //$form->addHidden('action','GETClientData'); + $form->addText('banner_id'); + $form->setLabel('banner_id', 'Enter Client ID: '); + $form->addSubmit('GO'); + + $tpl = $form->getTemplate(); + + $content = PHPWS_Template::process($tpl, 'slc', 'Main.tpl'); + + return parent::useTemplate($content); // Insert into the accessible div + } +} + +?> diff --git a/class/views/ViewNewClient.php b/class/views/ViewNewClient.php new file mode 100644 index 0000000..028affe --- /dev/null +++ b/class/views/ViewNewClient.php @@ -0,0 +1,31 @@ +setupTree(); + } + + private function setupTree() { + $this->theTree["How Referred"][] = "Friend / Word of Mouth"; + $this->theTree["How Referred"][] = "Former Client"; + $this->theTree["How Referred"][] = "Parents"; + $this->theTree["How Referred"][] = "Off-Campus Community Relations Office"; + $this->theTree["How Referred"][] = "Student Conduct"; + $this->theTree["How Referred"][] = "Housing / Residence Life"; + $this->theTree["How Referred"][] = "Counseling Center"; + $this->theTree["How Referred"][] = "Academic Advisor"; + $this->theTree["How Referred"][] = "Professor"; + $this->theTree["How Referred"][] = "ASU Police Department"; + $this->theTree["How Referred"][] = "Community Source"; + $this->theTree["How Referred"][] = "Sign on Door"; + $this->theTree["How Referred"][] = "Flyer in Residence Hall"; + $this->theTree["How Referred"][] = "Other Advertising"; + $this->theTree["How Referred"][] = "Other Referral"; + $this->theTree["How Referred"][] = "Internet"; + $this->theTree["How Referred"][] = "Off-Campus Presentation"; + $this->theTree["How Referred"][] = "Orientation"; + $this->theTree["How Referred"][] = "Meet and Greet Packet"; + } + + private $theTree = array(); + } +?> diff --git a/class/views/ViewNewIssue.php b/class/views/ViewNewIssue.php new file mode 100644 index 0000000..51720e2 --- /dev/null +++ b/class/views/ViewNewIssue.php @@ -0,0 +1,127 @@ +addHidden('module', 'slc'); + $form->addHidden('view','NewIssue'); + $form->addText('issuename'); + $form->setLabel('issuename', 'Filter: '); + + $content = $form->getTemplate(); + + $this->setupTree(); + + $tree = new PHPWS_Template('slc'); + $tree->setFile('IssueTree.tpl'); + + foreach( $this->theTree["Type Of Problem"] as $pType ) { + + if ( $pType["DBNAME"] == "problemlandlord") { + foreach( $this->theTree["Conditions"] as $data ) { + $tree->setCurrentBlock("problemlandlordcondition"); + $tree->setData($data); + $tree->parseCurrentBlock(); + } + + foreach ($this->theTree["Landlord-Tenant"] as $data) { + $tree->setCurrentBlock("problemlandlordnormal"); + $tree->setData($data); + $tree->parseCurrentBlock(); + } + } else if ( $pType["DBNAME"] == "problemregular") { + foreach( $this->theTree["Problem"] as $data ) { + $tree->setCurrentBlock("problemregular"); + $tree->setData($data); + $tree->parseCurrentBlock(); + } + } + // This displays the 'Criminal' sub-types. We don't use those anymore, so this is commented out to hide them. + /*else if ( $pType["DBNAME"] == "problemcriminal") { + foreach( $this->theTree["Law Enforcement Agency"] as $data ) { + $tree->setCurrentBlock("problemcriminalagency"); + $tree->setData($data); + $tree->parseCurrentBlock(); + } + + foreach( $this->theTree["Type of Criminal Problem"] as $data ) { + $tree->setCurrentBlock("problemcriminaltype"); + $tree->setData($data); + $tree->parseCurrentBlock(); + } + }*/ + + + $tree->setCurrentBlock($pType["DBNAME"]); + $tree->setData($pType); + $tree->parseCurrentBlock(); + } + + $content['VISITID'] = $_REQUEST['visitid']; + + // extract client from visitid + $query = "SELECT c_id FROM slc_visit WHERE id='".$_REQUEST['visitid']."'"; + $db = new PHPWS_DB("slc_visit"); + $results = $db->select(NULL, $query); + $content['CLIENTID'] = $results[0]['c_id']; + $content['TITLE'] = "Create New Issue for ".unserialize($_SESSION['cname']); + $content['SELECTED_ISSUES'] = "[ none ]"; + $content['PROBLEMS'] = $tree->get(); + $content['LANDLORD_PICKER'] = PHPWS_Template::process(array("landlords"=>$this->landlords), 'slc', 'LandlordPicker.tpl'); + $content = PHPWS_Template::process($content, 'slc', 'NewIssue.tpl'); + + return parent::useTemplate($content); + } + + private function setupTree() { + $this->theTree["Type Of Problem"] = array(); + $this->theTree["Type Of Problem"][] = array("PROBLEM_ID" => 997, "PROBLEM" => "Landlord-Tenant", "DBNAME" => "problemlandlord"); + $this->theTree["Type Of Problem"][] = array("PROBLEM_ID" => 998, "PROBLEM" => "Criminal", "DBNAME" => "problemcriminal"); + $this->theTree["Type Of Problem"][] = array("PROBLEM_ID" => 999, "PROBLEM" => "Other", "DBNAME" => "problemregular"); + + //$query = "SELECT * FROM slc_problem"; + // Don't select Criminal sub-types + $query = "SELECT * FROM slc_problem WHERE id NOT IN (25,26,27,28,29,30,31,32,33,34,995)"; + + $db = new PHPWS_DB("slc_problem"); + $results = $db->select(NULL, $query); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + $this->addResult("msg", "Database Exception"); + return; + } + + foreach ($results as $r) { + if (!isset($this->theTree[$r['type']])) + $this->theTree[$r['type']] = array(); + $this->theTree[$r['type']][] = array("PROBLEM_ID" => $r['id'], "NAME"=>$r['description'], "TREE"=>$r['tree']); + } + + $this->landlords = array(); + $query = "SELECT * FROM slc_landlord"; + + $db = new PHPWS_DB("slc_landlord"); + $results = $db->select(NULL, $query); + + if(PHPWS_Error::logIfError($results)){ + throw new DatabaseException(); + $this->addResult("msg", "Database Exception"); + return; + } + + foreach ($results as $r) { + $this->landlords[] = array("LANDLORD_ID" => $r['id'], "NAME"=>$r['name']); + } + + javascriptMod('slc', 'newIssue'); + } + + private $theTree = array(); + private $landlords = array(); + +} + +?> diff --git a/class/views/ViewReports.php b/class/views/ViewReports.php new file mode 100644 index 0000000..741d833 --- /dev/null +++ b/class/views/ViewReports.php @@ -0,0 +1,36 @@ +loadCall("GETReportBox"); + $ajax->execute(); + $result = $ajax->result(); + $content['REPORTPICKER'] = $result['report_picker']; // the HTML for the picker + + // Date range selection + javascript('datepicker'); + //$current_date = date('m/d/Y'); + $form = new PHPWS_Form("timespan"); + //$form->addText('start_date', date('m/d/Y', strtotime('-1 month'))); + $form->addText('start_date', ''); // date pickers are initially blank + $form->setSize('start_date', 10); + $form->setExtra('start_date', 'class="datepicker"'); + //$form->addText('end_date', $current_date); + $form->addText('end_date', ''); // date pickers are initially blank + $form->setSize('end_date', 10); + $form->setExtra('end_date', 'class="datepicker"'); + $content['START_DATE'] = $form->get('start_date'); + $content['END_DATE'] = $form->get('end_date'); + + // Process the template + $HTMLcontent .= PHPWS_Template::process($content, 'slc', 'Report.tpl'); + + return parent::useTemplate($HTMLcontent); // Insert into the accessible div + } +} +?> diff --git a/inc/defines.php b/inc/defines.php new file mode 100644 index 0000000..4f47613 --- /dev/null +++ b/inc/defines.php @@ -0,0 +1,25 @@ + + * @package mod + * @subpackage slc + */ + +define('STUDENT_FRESHMAN', 0); +define('STUDENT_SOPHOMORE', 1); +define('STUDENT_JUNIOR', 2); +define('STUDENT_SENIOR', 3); +define('STUDENT_GRADUATE', 4); +define('STUDENT_OTHER', 5); + +function getYearList(){ + return array(STUDENT_FRESHMAN => 'Freshman', + STUDENT_SOPHOMORE => 'Sophomore', + STUDENT_JUNIOR => 'Junior', + STUDENT_SENIOR => 'Senior', + STUDENT_GRADUATE => 'Graduate', + STUDENT_OTHER => 'Other'); +} +?> diff --git a/inc/functions.php b/inc/functions.php new file mode 100644 index 0000000..ee2a16e --- /dev/null +++ b/inc/functions.php @@ -0,0 +1,120 @@ +".htmlentities($text).""; + return $html; +} + + +function prettyAccess($timestamp) { + // Get difference + $difference = timestamp() - $timestamp; + + // Adjust to scale of minutes + $difference /= 60; + + if ( $difference < 1 ) + return "a few seconds ago"; + + // determine weeks + $weeks = floor($difference / (60 * 24 * 7))/1; + + $difference -= $weeks * 60 * 24 * 7; + + // determine days + $days = floor($difference / (60 * 24)); + + $difference -= $days * 60 * 24; + + // determine hours + $hours = floor($difference / (60)); + + $difference -= $hours * 60; + + // determine minutes + $minutes = floor($difference); + + // determine days + $days = floor($difference / (60 * 24)); + + if ( $days == 0 && $weeks == 0 ) { + $minutes = $minutes > 0 ? $minutes . " " . pluralize("minute", $minutes) . " " : ""; + $hours = $hours > 0 ? $hours . " " . pluralize("hour", $hours) . " " : ""; + } else + $minutes = $hours = ""; + $days = $days > 0 ? $days . " " . pluralize("day", $days) . " " : ""; + $weeks = $weeks > 0 ? $weeks . " " . pluralize("week", $weeks) . " " : ""; + + return $weeks . $days . $hours . $minutes . "ago"; +} + +function pluralize( $word, $number ) { + if ( $number > 1 ) + return $word ."s"; + else + return $word; +} + + +function timestamp() { + return time(); +} + +function prettyTime($timestamp) { + return date('l, F jS, Y', intval($timestamp)); +} + +// http://webcache.googleusercontent.com/search?q=cache:mWlWJfzCE4IJ:stackoverflow.com/questions/834303/php-startswith-and-endswith-functions+php+startswith&cd=2&hl=en&ct=clnk&gl=us +function startsWith($haystack, $needle) +{ + $length = strlen($needle); + return (substr($haystack, 0, $length) === $needle); +} + +function endsWith($haystack, $needle) +{ + $length = strlen($needle); + $start = $length * -1; //negative + return (substr($haystack, $start) === $needle); +} + +?> diff --git a/inc/runtime.php b/inc/runtime.php new file mode 100644 index 0000000..dcf7f07 --- /dev/null +++ b/inc/runtime.php @@ -0,0 +1,11 @@ + diff --git a/index.php b/index.php new file mode 100644 index 0000000..449e86e --- /dev/null +++ b/index.php @@ -0,0 +1,91 @@ +get('action'); + $af = AJAXFactory::get(); + $af->loadCall($action); + $af->execute(); + echo json_encode($af->result()); // To be left on the page for consumption + exit(); // Kill it +} catch(ParameterNotFoundException $e){ + // No AJAX found; do nothing + $action = 'None'; +} + +// Extract the view from the context +try { + $view = $context->get('view'); +} catch(ParameterNotFoundException $e){ + $view = 'Main'; +} + +// Get content from view + +$view = ViewFactory::getView($view); +$content = $view->display($context); + +// Build the panel +PHPWS_Core::initModClass('controlpanel', 'Panel.php'); +$panel = new PHPWS_Panel('slc_panel'); + +$tabs = array(); +$tabs['client'] = array('title' => 'Client Interaction', 'link' => 'index.php?module=slc&view=Main', 'link_title' => 'Submit Client/Visit Information'); +$tabs['report'] = array('title' => 'Reports', 'link' => 'index.php?module=slc&view=Reports', 'link_title' => 'Generate Reports'); +$panel->quickSetTabs($tabs); + +// Display the panel +$panel = $panel->display($content); +Layout::add($panel); + +// Setup Styles +Layout::addStyle('controlpanel'); + + +?> diff --git a/javascript/jquerytools/head.js b/javascript/jquerytools/head.js new file mode 100644 index 0000000..e9cfafb --- /dev/null +++ b/javascript/jquerytools/head.js @@ -0,0 +1 @@ + diff --git a/javascript/jquerytools/jquerytools.js b/javascript/jquerytools/jquerytools.js new file mode 100644 index 0000000..1c3d53b --- /dev/null +++ b/javascript/jquerytools/jquerytools.js @@ -0,0 +1,19 @@ +/*! + * jQuery Tools v1.2.6 - The missing UI library for the Web + * + * overlay/overlay.js + * overlay/overlay.apple.js + * scrollable/scrollable.js + * scrollable/scrollable.autoscroll.js + * scrollable/scrollable.navigator.js + * + * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE. + * + * http://flowplayer.org/tools/ + * + */ +(function(a){a.tools=a.tools||{version:"v1.2.6"},a.tools.overlay={addEffect:function(a,b,d){c[a]=[b,d]},conf:{close:null,closeOnClick:!0,closeOnEsc:!0,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:!1,mask:null,oneInstance:!0,speed:"normal",target:null,top:"10%"}};var b=[],c={};a.tools.overlay.addEffect("default",function(b,c){var d=this.getConf(),e=a(window);d.fixed||(b.top+=e.scrollTop(),b.left+=e.scrollLeft()),b.position=d.fixed?"fixed":"absolute",this.getOverlay().css(b).fadeIn(d.speed,c)},function(a){this.getOverlay().fadeOut(this.getConf().closeSpeed,a)});function d(d,e){var f=this,g=d.add(f),h=a(window),i,j,k,l=a.tools.expose&&(e.mask||e.expose),m=Math.random().toString().slice(10);l&&(typeof l=="string"&&(l={color:l}),l.closeOnClick=l.closeOnEsc=!1);var n=e.target||d.attr("rel");j=n?a(n):null||d;if(!j.length)throw"Could not find Overlay: "+n;d&&d.index(j)==-1&&d.click(function(a){f.load(a);return a.preventDefault()}),a.extend(f,{load:function(d){if(f.isOpened())return f;var i=c[e.effect];if(!i)throw"Overlay: cannot find effect : \""+e.effect+"\"";e.oneInstance&&a.each(b,function(){this.close(d)}),d=d||a.Event(),d.type="onBeforeLoad",g.trigger(d);if(d.isDefaultPrevented())return f;k=!0,l&&a(j).expose(l);var n=e.top,o=e.left,p=j.outerWidth({margin:!0}),q=j.outerHeight({margin:!0});typeof n=="string"&&(n=n=="center"?Math.max((h.height()-q)/2,0):parseInt(n,10)/100*h.height()),o=="center"&&(o=Math.max((h.width()-p)/2,0)),i[0].call(f,{top:n,left:o},function(){k&&(d.type="onLoad",g.trigger(d))}),l&&e.closeOnClick&&a.mask.getMask().one("click",f.close),e.closeOnClick&&a(document).bind("click."+m,function(b){a(b.target).parents(j).length||f.close(b)}),e.closeOnEsc&&a(document).bind("keydown."+m,function(a){a.keyCode==27&&f.close(a)});return f},close:function(b){if(!f.isOpened())return f;b=b||a.Event(),b.type="onBeforeClose",g.trigger(b);if(!b.isDefaultPrevented()){k=!1,c[e.effect][1].call(f,function(){b.type="onClose",g.trigger(b)}),a(document).unbind("click."+m).unbind("keydown."+m),l&&a.mask.close();return f}},getOverlay:function(){return j},getTrigger:function(){return d},getClosers:function(){return i},isOpened:function(){return k},getConf:function(){return e}}),a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}}),i=j.find(e.close||".close"),!i.length&&!e.close&&(i=a(""),j.prepend(i)),i.click(function(a){f.close(a)}),e.load&&f.load()}a.fn.overlay=function(c){var e=this.data("overlay");if(e)return e;a.isFunction(c)&&(c={onBeforeLoad:c}),c=a.extend(!0,{},a.tools.overlay.conf,c),this.each(function(){e=new d(a(this),c),b.push(e),a(this).data("overlay",e)});return c.api?e:this}})(jQuery); +(function(a){var b=a.tools.overlay,c=a(window);a.extend(b.conf,{start:{top:null,left:null},fadeInSpeed:"fast",zIndex:9999});function d(a){var b=a.offset();return{top:b.top+a.height()/2,left:b.left+a.width()/2}}var e=function(b,e){var f=this.getOverlay(),g=this.getConf(),h=this.getTrigger(),i=this,j=f.outerWidth({margin:!0}),k=f.data("img"),l=g.fixed?"fixed":"absolute";if(!k){var m=f.css("backgroundImage");if(!m)throw"background-image CSS property not set for overlay";m=m.slice(m.indexOf("(")+1,m.indexOf(")")).replace(/\"/g,""),f.css("backgroundImage","none"),k=a(""),k.css({border:0,display:"none"}).width(j),a("body").append(k),f.data("img",k)}var n=g.start.top||Math.round(c.height()/2),o=g.start.left||Math.round(c.width()/2);if(h){var p=d(h);n=p.top,o=p.left}g.fixed?(n-=c.scrollTop(),o-=c.scrollLeft()):(b.top+=c.scrollTop(),b.left+=c.scrollLeft()),k.css({position:"absolute",top:n,left:o,width:0,zIndex:g.zIndex}).show(),b.position=l,f.css(b),k.animate({top:f.css("top"),left:f.css("left"),width:j},g.speed,function(){f.css("zIndex",g.zIndex+1).fadeIn(g.fadeInSpeed,function(){i.isOpened()&&!a(this).index(f)?e.call():f.hide()})}).css("position",l)},f=function(b){var e=this.getOverlay().hide(),f=this.getConf(),g=this.getTrigger(),h=e.data("img"),i={top:f.start.top,left:f.start.left,width:0};g&&a.extend(i,d(g)),f.fixed&&h.css({position:"absolute"}).animate({top:"+="+c.scrollTop(),left:"+="+c.scrollLeft()},0),h.animate(i,f.closeSpeed,b)};b.addEffect("apple",e,f)})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.6"},a.tools.scrollable={conf:{activeClass:"active",circular:!1,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:"> *",items:".items",keyboard:!0,mousewheel:!1,next:".next",prev:".prev",size:1,speed:400,vertical:!1,touch:!0,wheelSpeed:0}};function b(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}var d;function e(b,e){var f=this,g=b.add(f),h=b.children(),i=0,j=e.vertical;d||(d=f),h.length>1&&(h=a(e.items,b)),e.size>1&&(e.circular=!1),a.extend(f,{getConf:function(){return e},getIndex:function(){return i},getSize:function(){return f.getItems().size()},getNaviButtons:function(){return n.add(o)},getRoot:function(){return b},getItemWrap:function(){return h},getItems:function(){return h.find(e.item).not("."+e.clonedClass)},move:function(a,b){return f.seekTo(i+a,b)},next:function(a){return f.move(e.size,a)},prev:function(a){return f.move(-e.size,a)},begin:function(a){return f.seekTo(0,a)},end:function(a){return f.seekTo(f.getSize()-1,a)},focus:function(){d=f;return f},addItem:function(b){b=a(b),e.circular?(h.children().last().before(b),h.children().first().replaceWith(b.clone().addClass(e.clonedClass))):(h.append(b),o.removeClass("disabled")),g.trigger("onAddItem",[b]);return f},seekTo:function(b,c,k){b.jquery||(b*=1);if(e.circular&&b===0&&i==-1&&c!==0)return f;if(!e.circular&&b<0||b>f.getSize()||b<-1)return f;var l=b;b.jquery?b=f.getItems().index(b):l=f.getItems().eq(b);var m=a.Event("onBeforeSeek");if(!k){g.trigger(m,[b,c]);if(m.isDefaultPrevented()||!l.length)return f}var n=j?{top:-l.position().top}:{left:-l.position().left};i=b,d=f,c===undefined&&(c=e.speed),h.animate(n,c,e.easing,k||function(){g.trigger("onSeek",[b])});return f}}),a.each(["onBeforeSeek","onSeek","onAddItem"],function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}});if(e.circular){var k=f.getItems().slice(-1).clone().prependTo(h),l=f.getItems().eq(1).clone().appendTo(h);k.add(l).addClass(e.clonedClass),f.onBeforeSeek(function(a,b,c){if(!a.isDefaultPrevented()){if(b==-1){f.seekTo(k,c,function(){f.end(0)});return a.preventDefault()}b==f.getSize()&&f.seekTo(l,c,function(){f.begin(0)})}});var m=b.parents().add(b).filter(function(){if(a(this).css("display")==="none")return!0});m.length?(m.show(),f.seekTo(0,0,function(){}),m.hide()):f.seekTo(0,0,function(){})}var n=c(b,e.prev).click(function(a){a.stopPropagation(),f.prev()}),o=c(b,e.next).click(function(a){a.stopPropagation(),f.next()});e.circular||(f.onBeforeSeek(function(a,b){setTimeout(function(){a.isDefaultPrevented()||(n.toggleClass(e.disabledClass,b<=0),o.toggleClass(e.disabledClass,b>=f.getSize()-1))},1)}),e.initialIndex||n.addClass(e.disabledClass)),f.getSize()<2&&n.add(o).addClass(e.disabledClass),e.mousewheel&&a.fn.mousewheel&&b.mousewheel(function(a,b){if(e.mousewheel){f.move(b<0?1:-1,e.wheelSpeed||50);return!1}});if(e.touch){var p={};h[0].ontouchstart=function(a){var b=a.touches[0];p.x=b.clientX,p.y=b.clientY},h[0].ontouchmove=function(a){if(a.touches.length==1&&!h.is(":animated")){var b=a.touches[0],c=p.x-b.clientX,d=p.y-b.clientY;f[j&&d>0||!j&&c>0?"next":"prev"](),a.preventDefault()}}}e.keyboard&&a(document).bind("keydown.scrollable",function(b){if(!(!e.keyboard||b.altKey||b.ctrlKey||b.metaKey||a(b.target).is(":input"))){if(e.keyboard!="static"&&d!=f)return;var c=b.keyCode;if(j&&(c==38||c==40)){f.move(c==38?-1:1);return b.preventDefault()}if(!j&&(c==37||c==39)){f.move(c==37?-1:1);return b.preventDefault()}}}),e.initialIndex&&f.seekTo(e.initialIndex,0,function(){})}a.fn.scrollable=function(b){var c=this.data("scrollable");if(c)return c;b=a.extend({},a.tools.scrollable.conf,b),this.each(function(){c=new e(a(this),b),a(this).data("scrollable",c)});return b.api?c:this}})(jQuery); +(function(a){var b=a.tools.scrollable;b.autoscroll={conf:{autoplay:!0,interval:3e3,autopause:!0}},a.fn.autoscroll=function(c){typeof c=="number"&&(c={interval:c});var d=a.extend({},b.autoscroll.conf,c),e;this.each(function(){var b=a(this).data("scrollable"),c=b.getRoot(),f,g=!1;function h(){f=setTimeout(function(){b.next()},d.interval)}b&&(e=b),b.play=function(){f||(g=!1,c.bind("onSeek",h),h())},b.pause=function(){f=clearTimeout(f),c.unbind("onSeek",h)},b.resume=function(){g||b.play()},b.stop=function(){g=!0,b.pause()},d.autopause&&c.add(b.getNaviButtons()).hover(b.pause,b.resume),d.autoplay&&b.play()});return d.api?e:this}})(jQuery); +(function(a){var b=a.tools.scrollable;b.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:!1,idPrefix:null,history:!1}};function c(b,c){var d=a(c);return d.length<2?d:b.parent().find(c)}a.fn.navigator=function(d){typeof d=="string"&&(d={navi:d}),d=a.extend({},b.navigator.conf,d);var e;this.each(function(){var b=a(this).data("scrollable"),f=d.navi.jquery?d.navi:c(b.getRoot(),d.navi),g=b.getNaviButtons(),h=d.activeClass,i=d.history&&history.pushState,j=b.getConf().size;b&&(e=b),b.getNaviButtons=function(){return g.add(f)},i&&(history.pushState({i:0}),a(window).bind("popstate",function(a){var c=a.originalEvent.state;c&&b.seekTo(c.i)}));function k(a,c,d){b.seekTo(c),d.preventDefault(),i&&history.pushState({i:c})}function l(){return f.find(d.naviItem||"> *")}function m(b){var c=a("<"+(d.naviItem||"a")+"/>").click(function(c){k(a(this),b,c)});b===0&&c.addClass(h),d.indexed&&c.text(b+1),d.idPrefix&&c.attr("id",d.idPrefix+b);return c.appendTo(f)}l().length?l().each(function(b){a(this).click(function(c){k(a(this),b,c)})}):a.each(b.getItems(),function(a){a%j==0&&m(a)}),b.onBeforeSeek(function(a,b){setTimeout(function(){if(!a.isDefaultPrevented()){var c=b/j,d=l().eq(c);d.length&&l().removeClass(h).eq(c).addClass(h)}},1)}),b.onAddItem(function(a,c){var d=b.getItems().index(c);d%j==0&&m(d)})});return d.api?e:this}})(jQuery); \ No newline at end of file diff --git a/javascript/json/head.js b/javascript/json/head.js new file mode 100644 index 0000000..4ab9d2f --- /dev/null +++ b/javascript/json/head.js @@ -0,0 +1,480 @@ + diff --git a/javascript/newIssue/head.js b/javascript/newIssue/head.js new file mode 100644 index 0000000..e0a1422 --- /dev/null +++ b/javascript/newIssue/head.js @@ -0,0 +1,79 @@ + diff --git a/javascript/report/head.js b/javascript/report/head.js new file mode 100644 index 0000000..9eec082 --- /dev/null +++ b/javascript/report/head.js @@ -0,0 +1,131 @@ + diff --git a/javascript/viewClient/head.js b/javascript/viewClient/head.js new file mode 100644 index 0000000..cd2ebf6 --- /dev/null +++ b/javascript/viewClient/head.js @@ -0,0 +1,81 @@ + diff --git a/phpdox.xml b/phpdox.xml new file mode 100644 index 0000000..b885c78 --- /dev/null +++ b/phpdox.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/slc.spec b/slc.spec new file mode 100644 index 0000000..a2abef9 --- /dev/null +++ b/slc.spec @@ -0,0 +1,48 @@ +%define name slc +%define install_dir /var/www/phpwebsite/mod/slc + +Summary: Student Legal Clinic Tracker +Name: %{name} +Version: %{version} +Release: %{release} +License: GPL +Group: Development/PHP +URL: http://phpwebsite.appstate.edu +Source: %{name}-%{version}-%{release}.tar.bz2 +Requires: php >= 5.0.0, php-gd >= 5.0.0, phpwebsite +Prefix: /var/www/phpwebsite +BuildArch: noarch + +%description +Student Legal Clinic Tracker + +%prep +%setup -n %{name}-%{version}-%{release} + +%post +/usr/bin/curl -L -k http://127.0.0.1/apc/clear + +%install +mkdir -p "$RPM_BUILD_ROOT%{install_dir}" +cp -r * "$RPM_BUILD_ROOT%{install_dir}" + +# Default Deletes for clean RPM + +rm -Rf "$RPM_BUILD_ROOT%{install_dir}/docs/" +rm -Rf "$RPM_BUILD_ROOT%{install_dir}/.hg/" +rm -f "$RPM_BUILD_ROOT%{install_dir}/.hgtags" +rm -f "$RPM_BUILD_ROOT%{install_dir}/build.xml" +rm -f "$RPM_BUILD_ROOT%{install_dir}/slc.spec" +rm -f "$RPM_BUILD_ROOT%{install_dir}/phpdox.xml" +rm -f "$RPM_BUILD_ROOT%{install_dir}/cache.properties" + +%clean +rm -rf "$RPM_BUILD_ROOT%{install_dir}" + +%files +%defattr(-,root,root) +%{install_dir} + +%changelog +* Mon Jun 18 2012 Jeff Tickle +- Initial RPM for SLC diff --git a/templates/Client.tpl b/templates/Client.tpl new file mode 100644 index 0000000..8978344 --- /dev/null +++ b/templates/Client.tpl @@ -0,0 +1,7 @@ + +

{CLIENT_NAME}First Visit: {FIRST_VISIT}

+

{CLIENT_INFO}

+{REFERRAL} +{CLIENT_VISITS} +
diff --git a/templates/ClientVisits.tpl b/templates/ClientVisits.tpl new file mode 100644 index 0000000..7bfe3c0 --- /dev/null +++ b/templates/ClientVisits.tpl @@ -0,0 +1,43 @@ +
'.prettyTime($visit->initial_date).'[ NEW ISSUE ]
+ + + + + +
Visits: + New Visit 
+
+ + + + + + + + +
{VISIT_DATE}[ {NEW_ISSUE} ]
+ + + + + + + + + + + +
+ {ISSUE}{LANDLORD} + + {VISITCOUNT} visit(s) + + {FOLLOWUP} +
+ Last Accessed {LASTACCESS} +
+ +
+ +
+
diff --git a/templates/Default.tpl b/templates/Default.tpl new file mode 100644 index 0000000..a4828ac --- /dev/null +++ b/templates/Default.tpl @@ -0,0 +1,3 @@ +
+{CONTENT} +
diff --git a/templates/IssueTree.tpl b/templates/IssueTree.tpl new file mode 100644 index 0000000..74b8cbe --- /dev/null +++ b/templates/IssueTree.tpl @@ -0,0 +1,58 @@ + + + + + +
+ + + + + + + + + +
{PROBLEM}
+ + + + + + + + + + + + +
{NAME}
Condition:
+ + + + + + +
{NAME}
+
+
+
+ + + + + + +
{PROBLEM}
+
+ + + + + + + + + +
{PROBLEM}
{NAME}
+
diff --git a/templates/LandlordPicker.tpl b/templates/LandlordPicker.tpl new file mode 100644 index 0000000..7d8ec9c --- /dev/null +++ b/templates/LandlordPicker.tpl @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/templates/Main.tpl b/templates/Main.tpl new file mode 100644 index 0000000..0cbb6c3 --- /dev/null +++ b/templates/Main.tpl @@ -0,0 +1 @@ +{START_FORM}{BANNER_ID_LABEL} {BANNER_ID} {SUBMIT}{END_FORM} \ No newline at end of file diff --git a/templates/NewIssue.tpl b/templates/NewIssue.tpl new file mode 100644 index 0000000..33b8455 --- /dev/null +++ b/templates/NewIssue.tpl @@ -0,0 +1,18 @@ + +

{TITLE} + + Return + +

+ +{START_FORM} +

Issues Added:

+ +
Selected Issue: {SELECTED_ISSUES}
+
{LANDLORD_PICKER}
+
+ +{END_FORM}
+

Problems
Create Issue

+{PROBLEMS} + diff --git a/templates/ReferralPicker.tpl b/templates/ReferralPicker.tpl new file mode 100644 index 0000000..c4a4978 --- /dev/null +++ b/templates/ReferralPicker.tpl @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/templates/Report.tpl b/templates/Report.tpl new file mode 100644 index 0000000..70a113f --- /dev/null +++ b/templates/Report.tpl @@ -0,0 +1,7 @@ +

Issue Tracker Reporting System

+Select report: {REPORTPICKER} +Date of visit: {START_DATE} to {END_DATE} +
+
+Once a report is generated, it will appear here. +
diff --git a/templates/ReportPicker.tpl b/templates/ReportPicker.tpl new file mode 100644 index 0000000..8c328b6 --- /dev/null +++ b/templates/ReportPicker.tpl @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/templates/style.css b/templates/style.css new file mode 100644 index 0000000..f1440cc --- /dev/null +++ b/templates/style.css @@ -0,0 +1,47 @@ +.problemLink { + cursor:pointer; +} + +.problemLink:hover { + font-weight:bold; +} + +.issue:hover { + background-color:#FADD76; +} + +.button { + border: outset 1px black; + position:relative; + right:2px; + background-color:#FBFBFB; + cursor:pointer; + font-weight:bold; + padding-right:6px; + padding-left:6px; +} + +th { + background-color: lightgrey; + border: 0px solid black; + text-align : center; + padding : 4px; +} +td.dataCell { + border: 0px solid black; + text-align : center; +} + +.divLandlordCell { + position:absolute; +} + +td.landlord { + text-align : left; + font-weight : bold; + white-space : nowrap; +} + +td.Total { + font-weight : bold; +}