Skip to content

Commit

Permalink
Merge branch 'master' into issue862-mappings-documantation
Browse files Browse the repository at this point in the history
  • Loading branch information
joelit authored May 14, 2020
2 parents f2b8a57 + 80fad12 commit c0bde73
Show file tree
Hide file tree
Showing 21 changed files with 2,711 additions and 276 deletions.
111 changes: 105 additions & 6 deletions controller/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
*/
class Controller
{
/**
* How long to store retrieved disk configuration for HTTP 304 header
* from git information.
*/
const GIT_MODIFIED_CONFIG_TTL = 600; // 10 minutes

/**
* The controller has to know the model to access the data stored there.
* @var Model $model contains the Model object.
Expand Down Expand Up @@ -177,6 +183,98 @@ protected function returnError($code, $status, $message)
echo "$code $status : $message";
}

protected function notModified(Modifiable $modifiable = null)
{
$notModified = false;
if ($modifiable !== null && $modifiable->isUseModifiedDate()) {
$modifiedDate = $this->getModifiedDate($modifiable);
$notModified = $this->sendNotModifiedHeader($modifiedDate);
}
return $notModified;
}

/**
* Return the modified date.
*
* @param Modifiable $modifiable
* @return DateTime|null
*/
protected function getModifiedDate(Modifiable $modifiable = null)
{
$modified = null;
$modifiedDate = $modifiable !== null ? $modifiable->getModifiedDate() : null;
$gitModifiedDate = $this->getGitModifiedDate();
$configModifiedDate = $this->getConfigModifiedDate();

// max with an empty list raises an error and returns bool
if ($modifiedDate || $gitModifiedDate || $configModifiedDate) {
$modified = max($modifiedDate, $gitModifiedDate, $configModifiedDate);
}
return $modified;
}

/**
* Return the datetime of the latest commit, or null if git is not available or if the command failed
* to execute.
*
* @see https://stackoverflow.com/a/33986403
* @return DateTime|null
*/
protected function getGitModifiedDate()
{
$commitDate = null;
$cache = $this->model->getConfig()->getCache();
$cacheKey = "git:modified_date";
$gitCommand = 'git log -1 --date=iso --pretty=format:%cd';
if ($cache->isAvailable()) {
$commitDate = $cache->fetch($cacheKey);
if (!$commitDate) {
$commitDate = $this->executeGitModifiedDateCommand($gitCommand);
if ($commitDate) {
$cache->store($cacheKey, $commitDate, static::GIT_MODIFIED_CONFIG_TTL);
}
}
} else {
$commitDate = $this->executeGitModifiedDateCommand($gitCommand);
}
return $commitDate;
}

/**
* Execute the git command and return a parsed date time, or null if the command failed.
*
* @param string $gitCommand git command line that returns a formatted date time
* @return DateTime|null
*/
protected function executeGitModifiedDateCommand($gitCommand)
{
$commitDate = null;
$commandOutput = @exec($gitCommand);
if ($commandOutput) {
$commitDate = new \DateTime(trim($commandOutput));
$commitDate->setTimezone(new \DateTimeZone('UTC'));
}
return $commitDate;
}

/**
* Return the datetime of the modified time of the config file. This value is read in the GlobalConfig
* for every request, so we simply access that value and if not null, we will return a datetime. Otherwise,
* we return a null value.
*
* @see http://php.net/manual/en/function.filemtime.php
* @return DateTime|null
*/
protected function getConfigModifiedDate()
{
$dateTime = null;
$configModifiedTime = $this->model->getConfig()->getConfigModifiedTime();
if ($configModifiedTime !== null) {
$dateTime = (new DateTime())->setTimestamp($configModifiedTime);
}
return $dateTime;
}

/**
* If the $modifiedDate is a valid DateTime, and if the $_SERVER variable contains the right info, and
* if the $modifiedDate is not more recent than the latest value in $_SERVER, then this function sets the
Expand All @@ -187,16 +285,16 @@ protected function returnError($code, $status, $message)
*
* Otherwise, it returns false.
*
* @param DateTime $modifiedDate the last modified date to be compared against server's modified since information
* @param DateTime|null $modifiedDate the last modified date to be compared against server's modified since information
* @return bool whether it sent the HTTP 304 not modified headers or not (useful for sending the response without
* further actions)
*/
protected function sendNotModifiedHeader($modifiedDate): bool
{
if ($modifiedDate) {
$ifModifiedSince = $this->getIfModifiedSince();
$this->sendHeader("Last-Modified: " . $modifiedDate->format('Y-m-d H:i:s'));
if (!is_null($ifModifiedSince) && $ifModifiedSince >= $modifiedDate) {
$this->sendHeader("Last-Modified: " . $modifiedDate->format('D, d M Y H:i:s \G\M\T'));
if ($ifModifiedSince !== null && $ifModifiedSince >= $modifiedDate) {
$this->sendHeader("HTTP/1.0 304 Not Modified");
return true;
}
Expand All @@ -210,9 +308,10 @@ protected function sendNotModifiedHeader($modifiedDate): bool
protected function getIfModifiedSince()
{
$ifModifiedSince = null;
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
// example value set by a browser: "2019-04-13 08:28:23"
$ifModifiedSince = DateTime::createFromFormat("Y-m-d H:i:s", $_SERVER["HTTP_IF_MODIFIED_SINCE"]);
$ifModSinceHeader = filter_input(INPUT_SERVER, 'HTTP_IF_MODIFIED_SINCE', FILTER_SANITIZE_STRING);
if ($ifModSinceHeader) {
// example value set by a browser: "Mon, 11 May 2020 10:46:57 GMT"
$ifModifiedSince = new DateTime($ifModSinceHeader);
}
return $ifModifiedSince;
}
Expand Down
Loading

0 comments on commit c0bde73

Please sign in to comment.