Changeset - f2de63b6af0b
[Not reviewed]
default
0 6 0
Nathan Brink (binki) - 14 years ago 2011-04-09 00:27:03
ohnobinki@ohnopublishing.net
Save the school_id and semester data with a saved_schedule. Make the school_id and semester local to the input page.

Now one can open multiple tabs and be using autocomplete for multiple semesters/schools using the same session.
6 files changed with 198 insertions and 27 deletions:
0 comments (0 inline, 0 general)
auto.php
Show inline comments
 
@@ -56,17 +56,22 @@ if (isset($_REQUEST['getsections'])) {
 
$term = $_REQUEST['term'];
 
$term_parts = Course::parse($term);
 
if (!count($term_parts)) {
 
  clean_empty_exit();
 
}
 

	
 
$school = school_load_guess();
 
/*
 
 * We let the *_load_guess() functions check $_REQUEST['school'] and
 
 * $_REQUEST['semester'] for us, asking them not to update the
 
 * session.
 
 */
 
$school = school_load_guess(FALSE);
 
if (!$school['crawled']) {
 
  clean_empty_exit();
 
}
 
$semester = school_semester_guess($school);
 
$semester = school_semester_guess($school, FALSE);
 

	
 
$cache_dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'auto'
 
  . DIRECTORY_SEPARATOR . $school['id'] . DIRECTORY_SEPARATOR . $semester['id'] . DIRECTORY_SEPARATOR;
 

	
 
/*
 
 * autocomplete the list of departments. If the user has already
inc/class.page.php
Show inline comments
 
@@ -81,20 +81,31 @@ class page
 
  private $pagetitle = ''; // Title of page
 
  private $scripts = array(); // Scripts to include on page
 

	
 
  /* the current school. See get_school(). */
 
  private $school;
 

	
 
  private $semester;
 

	
 
  /*
 
   * Whether or not the user should be presented with the option to
 
   * change the school profile or semester.
 
   */
 
  private $school_semester_constant;
 

	
 
  /**
 
   * \param $ntitle
 
   *   Must be a valid HTML string (i.e., escaped with htmlentities()).
 
   * \param $nscripts
 
   *   An array of strings identifying the scripts to include for this page.
 
   * \param $options
 
   *   An array containing any of the following keys:
 
   *     - 'school': The school to use instead of the autodetected one.
 
   *     - 'semester': The semester to use instead of the autodetected one.
 
   */
 
  public function __construct($ntitle, $nscripts = array(), $immediate = TRUE)
 
  public function __construct($ntitle, $nscripts = array(), $immediate = TRUE, array $options = array())
 
  {
 
    /* Begin tracking generation time */
 
    $this->pageGenTime = round(microtime(),4);
 

	
 
    global $ga_trackers;
 

	
 
@@ -146,14 +157,23 @@ class page
 
	 . "  </script>\n";
 
     }
 

	
 
    self::session_start();
 
    /* everything that needs sessions started to work: */
 

	
 
    $this->school = school_load_guess();
 
    $this->semester = school_semester_guess($this->school);
 
    if (empty($options['school']))
 
      $options['school'] = school_load_guess();
 
    $this->school = $options['school'];
 

	
 
    if (empty($options['semester']))
 
      $options['semester'] = school_semester_guess($this->school);
 
    $this->semester = $options['semester'];
 

	
 
    if (!isset($options['school_semester_constant']))
 
      $options['school_semester_constant'] = TRUE;
 
    $this->school_semester_constant = (bool)$options['school_semester_constant'];
 

	
 
    if($immediate
 
       && $ntitle != "NOHEAD")
 
      $this->head();
 
 }
 

	
 
