1<?php
2
3namespace GuzzleHttp\Cookie;
4
5use GuzzleHttp\Utils;
6
7/**
8 * Persists non-session cookies using a JSON formatted file
9 */
10class FileCookieJar extends CookieJar
11{
12    /**
13     * @var string filename
14     */
15    private $filename;
16
17    /**
18     * @var bool Control whether to persist session cookies or not.
19     */
20    private $storeSessionCookies;
21
22    /**
23     * Create a new FileCookieJar object
24     *
25     * @param string $cookieFile          File to store the cookie data
26     * @param bool   $storeSessionCookies Set to true to store session cookies
27     *                                    in the cookie jar.
28     *
29     * @throws \RuntimeException if the file cannot be found or created
30     */
31    public function __construct(string $cookieFile, bool $storeSessionCookies = false)
32    {
33        parent::__construct();
34        $this->filename = $cookieFile;
35        $this->storeSessionCookies = $storeSessionCookies;
36
37        if (\file_exists($cookieFile)) {
38            $this->load($cookieFile);
39        }
40    }
41
42    /**
43     * Saves the file when shutting down
44     */
45    public function __destruct()
46    {
47        $this->save($this->filename);
48    }
49
50    /**
51     * Saves the cookies to a file.
52     *
53     * @param string $filename File to save
54     *
55     * @throws \RuntimeException if the file cannot be found or created
56     */
57    public function save(string $filename): void
58    {
59        $json = [];
60        /** @var SetCookie $cookie */
61        foreach ($this as $cookie) {
62            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
63                $json[] = $cookie->toArray();
64            }
65        }
66
67        $jsonStr = Utils::jsonEncode($json);
68        if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
69            throw new \RuntimeException("Unable to save file {$filename}");
70        }
71    }
72
73    /**
74     * Load cookies from a JSON formatted file.
75     *
76     * Old cookies are kept unless overwritten by newly loaded ones.
77     *
78     * @param string $filename Cookie file to load.
79     *
80     * @throws \RuntimeException if the file cannot be loaded.
81     */
82    public function load(string $filename): void
83    {
84        $json = \file_get_contents($filename);
85        if (false === $json) {
86            throw new \RuntimeException("Unable to load file {$filename}");
87        }
88        if ($json === '') {
89            return;
90        }
91
92        $data = Utils::jsonDecode($json, true);
93        if (\is_array($data)) {
94            foreach ($data as $cookie) {
95                $this->setCookie(new SetCookie($cookie));
96            }
97        } elseif (\is_scalar($data) && !empty($data)) {
98            throw new \RuntimeException("Invalid cookie file: {$filename}");
99        }
100    }
101}
102