|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- <?php
- namespace OCA\Memento\Controller;
-
- require_once __DIR__ . '/datetimeConversion.php';
- require_once __DIR__ . '/getUrlParameter.php';
-
- use \Exception;
- use OCP\IRequest;
- use OCP\IServerContainer;
- use OCP\AppFramework\Controller;
- use OCP\AppFramework\Http\RedirectResponse;
- use OCP\AppFramework\Http\DataDisplayResponse;
-
- class TimeGateController extends Controller {
- use MementoFinder;
-
- private $loggedInUserId;
- private $serverContainer;
-
- public function __construct(
- $AppName,
- IRequest $request,
- $UserId,
- IServerContainer $serverContainer
- ) {
- parent::__construct($AppName, $request);
- $this->loggedInUserId = $UserId;
- $this->serverContainer = $serverContainer;
- }
-
- /**
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function singleUserTimeGate($userId, $url) {
- // XXX workaround, as nextcloud corrupts the $url parameter.
- $url = getUrlParameter("u/$userId/timegate");
-
- $matchingMementos = $this->findSingleUserMementosForUrl($userId, $url);
-
- return $this->makeResponse($url, $matchingMementos);
- }
-
- /**
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function allUsersTimeGate($url) {
- $url = getUrlParameter('timegate');
-
- $matchingMementos = $this->findAllUsersMementosForUrl($url);
-
- return $this->makeResponse($url, $matchingMementos);
- }
-
- private function makeResponse($url, $matchingMementos) {
- // 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 = datetimeStringToTimestamp($acceptDatetimeHeader);
- } 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);
- // Both the requested datetime and the authenticated user influence the response.
- $response->addHeader('Vary', 'accept-datetime, cookie');
-
- // Add a link to the original(s) and to the timemap.
- $originalLinks = implode(", ", array_map(
- function ($originalUrl) { return "<$originalUrl>;rel=\"original\""; },
- $chosenMemento['originalUrls']
- ));
- // XXX hardcoding the route URL.
- $timeMapUrl = $this->serverContainer->getURLGenerator()
- ->getAbsoluteUrl("/apps/memento/timemap/$url");
- $firstDatetime = datetimeTimestampToString($matchingMementos[0]['datetime']);
- $lastMemento = $matchingMementos[count($matchingMementos)-1];
- $lastDatetime = datetimeTimestampToString($lastMemento['datetime']);
- $timeMapLink = "<$timeMapUrl>"
- . ";rel=\"timemap\""
- . ";type=\"application/link-format\""
- . ";from=\"$firstDatetime\";until=\"$lastDatetime\"";
- $response->addHeader('Link', "$originalLinks, $timeMapLink");
-
- return $response;
- }
- }
-
- function minBy($array, $iteratee) {
- $values = array_map($iteratee, $array);
- $argmin = array_search(min($values), $values);
- return $array[$argmin];
- }
|