From d6eb36ecd753c91cdc786c877f725949f9fd2693 Mon Sep 17 00:00:00 2001
From: Tim Steiner <tsteiner2@unl.edu>
Date: Fri, 23 Jan 2009 17:51:28 +0000
Subject: [PATCH] Course searching at /courses/public-view/search

---
 .../controllers/PublicViewController.php      | 120 +++++--
 .../modules/courses/models/CourseModel.php    | 333 ++++++++++++++----
 .../views/scripts/public-view/results.phtml   |  41 +++
 .../views/scripts/public-view/search.phtml    |  57 +++
 .../views/scripts/public-view/view.phtml      |   6 +
 5 files changed, 451 insertions(+), 106 deletions(-)
 create mode 100644 application/modules/courses/views/scripts/public-view/results.phtml
 create mode 100644 application/modules/courses/views/scripts/public-view/search.phtml
 create mode 100644 application/modules/courses/views/scripts/public-view/view.phtml

diff --git a/application/modules/courses/controllers/PublicViewController.php b/application/modules/courses/controllers/PublicViewController.php
index ec53d30e..d2df2ff0 100644
--- a/application/modules/courses/controllers/PublicViewController.php
+++ b/application/modules/courses/controllers/PublicViewController.php
@@ -2,9 +2,9 @@
 
 /**
  * PublicViewController
- * 
+ *
  * @author
- * @version 
+ * @version
  */
 
 