@@ -169,16 +189,23 @@ class page
 
   *   The title of the page. Must be completely UTF-8 (will be
 
   *   escaped for you with htmlentitites()).
 
   * \param $scripts
 
   *   A list of scripts which the page desires to be included in the
 
   *   <head /> of the page. Should this param just be moved to the
 
   *   page::head() function?
 
   * \param $options
 
   *   An array containing any of the following keys:
 
   *     - 'school': The school to use instead of the autodetected one.
 
   *     - 'semester': The semester to use instead of the autodetected one.
 
   *     - 'school_semester_constant': Whether the options to change
 
   *        the current school and semester should be hidden. TRUE by
 
   *        default.
 
   */
 
  public static function page_create($title, array $scripts = array())
 
  public static function page_create($title, array $scripts = array(), array $options = array())
 
  {
 
    return new page(htmlentities($title), $scripts, FALSE);
 
    return new page(htmlentities($title), $scripts, FALSE, $options);
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Adds some headcode to this page.
 
   *
 
@@ -219,13 +246,16 @@ class page
 
          '    <!--[if IE]>'. PHP_EOL .
 
          '      <link rel="stylesheet" type="text/css" media="screen" charset="utf-8" href="styles/ie.css" />'. PHP_EOL .
 
          '    <![endif]-->'. PHP_EOL .
 
          '    <link rel="shortcut icon" href="images/favicon.png" />'. PHP_EOL
 
      . '    <style type="text/css">' . PHP_EOL
 
      . $this->cdata_wrap(school_page_css($this->school))
 
      . '    </style>' . PHP_EOL;
 
      . '    </style>' . PHP_EOL
 
      . $this->script_wrap(''
 
			   . 'var slate_permutate_school = ' . json_encode($this->school['id']) . ';' . PHP_EOL
 
			   . 'var slate_permutate_semester = ' . json_encode($this->semester['id']) . ';' . PHP_EOL);
 
    // Write out all passed scripts
 
    foreach ($this->scripts as $i)
 
      echo '    ' . $this->headCode["$i"] . "\n";
 

	
 
    echo '  </head>' . PHP_EOL .
 
	 '  <body>'. PHP_EOL .
 
@@ -233,15 +263,15 @@ class page
 
         '      <div id="header">'. PHP_EOL .
 
	 '        <div id="title">'. PHP_EOL .
 
         '          <h1><a href="index.php"><img src="images/slatepermutate-alpha.png" alt="SlatePermutate" class="noborder" /></a><br /></h1>'. PHP_EOL .
 
         '          <p>'. PHP_EOL .
 
         '            <span id="subtitle">'.$this->pagetitle.'</span>'. PHP_EOL .
 
  	 '            <span id="menu">' . PHP_EOL
 
      . '              Profile: '.$this->school['name'].' <a href="input.php?selectschool=1">(change)</a>' . PHP_EOL;
 
    if ($this->semester !== NULL)
 
      echo  '             Semester: ' . $this->semester['name'] . '<a href="input.php?selectsemester=1">(change)</a>' . PHP_EOL;
 
      . '              Profile: <em>' . $this->school['name'] . '</em>' . ($this->school_semester_constant ? '' : ' <a href="input.php?selectschool=1">(change)</a>') . PHP_EOL;
 
    if (!empty($this->semester))
 
      echo  '             Semester: <em>' . $this->semester['name'] . '</em>' . ($this->school_semester_constant ? '' : ' <a href="input.php?selectsemester=1">(change)</a>') . PHP_EOL;
 
    echo '            </span>'. PHP_EOL .
 
         '          </p>'. PHP_EOL .
 
         '        </div>'. PHP_EOL .
 
	 '      </div>'. PHP_EOL .
 
         '      <div id="content">'. PHP_EOL;
 
  }
 
