Skip to content

Commit

Permalink
Merge pull request cranleighschool#19 from cranleighschool/feature/pu…
Browse files Browse the repository at this point in the history
…piltimetable

Feature/pupiltimetable
  • Loading branch information
fredbradley authored Jun 23, 2021
2 parents c741ba2 + 4cf727d commit 97b137f
Show file tree
Hide file tree
Showing 9 changed files with 404 additions and 12 deletions.
111 changes: 100 additions & 11 deletions src/Controllers/PupilTimetableController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,128 @@
namespace spkm\isams\Controllers;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use spkm\isams\Endpoint;
use spkm\isams\Wrappers\PupilTimetable;
use spkm\isams\Wrappers\Lesson;
use spkm\isams\Wrappers\SchoolTerm;
use spkm\isams\Wrappers\TimetableDay;

/**
* Class PupilTimetableController.
*/
class PupilTimetableController extends Endpoint
{
/**
* Set the URL the request is made to.
* @var \Carbon\Carbon
*/
public $termStart;
/**
* @var \Carbon\Carbon
*/
public $termEnd;

/**
* @param string $schoolId
*
* @return void
* @throws \Exception
* @return \Illuminate\Support\Collection
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function setEndpoint()
public function getWeekCalendar(string $schoolId): Collection
{
$this->endpoint = $this->getDomain() . '/api/timetables/students';
$timetable = $this->show($schoolId);
$result = [];
foreach ($this->getTimetableStructure() as $day => $days) {
foreach ($days as $period) {
$lesson = collect($timetable['sets'])->filter(function ($item) use ($period) {
return $item->periodId === $period->id;
})->map(function ($item) {
return new Lesson($item);
})->first();
if ($lesson) {
$subjectName = $this->getSubject($lesson->subjectId)->name;
$lesson->subjectName = $subjectName;
}
$period->lesson = $lesson;
$result[$day][] = $period;
}
}

return collect($result)->map(function ($item) {
return new TimetableDay($item);
});
}

/**
* Get the timetable for the specified pupil.
*
* @param string $schoolId
* @param string $schoolId
*
* @return \Illuminate\Support\Collection
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function show(string $schoolId): Collection
{
$this->endpoint = $this->endpoint . '/' . $schoolId;

$response = $this->guzzle->request('GET', $this->endpoint, ['headers' => $this->getHeaders()]);
$response = $this->guzzle->request('GET', $this->endpoint,
['headers' => $this->getHeaders()]);

$decoded = json_decode($response->getBody()->getContents());

return collect($decoded)->map(function ($item) {
return new PupilTimetable($item);
return collect($decoded);
}

/**
* @return \Illuminate\Support\Collection
*/
private function getTimetableStructure(): Collection
{
$key = $this->institution->getConfigName() . 'timetableStructure.index';

return Cache::remember($key, now()->addWeek(), function () {
$schedule = new TimetableStructureController($this->institution);

return $schedule->index();
});
}

/**
* @param int $subjectId
*
* @return mixed
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function getSubject(int $subjectId)
{
$subjects = new TeachingSubjectController($this->institution);

return $subjects->index()->filter(function ($subject) use ($subjectId) {
return $subject->id === $subjectId;
})->first();
}

/**
* @return \spkm\isams\Wrappers\SchoolTerm
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getCurrentTermDates(): SchoolTerm
{
$terms = new SchoolTermsController($this->institution);
$currentTerm = $terms->getCurrentTerm();

$this->termStart = $currentTerm->startDate;
$this->termEnd = $currentTerm->finishDate;

return $currentTerm;
}

/**
* Set the URL the request is made to.
*
* @return void
* @throws \Exception
*/
protected function setEndpoint()
{
$this->endpoint = $this->getDomain() . '/api/timetables/students';
}
}
150 changes: 150 additions & 0 deletions src/Controllers/SchoolTermsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

namespace spkm\isams\Controllers;

use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use spkm\isams\Endpoint;
use spkm\isams\Exceptions\FailedtoFindNearestTerm;
use spkm\isams\Wrappers\SchoolTerm;