@@ -21,12 +21,12 @@ class Courses_PublicViewController extends App_Controller_Action {
     	$dom->formatOutput = true;
     	$root = $dom->createElement('courses');
     	$dom->appendChild($root);
-    	
+
     	foreach ($courses as $course) {
     		$courseNode = $dom->createElement('course');
-    		
+
     		$courseNode->appendChild($dom->createElement('title', htmlspecialchars($course->getTitle())));
-    		
+
     		$crosslistings = $course->getCrosslistings();
     		if (count($crosslistings) > 0) {
 	    		$courseCodesNode = $dom->createElement('courseCodes');
@@ -44,11 +44,11 @@ class Courses_PublicViewController extends App_Controller_Action {
     		} else {
     			continue;
     		}
-    		
+
             $courseNode->appendChild($dom->createElement('gradingType', htmlspecialchars($course->getGradingType(), null, 'UTF-8')));
             $courseNode->appendChild($dom->createElement('dfRemoval', htmlspecialchars($course->getDfRemoval(), null, 'UTF-8')));
             $courseNode->appendChild($dom->createElement('effectiveSemester', htmlspecialchars($course->getEffectiveSemester(), null, 'UTF-8')));
-    	
+
             if ($node = $this->_getNodeFromHtmlFragment($dom, 'prerequisite', $course->getPrerequisite())) {
                 $courseNode->appendChild($node);
             }
@@ -58,7 +58,7 @@ class Courses_PublicViewController extends App_Controller_Action {
             if ($node = $this->_getNodeFromHtmlFragment($dom, 'description', $course->getDescription())) {
                 $courseNode->appendChild($node);
             }
-            
+
             if (count($course->getCampuses()) > 0) {
                 $campusesNode = $dom->createElement('campuses');
                 $courseNode->appendChild($campusesNode);
@@ -66,7 +66,7 @@ class Courses_PublicViewController extends App_Controller_Action {
                     $campusesNode->appendChild($dom->createElement('campus', $campus));
                 }
             }
-            
+
             if (count($course->getDeliveryMethods()) > 0) {
                 $deliveryMethodsNode = $dom->createElement('deliveryMethods');
                 $courseNode->appendChild($deliveryMethodsNode);
@@ -74,7 +74,7 @@ class Courses_PublicViewController extends App_Controller_Action {
                     $deliveryMethodsNode->appendChild($dom->createElement('deliveryMethod', $deliveryMethod));
                 }
             }
-            
+
             if (count($course->getTermsOffered()) > 0) {
                 $termsOfferedNode = $dom->createElement('termsOffered');
                 $courseNode->appendChild($termsOfferedNode);
@@ -82,7 +82,7 @@ class Courses_PublicViewController extends App_Controller_Action {
                     $termsOfferedNode->appendChild($dom->createElement('term', $term));
                 }
             }
-    		
+
     		$activities = $course->getActivities();
     		if (count($crosslistings) > 0) {
     			$activitiesNode = $dom->createElement('activities');
@@ -96,7 +96,7 @@ class Courses_PublicViewController extends App_Controller_Action {
                     }
 	    		}
     		}
-    		
+
     		$credits = $course->getCredits();
     		if (count($credits) > 0) {
     			$creditsNode = $dom->createElement('credits');
@@ -107,7 +107,7 @@ class Courses_PublicViewController extends App_Controller_Action {
     				$creditNode->setAttribute('type', $credit['description']);
     			}
     		}
-    	
+
     		$gradTieIn = $course->getGradTieIn();
             if ($gradTieIn['credits']) {
                 $courseNode->appendChild($dom->createElement('gradCredits', htmlspecialchars($gradTieIn['credits'], null, 'UTF-8')));
@@ -118,45 +118,45 @@ class Courses_PublicViewController extends App_Controller_Action {
             if ($node = $this->_getNodeFromHtmlFragment($dom, 'gradPrerequisites', $gradTieIn['prerequisites'])) {
                 $courseNode->appendChild($node);
             }
-    		
-            
+
+
             $root->appendChild($courseNode);
     	}
-    	
+
     	header('Content-type: text/xml');
     	$dom->normalize();
     	echo $dom->saveXML();
 	}
-	
+
 	protected function _getNodeFromHtmlFragment($dom, $nodeName, $fragment)
 	{
 		$fragment = trim($fragment);
         if (!$fragment) {
         	return null;
         }
-        
+
         $node = new DOMDocument('1.0', 'UTF-8');
         $fragment = '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body>' . $fragment . '</body>';
         $node = DOMDocument::loadHTML(strtr($fragment, array('&' => '&amp;')));
         if (!$node->documentElement) {
         	return null;
         }
-        
+
         $node = $dom->importNode($node->documentElement, true);
         if (count($node->childNodes->item(1)->childNodes) == 1 && $node->childNodes->item(1)->childNodes->item(0)->nodeName == 'p') {
         	$realNode = $node->childNodes->item(1)->childNodes->item(0);
         } else {
             $realNode = $node->childNodes->item(1);
         }
-        
+
         $newNode = $dom->createElement($nodeName);
         while ($realNode->hasChildNodes()) {
         	$newNode->appendChild($realNode->childNodes->item(0));
         }
-       
+
         return $newNode;
 	}
-	
+
 	/**
 	 * This action syncronizes the qreqCourses.currentGeneration field with data from creqCourseGenerations
 	 *
@@ -166,19 +166,19 @@ class Courses_PublicViewController extends App_Controller_Action {
 		$this->_disableLayoutAndView();
         //header('Content-type: text/plain');
 
-        
+
 		$db = Zend_Registry::get('db');
-		
+
 		$sql = 'SELECT * FROM creqCourseGenerations';
 		$data = $db->query($sql)->fetchAll();
-		
+
 		$courses = array();
 		foreach ($data as $row) {
 			$courseId = $row['course'];
 			$generationId = $row['courseGenerationId'];
 			$courses[$courseId][$generationId] = $row;
 		}
-		
+
 		$multipleLatestCount = 0;
 		$courseLatest = array();
 		foreach ($courses as $courseId => $course) {
@@ -216,13 +216,75 @@ class Courses_PublicViewController extends App_Controller_Action {
 			$courseLatest[$courseId] = $latestId;
 		}
 		echo 'Multiple Latest Count: ' . $multipleLatestCount . PHP_EOL;
-		
+
 		foreach ($courseLatest as $courseId => $latestId) {
 			$data = array('currentGeneration' => $latestId);
 			$where = 'courseId = ' . $courseId;
 			$db->update('creqCourses', $data, $where);
 		}
-		
-		
+	}
+
+	public function searchAction()
+	{
+        $this->view->colleges = Courses_CourseModel::getCollegeNames();
+        $this->view->departments = Courses_CourseModel::getDepartments();
+        $this->view->subjects = Courses_CourseModel::getSubjectsFull();
+	}
+
+	public function resultsAction()
+	{
+		$criteria = $this->_getAllParams();
+		$in = $criteria;
+		$criteria['title'] = $criteria['courseTitle'];
+		$courses = Courses_CourseModel::findWithCriteria($criteria);
+
+        $data = new Unl_Model_Collection('Unl_Model_Array');
+        foreach ($courses as $requestId => $course) {
+        	$aceOutcomes = $course->getAceOutcomes();
+        	if (!$aceOutcomes) {
+        		$aceOutcomes = array('-');
+        	}
+            foreach ($aceOutcomes as $aceOutcome) {
+                $data[] = new Unl_Model_Array(array(
+                    'slo' => substr($aceOutcome['slo'], 3),
+                    'courseCode' => $course->getCourseCode(),
+                    'college' => $course->getCollege(),
+                    'title' => $course->getTitle(),
+                    'courseId' => $course->getCourseId(),
+                ));
+            }
+        }
+	
+        $session = new Zend_Session_Namespace(__CLASS__);
+        $sortBy = $session->sortBy;
+        if (!Unl_Util::isArray($sortBy)) {
+        	$sortBy = array();
+        }
+        if ($in['sort']) {
+        	if (($key = array_search($in['sort'], $sortBy)) !== FALSE) {
+        		unset($sortBy[$key]);
+        	}
+        	$sortBy[] = $in['sort'];
+        }
+        $session->sortBy = $sortBy;
+        
+        foreach ($sortBy as $sortKey) {
+        	$data->orderBy('get' . $sortKey);
+        }
+        
+        $this->view->data = $data;
+        $this->view->criteria = $criteria;
+	}
+
+	public function viewAction()
+	{
+	    $in = $this->_getAllParams();
+	    $id = $in['id'];
+
+	    if ($id) {
+	        $course = Courses_CourseModel::findByCourseId($id);
+	    }
+
+	    $this->view->course = $course;
 	}
 }
diff --git a/application/modules/courses/models/CourseModel.php b/application/modules/courses/models/CourseModel.php
index f1fcf102..978f94a2 100644
--- a/application/modules/courses/models/CourseModel.php
+++ b/application/modules/courses/models/CourseModel.php
@@ -4,8 +4,11 @@ require_once ('Unl/Model.php');
 
 class Courses_CourseModel extends Unl_Model
 {
-	static protected $_colleges = array();
-    
+    static protected $_colleges = array();
+    static protected $_collegeNames = array();
+    static protected $_departments = array();
+    static protected $_hierarchy = array();
+
 	static protected $_outcomeShortNames = array(
         'SLO1'  => 'writing',
         'SLO2'  => 'communication',
@@ -47,7 +50,7 @@ class Courses_CourseModel extends Unl_Model
         'globalAwareness'          => 'Global Awareness',
         'humanDiversity'           => 'Human Diversity'
     );
-    
+
     static protected $_activityMap;
 
     const CREDIT_TYPE_SINGLE       = 1;
@@ -228,7 +231,7 @@ class Courses_CourseModel extends Unl_Model
             'crosslistings'     => array(),
             'esDesignations'    => array(),
             'gradTieIn'         => null,
-        
+
             'aceReinforcements' => array(),
             'aceOutcomes'       => array()
     	);
@@ -368,7 +371,7 @@ class Courses_CourseModel extends Unl_Model
 		if (!$courseLetter) {
 			$courseLetter = '';
 		}
-		
+
 		$db = Zend_Registry::get('db');
 
 		$select = new Zend_Db_Select($db);
@@ -380,7 +383,28 @@ class Courses_CourseModel extends Unl_Model
 		$select->where('c.subject = ?', $subject);
 		$select->where('c.courseNumber = ?', $courseNumber);
         $select->where('c.courseLetter = ?', $courseLetter);
-        
+
+		$records = $select->query()->fetchAll();
+		if (count($records) == 0) {
+			return null;
+		}
+		$generationId = $records[0]['courseGenerationId'];
+		return self::find($generationId);
+	}
+
+	static public function findByCourseId($courseId)
+	{
+		if (!$courseLetter) {
+			$courseLetter = '';
+		}
+
+		$db = Zend_Registry::get('db');
+
+		$select = new Zend_Db_Select($db);
+		$select->from(array('g' => 'creqCourseGenerations'), array('courseGenerationId'));
+		$select->join(array('c' => 'creqCourses'), 'g.courseGenerationId = c.currentGeneration', array());
+        $select->where('c.courseId = ?', $courseId);
+
 		$records = $select->query()->fetchAll();
 		if (count($records) == 0) {
 			return null;
@@ -409,7 +433,7 @@ class Courses_CourseModel extends Unl_Model
         }
         $select->where('r.complete = "no"');
         */
-        
+
         $select = new Zend_Db_Select($db);
         $select->distinct();
         $select->from(array('c'  => 'creqCourseCodes'), array());
@@ -432,7 +456,7 @@ class Courses_CourseModel extends Unl_Model
         $requests = Requests_RequestModel::find($requestIds);
         return $requests;
 	}
-	
+
 	static public function findAllActive()
 	{
         $db = Zend_Registry::get('db');
@@ -441,7 +465,7 @@ class Courses_CourseModel extends Unl_Model
         $select->from(array('g' => 'creqCourseGenerations'), array('courseGenerationId'));
         $select->join(array('p' => 'creqCourses'), 'g.courseGenerationId = p.currentGeneration', array());
         $select->where('g.removed = "no"');
-        
+
         $records = $select->query()->fetchAll();
         $generationIds = array();
         foreach ($records as $row) {
@@ -450,6 +474,75 @@ class Courses_CourseModel extends Unl_Model
         return self::find($generationIds);
 	}
 
+	static public function findWithCriteria($criteria = array())
+	{
+		$validKeys = array('college', 'department', 'subject', 'courseNumber', 'courseLetter', 'title', 'campus', 'ace', 'essentialStudies', 'integratedStudies');
+		$criteria = array_intersect_key($criteria, array_flip($validKeys));
+		$emptySearch = true;
+		foreach ($criteria as $value) {
+			if ($value) {
+				$emptySearch = false;
+			}
+		}
+		if ($emptySearch) {
+			return new Unl_Model_Collection(__CLASS__);
+		}
+
+        $db = Zend_Registry::get('db');
+
+        $select = new Zend_Db_Select($db);
+        $select->from(array('l' => 'creqColleges'), array());
+        $select->join(array('d' => 'creqDepartments'), 'l.collegeId = d.college', array());
+        $select->join(array('s' => 'creqSubjects'), 'd.departmentId = s.department', array());
+        $select->join(array('c' => 'creqCourseCodes'), 's.name = c.subject', array());
+        $select->join(array('x' => 'creqCourseCrosslistings'), 'c.courseCodeId = x.courseCode', array());
+        $select->join(array('g' => 'creqCourseGenerations'), 'x.generation = g.courseGenerationId', array('courseGenerationId'));
+        $select->join(array('p' => 'creqCourses'), 'g.courseGenerationId = p.currentGeneration', array());
+        $select->join(array('e' => 'creqCourseDetails'), 'g.courseGenerationId = e.generation', array());
+        $select->where('g.removed = "no"');
+        $select->where('g.type = "official"');
+        if ($criteria['college']) {
+            $select->where('l.collegeId = ?', $criteria['college']);
+        }
+        if ($criteria['department']) {
+            $select->where('d.departmentId = ?', $criteria['department']);
+        }
+        if ($criteria['subject']) {
+            $select->where('c.subject = ?', $criteria['subject']);
+        }
+        if ($criteria['courseNumber']) {
+            $select->where('c.courseNumber LIKE ?', $criteria['courseNumber'] . '%');
+        }
+        if ($criteria['courseLetter']) {
+            $select->where('c.courseLetter = ?', $criteria['courseLetter']);
+        }
+        if ($criteria['title']) {
+            $select->where('e.title LIKE ?', '%' . $criteria['title'] . '%');
+        }
+        if ($criteria['campus']) {
+            $select->where('e.campuses LIKE ?', '%' . $criteria['title'] . '%');
+        }
+        if ($criteria['ace']) {
+        	$select->join(array('a' => 'creqCourseAceOutcomes'), 'g.courseGenerationId = a.generation', array());
+        }
+        if ($criteria['essentialStudies']) {
+        	$select->join(array('es' => 'creqCourseEsDesignations'), 'c.courseCodeId = es.courseCode', array());
+        }
+        if ($criteria['integratedStudies']) {
+        	$select->where('c.integratedStudies = ?', 'yes');
+        }
+
+        $records = $select->query()->fetchAll();
+        if (count($records) == 0) {
+            return null;
+        }
+        $generationIds = array();
+        foreach ($records as $record) {
+        	$generationIds[] = $record['courseGenerationId'];
+        }
+        return self::find($generationIds);
+	}
+
     static public function save($models)
     {
 
@@ -1459,6 +1552,48 @@ class Courses_CourseModel extends Unl_Model
         return $homeSubject;
     }
 
+    static public function getSubjects()
+    {
+        self::_loadSubjectList();
+        return self::$_subjectList;
+    }
+
+    static public function getSubjectNames()
+    {
+        self::_loadSubjectList();
+        return self::$_subjectNames;
+    }
+
+    static public function getSubjectsFull()
+    {
+        self::_loadSubjectList();
+        $subjects = array();
+        foreach (self::$_subjectList as $id => $code) {
+        	$subjects[$code] = $code . ' - ' . self::$_subjectNames[$id];
+        }
+        return $subjects;
+    }
+
+    static public function getSubjectDepartmentCollegeHierarchy()
+    {
+        if (count(self::$_hierarchy) == 0) {
+            $db = Zend_Registry::get('db');
+            $select = new Zend_Db_Select($db);
+            $select->from(array('c' => 'creqColleges'), array('college' => 'description'));
+            $select->join(array('d' => 'creqDepartments'), 'c.collegeId = d.college', array('department' => 'name'));
+            $select->join(array('s' => 'creqSubjects'), 'd.departmentId = s.department', array('code' => 'name', 'subject' => 'description'));
+            $select->order(array('college', 'department', 'subject'));
+            $records = $select->query()->fetchAll();
+            $hierarchy = array();
+            foreach ($records as $record) {
+            	$hierarchy[$record['college']][$record['department']][$record['code']] = $record['subject'];
+            }
+            self::$_hierarchy = $hierarchy;
+        }
+        return self::$_hierarchy;
+    }
+
+
     public function getCourseNumber()
     {
         $homeNumber = '';
@@ -1557,7 +1692,7 @@ class Courses_CourseModel extends Unl_Model
         if (!self::isSubjectValid($subject)) {
             throw new Zend_Exception('The subject code ' . $subject . ' is invalid.');
         }
-		
+
 		$homeIndex = null;
 		foreach ($this->_data['crosslistings'] as $index => $crosslisting) {
 			if ($crosslisting['type'] == 'home listing') {
@@ -1590,6 +1725,24 @@ class Courses_CourseModel extends Unl_Model
         return $homeDepartment;
     }
 
+    static public function getDepartments()
+    {
+        if (count(self::$_departments) == 0) {
+            $db = Zend_Registry::get('db');
+            $select = new Zend_Db_Select($db);
+            $select->from(array('d' => 'creqDepartments'));
+            $select->order('name');
+            $records = $select->query()->fetchAll();
+            $departments = array();
+            foreach ($records as $record) {
+                $departments[$record['departmentId']] = $record['name'];
+            }
+            self::$_departments = $departments;
+        }
+        return self::$_departments;
+    }
+
+
     public function getCollege()
     {
         $homeCollege = '';
@@ -1601,13 +1754,14 @@ class Courses_CourseModel extends Unl_Model
         }
         return $homeCollege;
     }
-    
+
     static public function getColleges()
-    {	
+    {
         if (count(self::$_colleges) == 0) {
             $db = Zend_Registry::get('db');
             $select = new Zend_Db_Select($db);
             $select->from(array('c' => 'creqColleges'));
+            $select->order('name');
             $records = $select->query()->fetchAll();
             $colleges = array();
             foreach ($records as $record) {
@@ -1618,6 +1772,23 @@ class Courses_CourseModel extends Unl_Model
         return self::$_colleges;
     }
 
+    static public function getCollegeNames()
+    {
+        if (count(self::$_collegeNames) == 0) {
+            $db = Zend_Registry::get('db');
+            $select = new Zend_Db_Select($db);
+            $select->from(array('c' => 'creqColleges'));
+            $select->order('description');
+            $records = $select->query()->fetchAll();
+            $colleges = array();
+            foreach ($records as $record) {
+                $colleges[$record['collegeId']] = $record['description'];
+            }
+            self::$_collegeNames = $colleges;
+        }
+        return self::$_collegeNames;
+    }
+
     public function isIntegratedStudies()
     {
     	$integratedStudies = false;
@@ -1681,7 +1852,7 @@ class Courses_CourseModel extends Unl_Model
     	if (!self::isSubjectValid($subject)) {
     		throw new Zend_Exception('The subject code ' . $subject . ' is invalid.');
     	}
-    	
+
         $lowestId = min(array_keys($this->_data['crosslistings']));
         if (!($lowestId < 0)) {
         	$lowestId = 0;
@@ -1702,7 +1873,7 @@ class Courses_CourseModel extends Unl_Model
         if (!self::isSubjectValid($subject)) {
             throw new Zend_Exception('The subject code ' . $subject . ' is invalid.');
         }
-        
+
         if (!$this->_data['crosslistings'][$id]) {
         	throw new Exception('Attempt to edit a non-existant crosslisting');
         }
@@ -1824,7 +1995,7 @@ class Courses_CourseModel extends Unl_Model
     	);
 
     	$this->_data['credits'][$lowestId] = $newCredit;
-    	
+
     }
 
     public function getCreditsText()
@@ -1928,7 +2099,7 @@ class Courses_CourseModel extends Unl_Model
     {
     	$activityMap = self::_getActivityMap();
     	$activityMap = array_flip($activityMap);
-    	
+
         $activityListing = array();
         foreach($this->_data['activities'] as $activity) {
             $newActivityListing = $activity['type'];
@@ -1945,7 +2116,7 @@ class Courses_CourseModel extends Unl_Model
 
         return $activities;
     }
-    
+
     static protected function _getActivityMap()
     {
     	if (!self::$_activityMap) {
@@ -1953,14 +2124,14 @@ class Courses_CourseModel extends Unl_Model
     	}
     	return self::$_activityMap;
     }
-    
+
     static protected function _loadActivityMap()
     {
     	$db = Zend_Registry::get('db');
     	$select = new Zend_Db_Select($db);
     	$select->from('creqActivityTypes');
     	$data = $select->query()->fetchAll();
-    	
+
     	foreach ($data as $row) {
     		self::$_activityMap[$row['activityTypeId']] = $row['shortName'];
     	}
@@ -1969,9 +2140,9 @@ class Courses_CourseModel extends Unl_Model
     public function setActivity($type, $hours = null)
     {
     	if ($hours == '') {
-    		$hours = null; 
+    		$hours = null;
     	}
-    	
+
     	$found = false;
         foreach ($this->_data['activities'] as $id => $activity) {
         	if ($activity['type'] == $type) {
@@ -2034,7 +2205,7 @@ class Courses_CourseModel extends Unl_Model
     {
         $this->_data['description'] = $description;
     }
-    
+
     public function getAceOutcomes()
     {
         if (!is_array($this->_data['aceOutcomes'])) {
@@ -2215,7 +2386,7 @@ class Courses_CourseModel extends Unl_Model
     {
         $this->_data['request'] = $request->getId();
     }
-    
+
     public function clearRequest()
     {
     	$this->_data['request'] = null;
@@ -2230,7 +2401,7 @@ class Courses_CourseModel extends Unl_Model
     {
         $this->_data['type'] = $type;
     }
-    
+
     public function getRemoved()
     {
     	if ($this->_data['removed'] == 'yes') {
@@ -2238,7 +2409,7 @@ class Courses_CourseModel extends Unl_Model
     	}
     	return false;
     }
-    
+
     public function setRemoved($removed = true)
     {
     	if ($removed) {
@@ -2248,6 +2419,11 @@ class Courses_CourseModel extends Unl_Model
     	}
     }
 
+    public function getCourseId()
+    {
+        return $this->_data['course'];
+    }
+
     public function isValid()
     {
     	//TODO: add criteria for this being valid
@@ -2256,35 +2432,38 @@ class Courses_CourseModel extends Unl_Model
     	}
     	return true;
     }
-    
+
     static $_subjectList;
-    
+    static $_subjectNames;
+
     static protected function _loadSubjectList()
     {
     	if (self::$_subjectList) {
     		return self::$_subjectList;
     	}
-    	
+
     	$db = Zend_Registry::get('db');
     	$select = new Zend_Db_Select($db);
-    	
-    	$select->from('creqSubjects', array('name'));
+
+    	$select->from('creqSubjects', array('subjectId', 'name', 'description'));
+    	$select->order('name');
     	$records = $select->query()->fetchAll();
     	self::$_subjectList = array();
     	foreach ($records as $record) {
-    		self::$_subjectList[] = $record['name'];
+    		self::$_subjectList[$record['subjectId']] = $record['name'];
+    		self::$_subjectNames[$record['subjectId']] = $record['description'];
     	}
-    	
+
     	return self::$_subjectList;
     }
-    
+
     static public function isSubjectValid($subject)
     {
     	self::_loadSubjectList();
-    	
+
     	return in_array($subject, self::$_subjectList);
     }
-    
+
     static public function makeCurrent($courseModels)
     {
         if (!Unl_Util::isArray($courseModels)) {
@@ -2295,19 +2474,19 @@ class Courses_CourseModel extends Unl_Model
         	$collection[] = $courseModels;
         	$courseModels = $collection;
         }
-        
+
         if (count($courseModels) == 0) {
         	return;
         }
-        
+
         $courseOfficialGenerations = array();
         foreach ($courseModels as $courseModel) {
         	$courseId = $courseModel->_data['course'];
         	$generationId = $courseModel->getId();
         	$courseOfficialGenerations[$courseId] = $generationId;
         }
-        
-        
+
+
 
         $db = Zend_Registry::get('db');
 
@@ -2330,7 +2509,7 @@ class Courses_CourseModel extends Unl_Model
              . 'WHERE a.courseId = b.courseId ';
 
         $db->query($sql);
-        
+
         $db->query('DROP TABLE creqCoursesUpdate');
     }
 
@@ -2355,13 +2534,13 @@ class Courses_CourseModel extends Unl_Model
 
         return $areas;
     }
-    
+
     /**
      * This function will create new generations of any courses with references to $oldCode and replace
      * them with $newCode.  All current official generations will have a new official generation created
      * the change, and all in-progress requests will have new generations created with the change.
      * This method should only be called !!ONCE!! for such a change.
-     * I recommend against having this method publicly available, except when needed. 
+     * I recommend against having this method publicly available, except when needed.
      *
      * @param string $oldCode
      * @param string $newCode
@@ -2370,7 +2549,7 @@ class Courses_CourseModel extends Unl_Model
     {
         $db = Zend_Registry::get('db');
         $generationIds = array();
-        
+
         // Get current official generation with crosslistings
         $select = new Zend_Db_Select($db);
         $select->from(array('c' => 'creqCourseCodes'), array());
@@ -2379,14 +2558,14 @@ class Courses_CourseModel extends Unl_Model
         $select->join(array('s' => 'creqCourses'), 'g.course = s.courseId', array('currentGeneration'));
         $select->where('c.subject = ?', $oldCode);
         $select->where('g.courseGenerationId = s.currentGeneration');
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['currentGeneration'];
         }
-        
-        
+
+
         // Get current official generation with prereq, notes, description, title
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseDetails'), array('prerequisite'));
@@ -2398,14 +2577,14 @@ class Courses_CourseModel extends Unl_Model
             $db->quoteInto('d.description LIKE ? OR ',  '%' . $oldCode . '%') .
             $db->quoteInto('d.title LIKE ?',            '%' . $oldCode . '%')
         );
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['currentGeneration'];
         }
-        
-        
+
+
         // Get current official generation with ace outcomes
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseAceOutcomes'));
@@ -2416,8 +2595,8 @@ class Courses_CourseModel extends Unl_Model
             $db->quoteInto('d.studentWork LIKE ? OR ',   '%' . $oldCode . '%') .
             $db->quoteInto('d.assesmentPlan LIKE ?',     '%' . $oldCode . '%')
         );
-        
-        
+
+
         // Get current official generation with ace reinforcements
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseAceReinforcements'));
@@ -2426,29 +2605,29 @@ class Courses_CourseModel extends Unl_Model
         $select->where(
             $db->quoteInto('d.description LIKE ?',     '%' . $oldCode . '%')
         );
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['currentGeneration'];
         }
-        
-        
-        // Get in-progress requests with crosslistings 
+
+
+        // Get in-progress requests with crosslistings
         $select = new Zend_Db_Select($db);
         $select->from(array('c' => 'creqCourseCodes'), array());
         $select->join(array('x' => 'creqCourseCrosslistings'), 'c.courseCodeId = x.courseCode', array('generation'));
         $select->join(array('g' => 'creqCourseGenerations'), 'x.generation = g.courseGenerationId', array('course', 'type'));
         $select->where('c.subject = ?', $oldCode);
         $select->where('g.courseGenerationId NOT IN (SELECT parent FROM creqCourseGenerations WHERE parent IS NOT NULL)');
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['generation'];
         }
-        
-        
+
+
         // Get in-progress requests with prereq, notes, description, title
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseDetails'), array('prerequisite'));
@@ -2460,14 +2639,14 @@ class Courses_CourseModel extends Unl_Model
             $db->quoteInto('d.title LIKE ?',            '%' . $oldCode . '%')
         );
         $select->where('g.courseGenerationId NOT IN (SELECT parent FROM creqCourseGenerations WHERE parent IS NOT NULL)');
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['generation'];
         }
-        
-        
+
+
         // Get in-progress requests with ace outcomes
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseAceOutcomes'));
@@ -2478,8 +2657,8 @@ class Courses_CourseModel extends Unl_Model
             $db->quoteInto('d.assesmentPlan LIKE ?',     '%' . $oldCode . '%')
         );
         $select->where('g.courseGenerationId NOT IN (SELECT parent FROM creqCourseGenerations WHERE parent IS NOT NULL)');
-        
-        
+
+
         // Get in-progress requests with ace reinforcements
         $select = new Zend_Db_Select($db);
         $select->from(array('d' => 'creqCourseAceReinforcements'));
@@ -2488,19 +2667,19 @@ class Courses_CourseModel extends Unl_Model
             $db->quoteInto('d.description LIKE ?',     '%' . $oldCode . '%')
         );
         $select->where('g.courseGenerationId NOT IN (SELECT parent FROM creqCourseGenerations WHERE parent IS NOT NULL)');
-        
+
         $data = $select->query()->fetchAll();
-        
+
         foreach ($data as $row) {
             $generationIds[] = $row['currentGeneration'];
         }
-        
-        
+
+
         sort($generationIds);
         $generationIds = array_unique($generationIds);
-        
+
         $officialGenerations = Courses_CourseModel::find($generationIds);
-        
+
         $parentMap = array();
         foreach ($officialGenerations as $course) {
             $newCourse = clone $course;
@@ -2531,16 +2710,16 @@ class Courses_CourseModel extends Unl_Model
                     strtr($aceReinforcement['description'], array($oldCode => $newCode))
                 );
             }
-            
+
             $newCourse->setEffectiveSemester('20092');
             if ($newCourse->getType() == 'official') {
                 $newCourse->clearRequest();
             }
-            
+
             Courses_CourseModel::save($newCourse);
             $parentMap[$course->getId()] = $newCourse->getId();
         }
-        
+
         foreach ($parentMap as $oldId => $newId) {
             $sql = "UPDATE creqCourseGenerations SET parent = $newId WHERE parent = $oldId AND courseGenerationId != $newId";
             $db->query($sql);
diff --git a/application/modules/courses/views/scripts/public-view/results.phtml b/application/modules/courses/views/scripts/public-view/results.phtml
new file mode 100644
index 00000000..54c56a85
--- /dev/null
+++ b/application/modules/courses/views/scripts/public-view/results.phtml
@@ -0,0 +1,41 @@
+<?php $this->headLink()->appendStylesheet($this->baseUrl() . '/css/iace/reports/weekly.css', 'all'); ?>
+<?php $this->layout()->tagline = ''; ?>
+<?php $this->layout()->hideMenu = true; ?>
+
+<h2>
+    ACE Certified Courses<br />
+    Interim ACE Committee<br />
+</h2>
+
+<table>
+    <tr>
+        <th><a href="<?php echo $this->url(array_merge($this->criteria, array('sort' => 'slo'))); ?>">SLO</a></th>
+        <th><a href="<?php echo $this->url(array_merge($this->criteria, array('sort' => 'college'))); ?>">College</a></th>
+        <th><a href="<?php echo $this->url(array_merge($this->criteria, array('sort' => 'courseCode'))); ?>">Course</a></th>
+        <th><a href="<?php echo $this->url(array_merge($this->criteria, array('sort' => 'title'))); ?>">Title</a></th>
+    </tr>
+    <?php foreach ($this->data as $record) { ?>
+    <tr <?php if ($rowCount++ % 2) { ?>class="even"<?php } ?>>
+        <td>
+            <a href="<?php echo $this->baseUrl(); ?>/courses/public-view/view/id/<?php echo $record->getCourseId(); ?>">
+                <?php echo $record->getSlo(); ?>
+            </a>
+        </td>
+        <td>
+            <a href="<?php echo $this->baseUrl(); ?>/courses/public-view/view/id/<?php echo $record->getCourseId(); ?>">
+                <?php echo $record->getCollege(); ?>
+            </a>
+        </td>
+        <td>
+            <a href="<?php echo $this->baseUrl(); ?>/courses/public-view/view/id/<?php echo $record->getCourseId(); ?>">
+                <?php echo $record->getCourseCode(); ?>
+            </a>
+        </td>
+        <td>
+            <a href="<?php echo $this->baseUrl(); ?>/courses/public-view/view/id/<?php echo $record->getCourseId(); ?>">
+                <?php echo $record->getTitle(); ?>
+            </a>
+        </td>
+    </tr>
+    <? } ?>
+</table>
\ No newline at end of file
diff --git a/application/modules/courses/views/scripts/public-view/search.phtml b/application/modules/courses/views/scripts/public-view/search.phtml
new file mode 100644
index 00000000..7666a099
--- /dev/null
+++ b/application/modules/courses/views/scripts/public-view/search.phtml
@@ -0,0 +1,57 @@
+<?php $this->headLink()->appendStylesheet($this->baseUrl() . '/css/courses/public-view/search.css', 'all'); ?>
+
+<form method="get" action="<?php echo $this->baseUrl(); ?>/courses/public-view/results">
+    <label class="row">
+        <span class="label">College</span>
+        <?php echo $this->formSelect('college', null, null, array(0 => '--Select a College--') + $this->colleges); ?>
+    </label>
+    <label class="row">
+        <span class="label">Department</span>
+        <?php echo $this->formSelect('department', null, null, array(0 => '--Select a Department--') + $this->departments); ?>
+    </label>
+    <label class="row">
+        <span class="label">Subject Area</span>
+        <?php echo $this->formSelect('subject', null, null, array('' => '--Select a Subject--') + $this->subjects); ?>
+    </label>
+    <label class="row">
+        <span class="label">Course #</span>
+        <?php echo $this->formText('courseNumber'); ?>
+    </label>
+    <label class="row">
+        <span class="label">&nbsp;</span>
+        Specific number (i.e. 101) or Partial number (i.e. 1 for 100 level courses)
+    </label>
+    <label class="row">
+        <span class="label">Course Letter</span>
+        <?php echo $this->formText('courseLetter'); ?>
+    </label>
+    <label class="row">
+        <span class="label">Course Title Keyword</span>
+        <?php echo $this->formText('courseTitle'); ?>
+    </label>
+    <label class="row">
+        <span class="label">Activity Type</span>
+        <?php echo $this->formSelect('activity', null, null, array(-1 => '--Select Activity--',
+                                                                   1 => 'Lec - Lecture',
+                                                                   2 => 'Lab - Lab',
+                                                                   3 => 'Quz - Quiz',
+                                                                   4 => 'Rct - Recitation',
+                                                                   5 => 'Stu - Studio',
+                                                                   6 => 'Fld - Field',
+                                                                   7 => 'Ind - Independent Study',
+                                                                   8 => 'Psi - Personalized System of Instruction')); ?>
+    </label>
+    <div class="row">
+        <span class="label">Display Only</span>
+        <label><?php echo $this->formCheckbox('ace'); ?>ACE</label>
+        <label><?php echo $this->formCheckbox('essentialStudies'); ?>ES</label>
+        <label><?php echo $this->formCheckbox('integratedStudies'); ?>IS</label>
+        <label><?php echo $this->formCheckbox('specialFee', null, array('disabled' => 'disabled')); ?>Special Fee</label>
+    </div>
+    <label class="row">
+        <span class="label">Campus</span>
+        <?php echo $this->formSelect('campus', null, null, array('' => '--Select a Campus--', 'UNL' => 'UNL', 'UNO' => 'UNO', 'UNK' => 'UNK')); ?>
+    </label>
+    
+    <?php echo $this->formSubmit('submit', 'Search'); ?>
+</form>
\ No newline at end of file
diff --git a/application/modules/courses/views/scripts/public-view/view.phtml b/application/modules/courses/views/scripts/public-view/view.phtml
new file mode 100644
index 00000000..599bbf39
--- /dev/null
+++ b/application/modules/courses/views/scripts/public-view/view.phtml
@@ -0,0 +1,6 @@
+<?php $this->headLink()->appendStylesheet($this->baseUrl() . '/css/courses/view.css', 'all'); ?>
+<?php $this->layout()->hideMenu = true; ?>
+
+<div class="bulletinEntry">
+<?php echo $this->bulletinEntry($this->course); ?>
+</div>
\ No newline at end of file
-- 
GitLab