@@ -523,12 +553,21 @@ class page
 
  {
 
    return $this->school;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Get the current semester.
 
   */
 
  public function semester_get()
 
  {
 
    return $this->semester;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Format a chunk of javascript suitable for adding to headcode.
 
   *
 
   * Takes into account whether or not the code should be wrapped in
 
   * CDATA or not.
 
   *
 
   * \param $js
inc/class.schedule.php
Show inline comments
 
@@ -27,12 +27,13 @@
 
//**************************************************
 

	
 
$incdir = dirname(__FILE__) . DIRECTORY_SEPARATOR;
 
include_once $incdir . 'class.course.inc';
 
include_once $incdir . 'class.section.php';
 
include_once $incdir . 'class.page.php';
 
require_once $incdir . 'school.inc';
 

	
 
/*
 
 * Load a Classes -> Course converter class for the sake of the
 
 * Schedule::__wakeup() magic function.
 
 */
 
require_once $incdir . 'class.classes_convert.inc';
 
@@ -49,12 +50,30 @@ class Schedule
 
  /* My member variables. */
 
  private $courses;
 
  private $nPermutations = 0;		// Integer number of real permutations
 
  private $possiblePermutations;	// Integer number of possible permutations
 
  private $scheduleName;			// String name of schedule
 
  private $storage;				// Integer array of valid schedules
 
  /**
 
   * \brief
 
   *   The school_id of the school this schedule was created for.
 
   */
 
  private $school_id;
 
  /**
 
   * \brief
 
   *   The semester this schedule was created for.
 
   *
 
   * The semester array is stored in full in a schedule because some
 
   * schools do not keep a backlog of all semesters for their course
 
   * data. Such a school is calvin. We want to be able to access, for
 
   * example, the friendly name and so on of a semester even one year
 
   * after the semester is created without worrying about having that
 
   * semester be stored in the autocomplete cache.
 
   */
 
  private $semester;
 

	
 
  /* The <title /> of the page used when rendering this schedule */
 
  private $title;
 

	
 
  /**
 
   * \brief
 
   *   My global identification number. Not defined until the schedule
 
@@ -76,21 +95,40 @@ class Schedule
 
   *   A string, the friendly name the user gave this schedule.
 
   * \param $parent
 
   *   An integer, the id of the schedule from which this schedule is
 
   *   derived. A schedule is considered to be derived of another of
 
   *   the user created this schedule by clicking ``Edit'' for the
 
   *   previous schedule. Or NULL if this schedule stands on its own.
 
   * \param $school
 
   *   The school used for this schedule. The intention of storing
 
   *   this data is that people from different schools may share
 
   *   schedules with eachother. Also, people who bookmark their
 
   *   schedules and want to edit their schedules should not have to
 
   *   go through the school selection dialogue again but should just
 
   *   be set to use the correct school.
 
   * \param $semester
 
   *   The semester used for this schedule.
 
   */
 
  function __construct($name, $parent = NULL)
 
  function __construct($name, $parent = NULL, array $school = NULL, array $semester = NULL)
 
  {
 
    $this->courses = array();
 
    $this->scheduleName = $name;
 
    $this->storage = array();
 
    $this->title = "SlatePermutate - Scheduler";
 
    $this->parent_id = $parent;
 

	
 
    if (empty($school))
 
      $school = school_load_guess();
 
    $this->school_id = $school['id'];
 

	
 
    if (empty($semester))
 
      {
 
	$semester = school_semester_guess($school);
 
      }
 
    $this->semester = $semester;
 

	
 
    /* mark this as an upgraded Schedule class. See __wakeup() */
 
    $this->nclasses = -1;
 
  }
 

	
 
  //--------------------------------------------------
 
  // Mutators and Accessors
 
@@ -149,12 +187,51 @@ class Schedule
 
	}
 

	
 
    error_log('Could not find class when parsing schedule from postData: ' . $course_name);
 
    echo 'Could not find class: ' . $course_name . "<br />\n";
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Get the school associated with this schedule.
 
   *
 
   * \return
 
   *   The school associated with this schedule or some fallback.
 
   */
 
  public function school_get()
 
  {
 
    $school = NULL;
 

	
 
    if (!empty($this->school_id))
 
      /*
 
       * May return NULL, so we don't just return this value right
 
       * away -- we fall through.
 
       */
 
      $school = school_load($this->school_id);
 
    if (empty($school))
 
      {
 
	/* Ensure we have $_SESSION. */
 
	page::session_start();
 
	$school = school_load_guess();
 
      }
 

	
 
    return $school;
 
  }
 

	
 
  /**
 
   * \brief
 
   *   Get the semester associated with this schedule.
 
   *
 
   * \return
 
   *   The schedule's associated semester.
 
   */
 
  public function semester_get()
 
  {
 
    return $this->semester;
 
  }
 

	
 
  //--------------------------------------------------
 
  // Finds all of the possible permutations and stores
 
  // the results in the storage array.
 
  //--------------------------------------------------
 
	function findPossibilities()
 
	{
 
@@ -290,13 +367,14 @@ class Schedule
 
    if(isset($_REQUEST['print']) && $_REQUEST['print'] != ''){
 
      $headcode = array('jQuery', 'jQueryUI', 'uiTabsKeyboard', 'outputStyle', 'outputPrintStyle', 'displayTables');
 
    }
 
    else {
 
      $headcode = array('outputStyle',  'jQuery', 'jQueryUI', 'jAddress', 'uiTabsKeyboard', 'qTip2','displayTables');
 
    }
 
    $outputPage = page::page_create(htmlentities($this->getName()), $headcode);
 
    $outputPage = page::page_create(htmlentities($this->getName()), $headcode,
 
				    array('school' => $this->school_get(), 'semester' => $this->semester_get()));
 
    $outputPage->head();
 

	
 

	
 

	
 
    if(isset($_REQUEST['print'])) {
 
 
 
@@ -736,8 +814,27 @@ class Schedule
 
	$this->courses[] = $classes->to_course();
 
      }
 
    $this->nclasses = -1;
 

	
 
    if (empty($this->parent_id))
 
      $this->parent_id = NULL;
 

	
 
    if (empty($this->school_id))
 
      {
 
	/* Ensure we have $_SESSION. */
 
	page::session_start();
 
	$school = school_load_guess();
 
	$this->school_id = $school['id'];
 
      }
 
    if (empty($this->semester))
 
      {
 
	if (empty($school))
 
	  {
 
	    /* Ensure we have $_SESSION. */
 
	    page::session_start();
 

	
 
	    $school = school_load($this->school_id);
 
	    $this->semester = school_semester_guess($school);
 
	  }
 
      }
 
  }
 
}
inc/school.inc
Show inline comments
 