class SchoolTermsController extends Endpoint
{
/**
* @var null
*/
private $terms = null;

/**
* Set the URL the request is made to.
*
* @return void
* @throws \Exception
*/
protected function setEndpoint()
{
$this->endpoint = $this->getDomain() . '/api/school/terms';
}

/**
* Returns a Term, for the given Institution based on
* the current date (albeit cached for a week).
*
* @return object
*/
public function thisTerm(): object
{
Cache::forget('termDatesThisTerm_' . $this->institution->short_code);

return Cache::remember('termDatesThisTerm_' . $this->institution->short_code, now()->addWeek(), function () {
$currentTerm = $this->getCurrentTerm();
array_walk($currentTerm, function (&$item, $key) {
if ($key == 'startDate' || $key == 'finishDate') {
$item = Carbon::parse($item);
}
});

return $currentTerm;
});
}

/**
* @return Collection
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function index(): Collection
{
if ($this->terms !== null) {
return $this->terms;
}
$response = $this->guzzle->request('GET', $this->endpoint, ['headers' => $this->getHeaders()]);
$terms = collect(json_decode($response->getBody()->getContents())->terms);
$terms->each(function ($item) {
$item->school = $this->institution->only(['school_id', 'short_code', 'long_name']);
});

$this->terms = $terms->mapInto(SchoolTerm::class);

return $this->terms;
}

/**
* @return object
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getCurrentTerm(): SchoolTerm
{
$terms = $this->index();

$findTerm = $terms->filter(function ($item) {
$startDate = $item->startDate;
$finishDate = $item->finishDate;
if (Carbon::now()->between(Carbon::parse($startDate), Carbon::parse($finishDate))) {
return $item;
}
});

if ($findTerm->count() === 1) {
return $findTerm->first();
} else {
return $this->getNearestTerm();
}
}

/**
* @param int $year
*
* @return Collection
*/
public function getYear(int $year): Collection
{
$terms = $this->index();

return $terms->filter(function ($item) use ($year) {
if ($item->schoolYear === $year) {
return $item;
}
});
}

/**
* @return object
* @throws \App\Exceptions\FailedToFindNearestTerm
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function getNearestTerm(): SchoolTerm
{
$terms = $this->index();

$nearestTerm = $terms->filter(function ($item) {
if (Carbon::parse($item->finishDate) > now()->subMonths(2) && Carbon::parse($item->startDate) < now()->addMonths(2)) {
return $item;
}
});

if ($nearestTerm->count() === 1) {
return $nearestTerm->first();
} elseif ($nearestTerm->count() === 2) {
/**
* If there are exactly two nearest terms at this point, then we assume it's a holiday.
* We now want to find the nearest term relevant to today's date.
*/
$term['first'] = $nearestTerm->first();
$term['last'] = $nearestTerm->last();

$daysSinceEndOfTerm = now()->diffInMilliseconds($term['first']->finishDate);
$daysUntilStartOfTerm = now()->diffInMilliseconds($term['last']->startDate);

$times = collect([
'first' => $daysSinceEndOfTerm,
'last' => $daysUntilStartOfTerm,
])->sort()->keys();

// The Nearest Term...
return $term[$times[0]];
} else {
throw new FailedtoFindNearestTerm('Could not find nearest term', 500);
}
}
}
53 changes: 53 additions & 0 deletions src/Controllers/TimetableStructureController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace spkm\isams\Controllers;

use Illuminate\Support\Collection;
use spkm\isams\Endpoint;
use spkm\isams\Wrappers\TimetableDay;
use spkm\isams\Wrappers\TimetableDayPart;

class TimetableStructureController extends Endpoint
{
/**
* Set the URL the request is made to.
*
* @return void
* @throws \Exception
*/
protected function setEndpoint()
{
$this->endpoint = $this->getDomain() . '/api/timetables/structure';
}

/**
* Get the timetable structure.
*
* @return \Illuminate\Support\Collection
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function index(): Collection
{
$this->endpoint = $this->endpoint . '/';

$response = $this->guzzle->request('GET', $this->endpoint, [
'headers' => $this->getHeaders(),
]);

$decoded = json_decode($response->getBody()->getContents());

$week = collect($decoded)['timetableWeeks'][0];

$days = $week->timetableDays;
$result = [];
foreach ($days as $day) {
$result[$day->name] = collect($day->periods)->map(function ($item) {
return new TimetableDayPart($item);
});
}

return collect($result)->map(function ($item) {
return new TimetableDay($item);
});
}
}
11 changes: 11 additions & 0 deletions src/Exceptions/FailedtoFindNearestTerm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace spkm\isams\Exceptions;

class FailedtoFindNearestTerm extends \Exception
{
public function __construct($message = '')
{
$this->message = $message;
}
}
24 changes: 24 additions & 0 deletions src/Wrappers/Lesson.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace spkm\isams\Wrappers;

use spkm\isams\Wrapper;

/**
* Wrapper for the array returned by the iSAMS REST API endpoint.
*/
class Lesson extends Wrapper
{
/**
* Handle the data.
*
* @return void
*/
protected function handle()
{
unset($this->employeeId);
$this->teacher = $this->employeeTitle . ' ' . $this->employeeSurname;
unset($this->employeeTitle);
unset($this->employeeSurname);
}
}
Loading

0 comments on commit 97b137f

Please sign in to comment.