<?php
namespace App\Controller;
use App\Document\ClassSchedule;
use App\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
/**
* Javascript Controller
*
* Dynamically create javascript
*
* @Route("/dynamic-assets")
* @author "Cornell University, Student Services IT"
*/
class JavascriptController extends AbstractController
{
/**
* Creates global RosterSharedConfig variables
* Used for configuration values across Class Roster
*
* Used for roster.config Angular Module enables .RosterConfig constant
*
* Single cached response for each roster
*
* @Route("/{rosterSlug}/RosterSharedConfig.js", name="app_js_roster_shared_config", methods={"GET"})
* @return \Symfony\Component\HttpFoundation\Response
*/
public function rosterSharedConfigAction($rosterSlug)
{
$roster = $this->getSystemSettings()->getRosterBySlug($rosterSlug);
if (!$roster) {
throw new NotFoundHttpException('Roster Not Found');
}
$response = new Response();
if ($this->isGatewayCacheEnabled()) {
$response->setPublic();
$response->setMaxAge($this->getGatewayCacheLifetime());
$response->setSharedMaxAge($this->getGatewayCacheLifetime());
}
$response->headers->set('Content-Type', 'text/javascript');
// color palettes
$colorChoices = [];
$colorPaletteData = $this->getConnection()->fetchAll('SELECT DISTINCT palette FROM colorchoice ORDER BY palette');
$colorPalettes = [];
foreach ($colorPaletteData AS $colorPalette) {
$colors = $this->getConnection()->fetchAll('SELECT * FROM colorchoice WHERE palette=? ORDER BY title', [$colorPalette['palette']]);
$colorPaletteChoices = [];
foreach ($colors AS $color) {
$colorPaletteChoices[] = [
'code' => $color['code_primary'],
'meta' => ['secondary' => $color['code_secondary'], 'title' => $color['title']]
];
}
$colorChoices[$colorPalette['palette']][] = $colorPaletteChoices;
$colorPalettes[] = $colorPalette['palette'];
}
// random events
$randomEvents = $this->getConnection()->fetchAll('SELECT title, location FROM randomevent');
// do not re-poll service if within this increment
$rosterSchedulerConfig = $this->getParameter('roster_scheduler');
$ttlMinFav = $rosterSchedulerConfig['ttl_min_fav'];
// wait at least # seconds before saving to throttle repeated changes
$ttlMinSave = $rosterSchedulerConfig['ttl_min_save'];
// min Ttl before considering course-detail data stale, should be at least as long
// as CapLoader refresh sequence
$ttlMinCourseDetail = $rosterSchedulerConfig['ttl_min_course_detail'];
$availRosters = [];
$allAvailableRosters = $this->getSystemSettings()->getAvailableRosters();
foreach ($allAvailableRosters as $availableRoster) {
$availRosters[$availableRoster->getStrm()] = $availableRoster;
}
$termSetup = $this->getSystemSettings()->getTermSetup($roster);
$navRosters = array_values($this->getSystemSettings()->getDropdownRosters()->toArray());
// terms - used by termTranslate filter in Syllabi for Enrollment display
$minStrm = 2363;
$academicTerms = $this->getDocumentManager()->createQueryBuilder('AppBundle:Term')->field('strm')->gte($minStrm)->getQuery()->execute();
return $this->render('Javascript/rosterSharedConfig.js.twig', ['colorPalettes' => json_encode($colorPalettes),
'colorChoices' => json_encode($colorChoices),
'randomEvents' => json_encode($randomEvents),
'ttlMinFav' => $ttlMinFav,
'ttlMinSave' => $ttlMinSave,
'ttlMinCourseDetail' => $ttlMinCourseDetail,
'availRosters' => json_encode($availRosters),
'navRosters' => json_encode($navRosters),
'termSetup' => json_encode($termSetup),
'academicTerms' => $academicTerms,
'roster' => $roster,
], $response);
}
/**
* Support Scheduler's course search type-ahead. All searches previously server side.
*
* @Route("/{rosterSlug}/CourseTypeahead.js", name="app_js_roster_course_typeahead", methods={"GET"})
* @return \Symfony\Component\HttpFoundation\Response
*/
public function courseTypeaheadAction($rosterSlug)
{
$roster = $this->getSystemSettings()->getRosterBySlug($rosterSlug);
if (!$roster) {
throw new NotFoundHttpException('Roster Not Found');
}
$response = new Response();
if ($this->isGatewayCacheEnabled()) {
$response->setPublic();
$response->setMaxAge($this->getGatewayCacheLifetime());
$response->setSharedMaxAge($this->getGatewayCacheLifetime());
}
$response->headers->set('Content-Type', 'text/javascript');
$courses = [];
$qb = $this->getDocumentManager()->createQueryBuilder('App\Document\ClassSchedule');
// assigning results back to $qb allows us to modify results before returning
$qb = $qb
->select('crseId', 'crseOfferNbr', 'subject', 'catalogNbr', 'titleShort', 'titleLong')
->field('versionId')->equals($roster->getVersion()->getId())
->sort('subject', 'asc')
->sort('catalogNbr', 'asc')
->getQuery();
$cursor = $qb->execute();
/** @var ClassSchedule $classSchedule */
foreach ($cursor as $classSchedule) {
$courses[] = ['i' => $classSchedule->getCrseId(),
'o' => $classSchedule->getCrseOfferNbr(),
's' => $classSchedule->getSubject(),
'n' => $classSchedule->getCatalogNbr(),
'ts' => $classSchedule->getTitleShort()?$classSchedule->getTitleShort():'',
'tl' => $classSchedule->getTitleLong()?$classSchedule->getTitleLong():'',
];
}
return $this->render('Javascript/courseTypeahead.js.twig', ['courses' => json_encode($courses),
'roster' => $roster
], $response);
}
}