@@ -109,24 +109,35 @@ function school_load($school_id, $load_a
 
 * This function checks if $_REQUEST['school'] is set to a valid
 
 * school, so that the user can manually choose his school. Then it
 
 * chcecks if the user's session specifies what school profile to
 
 * use. Then it tries to make a best guess as to the school he's from
 
 * using the rDNS information provided by the httpd.
 
 *
 
 * \param $update_session
 
 *   Whether or not the results should be stored into the session for
 
 *   later use. A value of disabled makes sense for the auto.php AJAX
 
 *   callback script, where the user is not loading a page himself but
 
 *   the current school is being specified in the URL
 
 *   parameters... thus updating the session value here would be a
 
 *   side-effect. We're doing this so that the user can do
 
 *   autocomplete for two different school/semester pairs in two
 
 *   different browser tabs under the same session.
 
 *
 
 * \return
 
 *   A school profile or NULL if the school isn't in the session and
 
 *   can't be guessed.
 
 */
 
function school_load_guess()
 
function school_load_guess($update_session = TRUE)
 
{
 
  if (isset($_REQUEST['school']))
 
    {
 
      $school = school_load($_REQUEST['school']);
 
      if ($school)
 
	{
 
	  $_SESSION['school'] = $school['id'];
 
	  if ($update_session)
 
	    $_SESSION['school'] = $school['id'];
 
	  return $school;
 
	}
 
    }
 

	
 
  /* assume that we stored a valid school in the $_SESSION */
 
  if (isset($_SESSION['school']))
 
@@ -157,28 +168,30 @@ function school_load_guess()
 
	   */
 
	  if ($domain_school)
 
	    {
 
	      $school = school_load($domain_school);
 
	      if ($school)
 
		{
 
		  $_SESSION['school'] = $domain_school;
 
		  if ($update_sesssion)
 
		    $_SESSION['school'] = $domain_school;
 
		  return school_load($domain_school);
 
		}
 
	    }
 
	}
 
    }
 

	
 
  /*
 
   * set something in $_SESSION so that the gethostbyaddr() call
 
   * doesn't have to be done too often. (the isset() call above should
 
   * detect even the empty string).
 
   */
 
  $_SESSION['school'] = 'default';
 
  if ($update_session)
 
    $_SESSION['school'] = 'default';
 

	
 
  /* loading the school_id of 'default' MUST always work */
 
  return school_load($_SESSION['school']);
 
  return school_load('default');
 
}
 

	
 
/**
 
 * \brief
 
 *   Render a list of school profile choices.
 
 *
 
@@ -328,26 +341,30 @@ function school_semesters(array $school)
 
 * \brief
 
 *   Return the semester which either the user has selected or which
 
 *   makes the most sense.
 
 *
 
 * \param $school
 
 *   The school for which a semester should be guessed.
 
 * \param $update_session
 
 *   Whether or not $_SESSION should be updatd with the new value. A
 
 *   value of FALSE makes sense for the ajax.php callback script.
 
 * \return
 
 *   An array with the keys 'id', 'name', and 'weight' corresponding
 
 *   to the same keys in the arrays returned by school_semesters() or
 
 *   NULL if no semester can be found.
 
 */
 
function school_semester_guess(array $school)
 
function school_semester_guess(array $school, $update_session = FALSE)
 
