1<?php
2
3namespace Elastica;
4
5use Elastica\Exception\ClientException;
6use Elastica\Exception\ConnectionException;
7use Elastica\Exception\NotFoundException;
8use Elastica\Exception\ResponseException;
9use Elasticsearch\Endpoints\Snapshot\Restore;
10
11/**
12 * Class Snapshot.
13 *
14 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html
15 */
16class Snapshot
17{
18    /**
19     * @var Client
20     */
21    protected $_client;
22
23    public function __construct(Client $client)
24    {
25        $this->_client = $client;
26    }
27
28    /**
29     * Register a snapshot repository.
30     *
31     * @param string $name     the name of the repository
32     * @param string $type     the repository type ("fs" for file system)
33     * @param array  $settings Additional repository settings. If type "fs" is used, the "location" setting must be provided.
34     *
35     * @throws ClientException
36     * @throws ConnectionException
37     * @throws ResponseException
38     *
39     * @return Response
40     */
41    public function registerRepository($name, $type, $settings = [])
42    {
43        $data = [
44            'type' => $type,
45            'settings' => $settings,
46        ];
47
48        return $this->request($name, Request::PUT, $data);
49    }
50
51    /**
52     * Retrieve a repository record by name.
53     *
54     * @param string $name the name of the desired repository
55     *
56     * @throws ClientException
57     * @throws ConnectionException
58     * @throws NotFoundException
59     * @throws ResponseException
60     *
61     * @return array
62     */
63    public function getRepository($name)
64    {
65        try {
66            $response = $this->request($name);
67        } catch (ResponseException $e) {
68            if (404 === $e->getResponse()->getStatus()) {
69                throw new NotFoundException("Repository '".$name."' does not exist.");
70            }
71            throw $e;
72        }
73        $data = $response->getData();
74
75        return $data[$name];
76    }
77
78    /**
79     * Retrieve all repository records.
80     *
81     * @throws ClientException
82     * @throws ConnectionException
83     * @throws ResponseException
84     *
85     * @return array
86     */
87    public function getAllRepositories()
88    {
89        return $this->request('_all')->getData();
90    }
91
92    /**
93     * Create a new snapshot.
94     *
95     * @param string $repository        the name of the repository in which this snapshot should be stored
96     * @param string $name              the name of this snapshot
97     * @param array  $options           optional settings for this snapshot
98     * @param bool   $waitForCompletion if true, the request will not return until the snapshot operation is complete
99     *
100     * @throws ClientException
101     * @throws ConnectionException
102     * @throws ResponseException
103     *
104     * @return Response
105     */
106    public function createSnapshot($repository, $name, $options = [], $waitForCompletion = false)
107    {
108        return $this->request($repository.'/'.$name, Request::PUT, $options, ['wait_for_completion' => $waitForCompletion]);
109    }
110
111    /**
112     * Retrieve data regarding a specific snapshot.
113     *
114     * @param string $repository the name of the repository from which to retrieve the snapshot
115     * @param string $name       the name of the desired snapshot
116     *
117     * @throws ClientException
118     * @throws ConnectionException
119     * @throws NotFoundException
120     * @throws ResponseException
121     *
122     * @return array
123     */
124    public function getSnapshot($repository, $name)
125    {
126        try {
127            $response = $this->request($repository.'/'.$name);
128        } catch (ResponseException $e) {
129            if (404 === $e->getResponse()->getStatus()) {
130                throw new NotFoundException("Snapshot '".$name."' does not exist in repository '".$repository."'.");
131            }
132            throw $e;
133        }
134        $data = $response->getData();
135
136        return $data['snapshots'][0];
137    }
138
139    /**
140     * Retrieve data regarding all snapshots in the given repository.
141     *
142     * @param string $repository the repository name
143     *
144     * @throws ClientException
145     * @throws ConnectionException
146     * @throws ResponseException
147     *
148     * @return array
149     */
150    public function getAllSnapshots($repository)
151    {
152        return $this->request($repository.'/_all')->getData();
153    }
154
155    /**
156     * Delete a snapshot.
157     *
158     * @param string $repository the repository in which the snapshot resides
159     * @param string $name       the name of the snapshot to be deleted
160     *
161     * @throws ClientException
162     * @throws ConnectionException
163     * @throws ResponseException
164     *
165     * @return Response
166     */
167    public function deleteSnapshot($repository, $name)
168    {
169        return $this->request($repository.'/'.$name, Request::DELETE);
170    }
171
172    /**
173     * Restore a snapshot.
174     *
175     * @param string $repository        the name of the repository
176     * @param string $name              the name of the snapshot
177     * @param array  $options           options for the restore operation
178     * @param bool   $waitForCompletion if true, the request will not return until the restore operation is complete
179     *
180     * @throws ClientException
181     * @throws ConnectionException
182     * @throws ResponseException
183     *
184     * @return Response
185     */
186    public function restoreSnapshot($repository, $name, $options = [], $waitForCompletion = false)
187    {
188        $endpoint = (new Restore())
189            ->setRepository($repository)
190            ->setSnapshot($name)
191            ->setBody($options)
192            ->setParams([
193                'wait_for_completion' => $waitForCompletion ? 'true' : 'false',
194            ])
195        ;
196
197        return $this->_client->requestEndpoint($endpoint);
198    }
199
200    /**
201     * Perform a snapshot request.
202     *
203     * @param string $path   the URL
204     * @param string $method the HTTP method
205     * @param array  $data   request body data
206     * @param array  $query  query string parameters
207     *
208     * @throws ClientException
209     * @throws ConnectionException
210     * @throws ResponseException
211     *
212     * @return Response
213     */
214    public function request($path, $method = Request::GET, $data = [], array $query = [])
215    {
216        return $this->_client->request('_snapshot/'.$path, $method, $data, $query);
217    }
218}
219