Kohana_Upload_Source::factory()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php defined('SYSPATH') OR die('No direct script access.');
2
3
/**
4
 * This class handles getting data from different sources (url, upload, stream)
5
 * and can copy the content of the source to a specified local directory
6
 *
7
 * @package    Jam
8
 * @author     Ivan Kerin
9
 * @copyright  (c) 2011-2012 Despark Ltd.
10
 * @license    http://creativecommons.org/licenses/by-sa/3.0/legalcode
11
*/
12
abstract class Kohana_Upload_Source {
13
14
	const TYPE_URL = 'url';
15
	const TYPE_STREAM = 'stream';
16
	const TYPE_TEMP = 'temp';
17
	const TYPE_FILE = 'file';
18
	const TYPE_UPLOAD = 'upload';
19
20
	/**
21
	 * Determine if the source is a valid one
22
	 * @param  mixed $source
23
	 * @return boolean
24
	 */
25 10
	public static function valid($source)
26
	{
27 10
		return Upload_Source::guess_type($source) !== FALSE;
28
	}
29
30
	/**
31
	 * Store any native errors occurred during upload
32
	 */
33
	protected $_error;
34
35 13
	public function error($error = NULL)
36
	{
37 13
		if ($error !== NULL)
38
		{
39
			$this->_error = $error;
40
			return $this;
41
		}
42
43 13
		return $this->_error;
44
	}
45
46
	/**
47
	 * Guess the type of the source:
48
	 *
49
	 *  - Upload_Source::TYPE_URL
50
	 *  - Upload_Source::TYPE_STREAM
51
	 *  - Upload_Source::TYPE_TEMP
52
	 *  - Upload_Source::TYPE_FILE
53
	 *  - Upload_Source::TYPE_UPLOAD
54
	 *  - FALSE
55
	 *
56
	 * @param  mixed $source
57
	 * @return string|boolean
58
	 */
59 30
	public static function guess_type($source)
60
	{
61 30
		if (is_array($source))
62
		{
63 2
			return (Upload::valid($source) AND $source['error'] !== UPLOAD_ERR_NO_FILE) ? Upload_Source::TYPE_UPLOAD : FALSE;
64
		}
65 28
		elseif ($source == 'php://input')
66
		{
67 1
			return Upload_Source::TYPE_STREAM;
68
		}
69 27
		elseif (Valid::url($source))
70
		{
71 5
			return Upload_Source::TYPE_URL;
72
		}
73 23
		elseif (substr_count($source, DIRECTORY_SEPARATOR) === 1)
74
		{
75 7
			return Upload_Source::TYPE_TEMP;
76
		}
77 16
		elseif (is_file($source))
78
		{
79 15
			return Upload_Source::TYPE_FILE;
80
		}
81
		else
82
		{
83 1
			return FALSE;
84
		}
85
	}
86
87 21
	public static function factory($data)
88
	{
89 21
		return new Upload_Source($data);
90
	}
91
92
	protected $_filename;
93
	protected $_data = NULL;
94
	protected $_type = NULL;
95
	protected $_copied = FALSE;
96
97 21
	public function __construct($data)
98
	{
99 21
		$this->_data = $data;
100
101 21
		if (($type = Upload_Source::guess_type($data)))
102
		{
103 21
			$this->_type = $type;
104
		}
105 21
	}
106
107 21
	public function type()
108
	{
109 21
		return $this->_type;
110
	}
111
112 15
	public function data()
113
	{
114 15
		return $this->_data;
115
	}
116
117 13
	public function copied()
118
	{
119 13
		return $this->_copied;
120
	}
121
122 13
	public function filename($filename = NULL)
123
	{
124 13
		if ($filename !== NULL)
125
		{
126 13
			$this->_filename = $filename;
127 13
			return $this;
128
		}
129 13
		return $this->_filename;
130
	}
131
132
	/**
133
	 * move the uploaded file to a specified location, throw an exception on upload error (with appropriate error message)
134
	 * Return the filename
135
	 *
136
	 * @param  array $data
137
	 * @param  string $directory
138
	 * @return string
139
	 */
140 5
	public static function process_type_upload(array $data, $directory)
141
	{
142 5
		if ( ! Upload::not_empty($data))
143
		{
144
			$errors = array(
145 5
				UPLOAD_ERR_OK          => 'No errors.',
146 5
				UPLOAD_ERR_INI_SIZE    => 'must not be larger than '.ini_get('upload_max_filesize'),
147 5
				UPLOAD_ERR_FORM_SIZE   => 'must not be larger than specified',
148 5
				UPLOAD_ERR_PARTIAL     => 'was only partially uploaded.',
149 5
				UPLOAD_ERR_NO_FILE     => 'no file was uploaded.',
150 5
				UPLOAD_ERR_NO_TMP_DIR  => 'missing a temporary folder.',
151 5
				UPLOAD_ERR_CANT_WRITE  => 'failed to write file to disk.',
152 5
				UPLOAD_ERR_EXTENSION   => 'file upload stopped by extension.',
153
			);
154
155 5
			throw new Jam_Exception_Upload("File not uploaded properly. Error: :error", array(':error' => Arr::get($errors, Arr::get($data, 'error'), '-')));
156
		}
157
158
		if ( ! move_uploaded_file($data['tmp_name'], Upload_Util::combine($directory, $data['name'])))
159
			throw new Jam_Exception_Upload('There was an error moving the file to :directory', array(':directory' => $directory));
160
161
		return $data['name'];
162
	}
163
164
	/**
165
	 * Check if the file can be operated with.
166
	 *
167
	 * @param  string $file
168
	 */
169 13
	public static function valid_file($file)
170
	{
171 13
		return (strpos($file, DOCROOT) === 0 OR Kohana::$environment === Kohana::TESTING);
172
	}
173
174
	/**
175
	 * Copy the source data to a directory
176
	 *
177
	 * @param  string $directory
178
	 * @return Upload_Source $this
179
	 */
180 13
	public function copy_to($directory)
181
	{
182 13
		switch ($this->type())
183
		{
184 13
			case Upload_Source::TYPE_URL:
185
				$filename = Upload_Util::download($this->data(), $directory, $this->filename());
186
				$this->filename($filename);
187
			break;
188
189 13
			case Upload_Source::TYPE_UPLOAD:
190
				try
191
				{
192
					$filename = Upload_Source::process_type_upload($this->data(), $directory);
193
					$this->filename($filename);
194
				}
195
				catch (Jam_Exception_Upload $e)
196
				{
197
					$this->error($e->getMessage());
198
				}
199
			break;
200
201 13
			case Upload_Source::TYPE_STREAM:
202
				if ( ! $this->filename())
203
				{
204
					$this->filename(uniqid());
205
				}
206
				Upload_Util::stream_copy_to_file($this->data(), Upload_Util::combine($directory, $this->filename()));
207
			break;
208
209 13
			case Upload_Source::TYPE_FILE:
210 13
				if ( ! Upload_Source::valid_file($this->data()))
211
					throw new Kohana_Exception("File must be in the document root, or must be testing environment");
212
213 13
				if ( ! $this->filename())
214
				{
215 13
					$this->filename(basename($this->data()));
216
				}
217
218 13
				copy($this->data(), Upload_Util::combine($directory, $this->filename()));
219 13
			break;
220
221
			case Upload_Source::TYPE_TEMP:
222
				if ( ! Upload_Temp::valid($this->data()))
223
					throw new Kohana_Exception("This file does not exist");
224
225
				$this->filename(basename($this->data()));
226
			break;
227
		}
228
229 13
		$this->_copied = TRUE;
230
231 13
		return $this;
232
	}
233
}
234