/library/Axis/File/Uploader.php

https://github.com/faktoral/axiscommerce · PHP · 242 lines · 125 code · 26 blank · 91 comment · 13 complexity · 1c339eabe315b6d9821970c3e58e9cd6 MD5 · raw file

  1. <?php
  2. /**
  3. * Axis
  4. *
  5. * This file is part of Axis.
  6. *
  7. * Axis is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * Axis is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with Axis. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. * @category Axis
  21. * @package Axis_File
  22. * @copyright Copyright 2008-2012 Axis
  23. * @license GNU Public License V3.0
  24. */
  25. /**
  26. *
  27. * @category Axis
  28. * @package Axis_File
  29. * @author Axis Core Team <core@axiscommerce.com>
  30. */
  31. //@todo use Zend_File_Transfer
  32. class Axis_File_Uploader
  33. {
  34. /**
  35. * Copy of $_FILES[$fileName]
  36. *
  37. * @var array
  38. */
  39. protected $_file = array();
  40. /**
  41. * @var bool
  42. */
  43. protected $_useDispersion = false;
  44. /**
  45. * @var array
  46. */
  47. protected $_allowedExtensions = null;
  48. /**
  49. * Php error codes
  50. *
  51. * @var array
  52. */
  53. protected $_errorCode = array(
  54. 0 => "There is no error, the file uploaded with success",
  55. 1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
  56. 2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
  57. 3 => "The uploaded file was only partially uploaded",
  58. 4 => "No file was uploaded",
  59. 6 => "Missing a temporary folder"
  60. );
  61. /**
  62. * @param string $fileName
  63. * @throws Axis_Exception
  64. */
  65. public function __construct($fileName)
  66. {
  67. if (!isset($_FILES[$fileName])) {
  68. throw new Axis_Exception(
  69. sprintf("File was not uploaded correctly. %s array doesn't have '%s' file", '$_FILES', $fileName)
  70. );
  71. }
  72. $this->_file = $_FILES[$fileName];
  73. }
  74. /**
  75. * @param string $desinationFolder
  76. * @param string $fileName
  77. * @return array|false
  78. * @throws Axis_Exception
  79. */
  80. public function save($destination, $fileName = null)
  81. {
  82. $this->_validateFile();
  83. $destination = rtrim($destination, '/\\');
  84. if (null === $fileName) {
  85. $fileName = $this->_file['name'];
  86. }
  87. $fileName = $this->_getCorrectFileName($fileName);
  88. $dispersion = $this->_getDispersionPath($fileName);
  89. if (!is_dir($destination . $dispersion)
  90. && !@mkdir($destination . $dispersion, 0777, true)) {
  91. throw new Axis_Exception("Unable to create directory '{$destination}'");
  92. }
  93. $fileName = $this->_getNewFileName($destination . $dispersion . $fileName);
  94. $fileName = $dispersion . $fileName;
  95. $result = @move_uploaded_file(
  96. $this->_file['tmp_name'],
  97. $destination . $fileName
  98. );
  99. if (!$result) {
  100. throw new Axis_Exception($this->_errorCode[$this->_file['error']]);
  101. }
  102. chmod($destination . $fileName, 0777);
  103. return array(
  104. 'path' => $destination,
  105. 'file' => $fileName
  106. );
  107. }
  108. /**
  109. * Set allowed extensions for uploader instance
  110. *
  111. * @param array $extensions
  112. * @return Axis_File_Uploader Provides fluent interface
  113. */
  114. public function setAllowedExtensions($extensions)
  115. {
  116. foreach ($extensions as $extension) {
  117. $this->_allowedExtensions[strtolower($extension)] = strtolower($extension);
  118. }
  119. return $this;
  120. }
  121. /**
  122. * Validate file extension
  123. *
  124. * @param string $extension
  125. * @return bool
  126. */
  127. public function isAllowedExtension($extension)
  128. {
  129. if (null === $this->_allowedExtensions) {
  130. return true;
  131. }
  132. if (in_array(strtolower($extension), $this->_allowedExtensions)) {
  133. return true;
  134. }
  135. return false;
  136. }
  137. /**
  138. * @param bool $flag
  139. * @return Axis_File_Uploader Provides fluent interface
  140. */
  141. public function setUseDispersion($flag)
  142. {
  143. $this->_useDispersion = (bool) $flag;
  144. return $this;
  145. }
  146. /**
  147. * Validate file before save
  148. *
  149. * @return void
  150. * @throws Axis_Exception
  151. */
  152. protected function _validateFile()
  153. {
  154. $pathinfo = pathinfo($this->_file['name']);
  155. if (!isset($pathinfo['extension'])) {
  156. $pathinfo['extension'] = '';
  157. }
  158. if (!$this->isAllowedExtension($pathinfo['extension'])) {
  159. throw new Axis_Exception("Disallowed file type.");
  160. }
  161. }
  162. /**
  163. * Retrieve unique file name within destination folder
  164. * Adds number to the end of fileName if same fileName found
  165. *
  166. * @param string $filePath
  167. * @return string
  168. */
  169. protected function _getNewFileName($filePath)
  170. {
  171. $i = 1;
  172. $fileInfo = pathinfo($filePath);
  173. while (file_exists($filePath)) {
  174. $filePath = $fileInfo['dirname']
  175. . DIRECTORY_SEPARATOR
  176. . $fileInfo['filename']
  177. . '-'
  178. . $i++
  179. . '.'
  180. . $fileInfo['extension'];
  181. }
  182. return basename($filePath);
  183. }
  184. /**
  185. * Removes invalid symbols from the fileName
  186. *
  187. * @param string $fileName
  188. * @return string
  189. */
  190. protected function _getCorrectFileName($fileName)
  191. {
  192. return preg_replace('/[^a-zA-Z0-9_\.]/', '_', $fileName);
  193. }
  194. /**
  195. * Retrieve additional folders to move file to it
  196. *
  197. * @param string $fileName
  198. * @return string
  199. */
  200. protected function _getDispersionPath($fileName)
  201. {
  202. $dispersionPath = '/';
  203. if (!$this->_useDispersion) {
  204. return $dispersionPath;
  205. }
  206. for ($i = 0; $i < 2; $i++) {
  207. if (!preg_match('/[a-zA-Z0-9_]{1}/', $fileName[$i])) {
  208. break;
  209. }
  210. $dispersionPath .= strtolower($fileName[$i]) . '/';
  211. }
  212. return $dispersionPath;
  213. }
  214. }