1<?php 2/* 3 * Copyright 2016 Google Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18namespace Google\Auth\Cache; 19 20use DateTime; 21use DateTimeInterface; 22use DateTimeZone; 23use Psr\Cache\CacheItemInterface; 24use TypeError; 25 26/** 27 * A cache item. 28 */ 29final class Item implements CacheItemInterface 30{ 31 /** 32 * @var string 33 */ 34 private $key; 35 36 /** 37 * @var mixed 38 */ 39 private $value; 40 41 /** 42 * @var DateTimeInterface|null 43 */ 44 private $expiration; 45 46 /** 47 * @var bool 48 */ 49 private $isHit = false; 50 51 /** 52 * @param string $key 53 */ 54 public function __construct($key) 55 { 56 $this->key = $key; 57 } 58 59 /** 60 * {@inheritdoc} 61 */ 62 public function getKey() 63 { 64 return $this->key; 65 } 66 67 /** 68 * {@inheritdoc} 69 */ 70 public function get() 71 { 72 return $this->isHit() ? $this->value : null; 73 } 74 75 /** 76 * {@inheritdoc} 77 */ 78 public function isHit() 79 { 80 if (!$this->isHit) { 81 return false; 82 } 83 84 if ($this->expiration === null) { 85 return true; 86 } 87 88 return $this->currentTime()->getTimestamp() < $this->expiration->getTimestamp(); 89 } 90 91 /** 92 * {@inheritdoc} 93 */ 94 public function set($value) 95 { 96 $this->isHit = true; 97 $this->value = $value; 98 99 return $this; 100 } 101 102 /** 103 * {@inheritdoc} 104 */ 105 public function expiresAt($expiration) 106 { 107 if ($this->isValidExpiration($expiration)) { 108 $this->expiration = $expiration; 109 110 return $this; 111 } 112 113 $error = sprintf( 114 'Argument 1 passed to %s::expiresAt() must implement interface DateTimeInterface, %s given', 115 get_class($this), 116 gettype($expiration) 117 ); 118 119 throw new TypeError($error); 120 } 121 122 /** 123 * {@inheritdoc} 124 */ 125 public function expiresAfter($time) 126 { 127 if (is_int($time)) { 128 $this->expiration = $this->currentTime()->add(new \DateInterval("PT{$time}S")); 129 } elseif ($time instanceof \DateInterval) { 130 $this->expiration = $this->currentTime()->add($time); 131 } elseif ($time === null) { 132 $this->expiration = $time; 133 } else { 134 $message = 'Argument 1 passed to %s::expiresAfter() must be an ' . 135 'instance of DateInterval or of the type integer, %s given'; 136 $error = sprintf($message, get_class($this), gettype($time)); 137 138 throw new TypeError($error); 139 } 140 141 return $this; 142 } 143 144 /** 145 * Determines if an expiration is valid based on the rules defined by PSR6. 146 * 147 * @param mixed $expiration 148 * @return bool 149 */ 150 private function isValidExpiration($expiration) 151 { 152 if ($expiration === null) { 153 return true; 154 } 155 156 if ($expiration instanceof DateTimeInterface) { 157 return true; 158 } 159 160 return false; 161 } 162 163 /** 164 * @return DateTime 165 */ 166 protected function currentTime() 167 { 168 return new DateTime('now', new DateTimeZone('UTC')); 169 } 170} 171