1<?php
2/**
3 * Copyright 2017 Facebook, Inc.
4 *
5 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6 * use, copy, modify, and distribute this software in source code or binary
7 * form for use in connection with the web services and APIs provided by
8 * Facebook.
9 *
10 * As with any software that integrates with the Facebook platform, your use
11 * of this software is subject to the Facebook Developer Principles and
12 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13 * shall be included in all copies or substantial portions of the software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24namespace Facebook\FileUpload;
25
26use Facebook\Exceptions\FacebookSDKException;
27
28/**
29 * Class FacebookFile
30 *
31 * @package Facebook
32 */
33class FacebookFile
34{
35    /**
36     * @var string The path to the file on the system.
37     */
38    protected $path;
39
40    /**
41     * @var int The maximum bytes to read. Defaults to -1 (read all the remaining buffer).
42     */
43    private $maxLength;
44
45    /**
46     * @var int Seek to the specified offset before reading. If this number is negative, no seeking will occur and reading will start from the current position.
47     */
48    private $offset;
49
50    /**
51     * @var resource The stream pointing to the file.
52     */
53    protected $stream;
54
55    /**
56     * Creates a new FacebookFile entity.
57     *
58     * @param string $filePath
59     * @param int $maxLength
60     * @param int $offset
61     *
62     * @throws FacebookSDKException
63     */
64    public function __construct($filePath, $maxLength = -1, $offset = -1)
65    {
66        $this->path = $filePath;
67        $this->maxLength = $maxLength;
68        $this->offset = $offset;
69        $this->open();
70    }
71
72    /**
73     * Closes the stream when destructed.
74     */
75    public function __destruct()
76    {
77        $this->close();
78    }
79
80    /**
81     * Opens a stream for the file.
82     *
83     * @throws FacebookSDKException
84     */
85    public function open()
86    {
87        if (!$this->isRemoteFile($this->path) && !is_readable($this->path)) {
88            throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to read resource: ' . $this->path . '.');
89        }
90
91        $this->stream = fopen($this->path, 'r');
92
93        if (!$this->stream) {
94            throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to open resource: ' . $this->path . '.');
95        }
96    }
97
98    /**
99     * Stops the file stream.
100     */
101    public function close()
102    {
103        if (is_resource($this->stream)) {
104            fclose($this->stream);
105        }
106    }
107
108    /**
109     * Return the contents of the file.
110     *
111     * @return string
112     */
113    public function getContents()
114    {
115        return stream_get_contents($this->stream, $this->maxLength, $this->offset);
116    }
117
118    /**
119     * Return the name of the file.
120     *
121     * @return string
122     */
123    public function getFileName()
124    {
125        return basename($this->path);
126    }
127
128    /**
129     * Return the path of the file.
130     *
131     * @return string
132     */
133    public function getFilePath()
134    {
135        return $this->path;
136    }
137
138    /**
139     * Return the size of the file.
140     *
141     * @return int
142     */
143    public function getSize()
144    {
145        return filesize($this->path);
146    }
147
148    /**
149     * Return the mimetype of the file.
150     *
151     * @return string
152     */
153    public function getMimetype()
154    {
155        return Mimetypes::getInstance()->fromFilename($this->path) ?: 'text/plain';
156    }
157
158    /**
159     * Returns true if the path to the file is remote.
160     *
161     * @param string $pathToFile
162     *
163     * @return boolean
164     */
165    protected function isRemoteFile($pathToFile)
166    {
167        return preg_match('/^(https?|ftp):\/\/.*/', $pathToFile) === 1;
168    }
169}
170