{
 
  $semesters = school_semesters($school);
 

	
 
  if (!empty($_REQUEST['semester'])
 
      && isset($semesters[$_REQUEST['semester']]))
 
    {
 
      $semester = $semesters[$_REQUEST['semester']];
 
      $_SESSION['semester'] = $semester['id'];
 
      if ($update_session)
 
	$_SESSION['semester'] = $semester['id'];
 
      return $semester;
 
    }
 

	
 
  if (!empty($_SESSION['semester'])
 
      && isset($semesters[$_SESSION['semester']]))
 
      return $semesters[$_SESSION['semester']];
input.php
Show inline comments
 
@@ -21,26 +21,25 @@
 
include_once 'inc' . DIRECTORY_SEPARATOR . 'class.schedule.php';
 
include_once 'inc' . DIRECTORY_SEPARATOR . 'class.course.inc';
 
include_once 'inc' . DIRECTORY_SEPARATOR . 'class.section.php';
 
include_once 'inc' . DIRECTORY_SEPARATOR . 'class.page.php';
 
require_once('inc' . DIRECTORY_SEPARATOR . 'schedule_store.inc');
 

	
 
$scripts = array('jQuery', 'jQueryUI', 'qTip2', 'schedInput');
 
$inputPage = page::page_create('Scheduler', $scripts, FALSE);
 

	
 
$schedule_store = FALSE;
 
$sch = FALSE;
 
$errors_fix = FALSE;
 
$school = $inputPage->get_school();
 
$inputPage_options = array('school_semester_constant' => FALSE);
 

	
 
$parent_schedule_id = NULL;
 
if (isset($_REQUEST['s']))
 
  {
 
    $schedule_store = schedule_store_init();
 
    $parent_schedule_id = (int)$_REQUEST['s'];
 
    $sch = schedule_store_retrieve($schedule_store, $parent_schedule_id);
 
    $inputPage_options += array('school' => $sch->school_get(),
 
				'semester' => $sch->semester_get());
 
  }
 
elseif (!empty($_REQUEST['e']))
 
  {
 
    /*
 
     * Read an errorful schedule out of $_POST, this $_POST is created
 
     * by process.php when the originally sinful user produces bad
 
@@ -48,12 +47,21 @@ elseif (!empty($_REQUEST['e']))
 
     */
 
    $errors_fix = TRUE;
 
    if (!empty($_POST['postData']['parent_schedule_id']))
 
      $parent_schedule_id = (int)$_POST['postData']['parent_schedule_id'];
 
  }
 

	
 
/*
 
 * We cannot initialize the page object nor guess the school before
 
 * figuring loading a saved schedule because we'll default to that
 
 * saved_schedule's school/semester.
 
 */
 
$scripts = array('jQuery', 'jQueryUI', 'qTip2', 'schedInput');
 
$inputPage = page::page_create('Scheduler', $scripts, $inputPage_options);
 
$school = $inputPage->get_school();
 

	
 
$my_hc = 'var slate_permutate_example_course_id = ' . json_encode(school_example_course_id($inputPage->get_school())) . ';
 

	
 
jQuery(document).ready(
 
  function()
 
  {
 
    var class_last = 0;
 
@@ -183,13 +191,13 @@ if (!empty($_REQUEST['selectsemester']))
 
<input
 
    id="scheduleName"
 
    style="margin-bottom: 1em;"
 
    class="defText required"
 
    type="text"
 
    size="25"
 
    title="My <?php echo $inputPage->semester['name'] ?> Schedule"
 
    title="My <?php $semester = $inputPage->semester_get(); echo $semester['name'] ?> Schedule"
 
    name="postData[name]"
 
    <?php
 
      if ($sch)
 
        echo 'value="' . htmlentities($sch->getName(), ENT_QUOTES) . '"';
 
      elseif ($errors_fix)
 
        echo 'value="' . htmlentities($_POST['postData']['name'], ENT_QUOTES) . '"';
scripts/scheduleInput.js
Show inline comments
 
@@ -272,25 +272,30 @@ function add_class_n(course_id, title)
 
    tr_course.data({course_i: classNum});
 
    tr_course.find('.course-title-entry').val(title);
 
    tr_course.find('.className').val(course_id);
 

	
 
		var class_elem = jQuery('.className' + classNum);
 

	
 
		class_elem.autocomplete({ source: 'auto.php' });
 
		class_elem.autocomplete({ source: 'auto.php?school=' + slate_permutate_school + '&semester=' + slate_permutate_semester });
 
		class_elem.bind('autocompleteselect', {class_num: classNum, class_elem: class_elem},
 
			function(event, ui)
 
			    {
 
				if (!ui.item)
 
				    return;
 

	
 
				if (ui.item.value.indexOf('-') != -1)
 
				    {
 
					jQuery.ajax(
 
						    {
 
							url: 'auto.php',
 
							    data: {'getsections': 1, 'term': ui.item.value},
 
							    data: {
 
    							        getsections: 1,
 
								term: ui.item.value,
 
								school: slate_permutate_school,
 
								semester: slate_permutate_semester
 
								},
 
							    context: {'class_num': event.data.class_num},
 
							    success: function(data, textStatus, reqobj)
 
							    {
 
								var new_course_num;
 

	
 
								if (data.sections)
0 comments (0 inline, 0 general)