<?php namespace OCA\Memento\Controller; require_once __DIR__ . '/findMementos.php'; use DateTime; use OCP\IRequest; use OCP\IServerContainer; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\DataDisplayResponse; use findMementos; class TimeGateController extends Controller { private $userFolder; public function __construct( $AppName, IRequest $request, $UserId, IServerContainer $serverContainer ) { parent::__construct($AppName, $request); $this->userFolder = $serverContainer->getUserFolder($UserId); } /** * @NoAdminRequired * @NoCSRFRequired */ public function timeGate($url) { $matchingMementos = findMementos($this->userFolder, $url); // Choose one of the matched mementos, if any. if (count($matchingMementos) === 0) { // No matches. :( $message = "<h1>No snapshots found for requested URL. :(</h1>"; return new DataDisplayResponse($message, 404); } else if (count($matchingMementos) === 1) { // One match; no need to choose. $chosenMemento = $matchingMementos[0]; } else { // Multiple matches: choose based on requested date. $acceptDatetimeHeader = $this->request->getHeader('Accept-Datetime'); if ($acceptDatetimeHeader) { try { $requestedDatetime = DateTime::createFromFormat(DateTime::RFC1123, $acceptDatetimeHeader) ->getTimestamp(); } catch (Exception $e) { return new DataDisplayResponse("Invalid Accept-Datetime header.", 400); } } else { // Not sending the header means requesting the most recent version. $requestedDatetime = time(); } // Pick the one closest to the requested date (either before or after it). $chosenMemento = minBy($matchingMementos, function ($matchingMemento) use ($requestedDatetime) { return abs($matchingMemento['datetime'] - $requestedDatetime); } ); } // Send a 302 Found redirect pointing to the chosen memento. $response = new RedirectResponse($chosenMemento['mementoUrl']); $response->setStatus(302); $response->addHeader('Vary', 'accept-datetime'); $response->addHeader('Link', "<{$chosenMemento['originalUrl']}>; rel=\"original\""); return $response; } } function minBy($array, $iteratee) { // is there any simpler way for this in php? $values = array_map($iteratee, $array); $argmin = array_search(min($values), $values); return $array[$argmin]; }