run:R W Run
4.26 KB
2026-03-11 16:18:52
R W Run
error_log
📄Jar.php
1<?php
2/**
3 * Cookie holder object
4 *
5 * @package Requests\Cookies
6 */
7
8namespace WpOrg\Requests\Cookie;
9
10use ArrayAccess;
11use ArrayIterator;
12use IteratorAggregate;
13use ReturnTypeWillChange;
14use WpOrg\Requests\Cookie;
15use WpOrg\Requests\Exception;
16use WpOrg\Requests\Exception\InvalidArgument;
17use WpOrg\Requests\HookManager;
18use WpOrg\Requests\Iri;
19use WpOrg\Requests\Response;
20
21/**
22 * Cookie holder object
23 *
24 * @package Requests\Cookies
25 */
26class Jar implements ArrayAccess, IteratorAggregate {
27 /**
28 * Actual item data
29 *
30 * @var array
31 */
32 protected $cookies = [];
33
34 /**
35 * Create a new jar
36 *
37 * @param array $cookies Existing cookie values
38 *
39 * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array.
40 */
41 public function __construct($cookies = []) {
42 if (is_array($cookies) === false) {
43 throw InvalidArgument::create(1, '$cookies', 'array', gettype($cookies));
44 }
45
46 $this->cookies = $cookies;
47 }
48
49 /**
50 * Normalise cookie data into a \WpOrg\Requests\Cookie
51 *
52 * @param string|\WpOrg\Requests\Cookie $cookie Cookie header value, possibly pre-parsed (object).
53 * @param string $key Optional. The name for this cookie.
54 * @return \WpOrg\Requests\Cookie
55 */
56 public function normalize_cookie($cookie, $key = '') {
57 if ($cookie instanceof Cookie) {
58 return $cookie;
59 }
60
61 return Cookie::parse($cookie, $key);
62 }
63
64 /**
65 * Check if the given item exists
66 *
67 * @param string $offset Item key
68 * @return boolean Does the item exist?
69 */
70 #[ReturnTypeWillChange]
71 public function offsetExists($offset) {
72 return isset($this->cookies[$offset]);
73 }
74
75 /**
76 * Get the value for the item
77 *
78 * @param string $offset Item key
79 * @return string|null Item value (null if offsetExists is false)
80 */
81 #[ReturnTypeWillChange]
82 public function offsetGet($offset) {
83 if (!isset($this->cookies[$offset])) {
84 return null;
85 }
86
87 return $this->cookies[$offset];
88 }
89
90 /**
91 * Set the given item
92 *
93 * @param string $offset Item name
94 * @param string $value Item value
95 *
96 * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`)
97 */
98 #[ReturnTypeWillChange]
99 public function offsetSet($offset, $value) {
100 if ($offset === null) {
101 throw new Exception('Object is a dictionary, not a list', 'invalidset');
102 }
103
104 $this->cookies[$offset] = $value;
105 }
106
107 /**
108 * Unset the given header
109 *
110 * @param string $offset The key for the item to unset.
111 */
112 #[ReturnTypeWillChange]
113 public function offsetUnset($offset) {
114 unset($this->cookies[$offset]);
115 }
116
117 /**
118 * Get an iterator for the data
119 *
120 * @return \ArrayIterator
121 */
122 #[ReturnTypeWillChange]
123 public function getIterator() {
124 return new ArrayIterator($this->cookies);
125 }
126
127 /**
128 * Register the cookie handler with the request's hooking system
129 *
130 * @param \WpOrg\Requests\HookManager $hooks Hooking system
131 */
132 public function register(HookManager $hooks) {
133 $hooks->register('requests.before_request', [$this, 'before_request']);
134 $hooks->register('requests.before_redirect_check', [$this, 'before_redirect_check']);
135 }
136
137 /**
138 * Add Cookie header to a request if we have any
139 *
140 * As per RFC 6265, cookies are separated by '; '
141 *
142 * @param string $url
143 * @param array $headers
144 * @param array $data
145 * @param string $type
146 * @param array $options
147 */
148 public function before_request($url, &$headers, &$data, &$type, &$options) {
149 if (!$url instanceof Iri) {
150 $url = new Iri($url);
151 }
152
153 if (!empty($this->cookies)) {
154 $cookies = [];
155 foreach ($this->cookies as $key => $cookie) {
156 $cookie = $this->normalize_cookie($cookie, $key);
157
158 // Skip expired cookies
159 if ($cookie->is_expired()) {
160 continue;
161 }
162
163 if ($cookie->domain_matches($url->host)) {
164 $cookies[] = $cookie->format_for_header();
165 }
166 }
167
168 $headers['Cookie'] = implode('; ', $cookies);
169 }
170 }
171
172 /**
173 * Parse all cookies from a response and attach them to the response
174 *
175 * @param \WpOrg\Requests\Response $response Response as received.
176 */
177 public function before_redirect_check(Response $response) {
178 $url = $response->url;
179 if (!$url instanceof Iri) {
180 $url = new Iri($url);
181 }
182
183 $cookies = Cookie::parse_from_headers($response->headers, $url);
184 $this->cookies = array_merge($this->cookies, $cookies);
185 $response->cookies = $this;
186 }
187}
188