PageRenderTime 32ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Filter/File/Rename.php

http://github.com/zendframework/zf2
PHP | 335 lines | 204 code | 44 blank | 87 comment | 44 complexity | 5ac23cffa63a42aac3a4ed5fc049cfe2 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Filter\File;
  10. use Traversable;
  11. use Zend\Filter;
  12. use Zend\Filter\Exception;
  13. use Zend\Stdlib\ArrayUtils;
  14. class Rename extends Filter\AbstractFilter
  15. {
  16. /**
  17. * Internal array of array(source, target, overwrite)
  18. */
  19. protected $files = array();
  20. /**
  21. * Class constructor
  22. *
  23. * Options argument may be either a string, a Zend\Config\Config object, or an array.
  24. * If an array or Zend\Config\Config object, it accepts the following keys:
  25. * 'source' => Source filename or directory which will be renamed
  26. * 'target' => Target filename or directory, the new name of the source file
  27. * 'overwrite' => Shall existing files be overwritten ?
  28. * 'randomize' => Shall target files have a random postfix attached?
  29. *
  30. * @param string|array|Traversable $options Target file or directory to be renamed
  31. * @throws Exception\InvalidArgumentException
  32. */
  33. public function __construct($options)
  34. {
  35. if ($options instanceof Traversable) {
  36. $options = ArrayUtils::iteratorToArray($options);
  37. } elseif (is_string($options)) {
  38. $options = array('target' => $options);
  39. } elseif (!is_array($options)) {
  40. throw new Exception\InvalidArgumentException(
  41. 'Invalid options argument provided to filter'
  42. );
  43. }
  44. $this->setFile($options);
  45. }
  46. /**
  47. * Returns the files to rename and their new name and location
  48. *
  49. * @return array
  50. */
  51. public function getFile()
  52. {
  53. return $this->files;
  54. }
  55. /**
  56. * Sets a new file or directory as target, deleting existing ones
  57. *
  58. * Array accepts the following keys:
  59. * 'source' => Source filename or directory which will be renamed
  60. * 'target' => Target filename or directory, the new name of the sourcefile
  61. * 'overwrite' => Shall existing files be overwritten?
  62. * 'randomize' => Shall target files have a random postfix attached?
  63. *
  64. * @param string|array $options Old file or directory to be rewritten
  65. * @return self
  66. */
  67. public function setFile($options)
  68. {
  69. $this->files = array();
  70. $this->addFile($options);
  71. return $this;
  72. }
  73. /**
  74. * Adds a new file or directory as target to the existing ones
  75. *
  76. * Array accepts the following keys:
  77. * 'source' => Source filename or directory which will be renamed
  78. * 'target' => Target filename or directory, the new name of the sourcefile
  79. * 'overwrite' => Shall existing files be overwritten?
  80. * 'randomize' => Shall target files have a random postfix attached?
  81. *
  82. * @param string|array $options Old file or directory to be rewritten
  83. * @return Rename
  84. * @throws Exception\InvalidArgumentException
  85. */
  86. public function addFile($options)
  87. {
  88. if (is_string($options)) {
  89. $options = array('target' => $options);
  90. } elseif (!is_array($options)) {
  91. throw new Exception\InvalidArgumentException(
  92. 'Invalid options to rename filter provided'
  93. );
  94. }
  95. $this->_convertOptions($options);
  96. return $this;
  97. }
  98. /**
  99. * Returns only the new filename without moving it
  100. * But existing files will be erased when the overwrite option is true
  101. *
  102. * @param string $value Full path of file to change
  103. * @param bool $source Return internal informations
  104. * @return string The new filename which has been set
  105. * @throws Exception\InvalidArgumentException If the target file already exists.
  106. */
  107. public function getNewName($value, $source = false)
  108. {
  109. $file = $this->_getFileName($value);
  110. if (!is_array($file)) {
  111. return $file;
  112. }
  113. if ($file['source'] == $file['target']) {
  114. return $value;
  115. }
  116. if (!file_exists($file['source'])) {
  117. return $value;
  118. }
  119. if ($file['overwrite'] && file_exists($file['target'])) {
  120. unlink($file['target']);
  121. }
  122. if (file_exists($file['target'])) {
  123. throw new Exception\InvalidArgumentException(
  124. sprintf("File '%s' could not be renamed. It already exists.", $value)
  125. );
  126. }
  127. if ($source) {
  128. return $file;
  129. }
  130. return $file['target'];
  131. }
  132. /**
  133. * Defined by Zend\Filter\Filter
  134. *
  135. * Renames the file $value to the new name set before
  136. * Returns the file $value, removing all but digit characters
  137. *
  138. * @param string|array $value Full path of file to change or $_FILES data array
  139. * @throws Exception\RuntimeException
  140. * @return string|array The new filename which has been set
  141. */
  142. public function filter($value)
  143. {
  144. if (!is_scalar($value) && !is_array($value)) {
  145. return $value;
  146. }
  147. // An uploaded file? Retrieve the 'tmp_name'
  148. $isFileUpload = false;
  149. if (is_array($value)) {
  150. if (!isset($value['tmp_name'])) {
  151. return $value;
  152. }
  153. $isFileUpload = true;
  154. $uploadData = $value;
  155. $value = $value['tmp_name'];
  156. }
  157. $file = $this->getNewName($value, true);
  158. if (is_string($file)) {
  159. if ($isFileUpload) {
  160. return $uploadData;
  161. } else {
  162. return $file;
  163. }
  164. }
  165. $result = rename($file['source'], $file['target']);
  166. if ($result !== true) {
  167. throw new Exception\RuntimeException(
  168. sprintf(
  169. "File '%s' could not be renamed. " .
  170. "An error occurred while processing the file.",
  171. $value
  172. )
  173. );
  174. }
  175. if ($isFileUpload) {
  176. $uploadData['tmp_name'] = $file['target'];
  177. return $uploadData;
  178. }
  179. return $file['target'];
  180. }
  181. /**
  182. * Internal method for creating the file array
  183. * Supports single and nested arrays
  184. *
  185. * @param array $options
  186. * @return array
  187. */
  188. protected function _convertOptions($options)
  189. {
  190. $files = array();
  191. foreach ($options as $key => $value) {
  192. if (is_array($value)) {
  193. $this->_convertOptions($value);
  194. continue;
  195. }
  196. switch ($key) {
  197. case "source":
  198. $files['source'] = (string) $value;
  199. break;
  200. case 'target':
  201. $files['target'] = (string) $value;
  202. break;
  203. case 'overwrite':
  204. $files['overwrite'] = (bool) $value;
  205. break;
  206. case 'randomize':
  207. $files['randomize'] = (bool) $value;
  208. break;
  209. default:
  210. break;
  211. }
  212. }
  213. if (empty($files)) {
  214. return $this;
  215. }
  216. if (empty($files['source'])) {
  217. $files['source'] = '*';
  218. }
  219. if (empty($files['target'])) {
  220. $files['target'] = '*';
  221. }
  222. if (empty($files['overwrite'])) {
  223. $files['overwrite'] = false;
  224. }
  225. if (empty($files['randomize'])) {
  226. $files['randomize'] = false;
  227. }
  228. $found = false;
  229. foreach ($this->files as $key => $value) {
  230. if ($value['source'] == $files['source']) {
  231. $this->files[$key] = $files;
  232. $found = true;
  233. }
  234. }
  235. if (!$found) {
  236. $count = count($this->files);
  237. $this->files[$count] = $files;
  238. }
  239. return $this;
  240. }
  241. /**
  242. * Internal method to resolve the requested source
  243. * and return all other related parameters
  244. *
  245. * @param string $file Filename to get the informations for
  246. * @return array|string
  247. */
  248. protected function _getFileName($file)
  249. {
  250. $rename = array();
  251. foreach ($this->files as $value) {
  252. if ($value['source'] == '*') {
  253. if (!isset($rename['source'])) {
  254. $rename = $value;
  255. $rename['source'] = $file;
  256. }
  257. }
  258. if ($value['source'] == $file) {
  259. $rename = $value;
  260. break;
  261. }
  262. }
  263. if (!isset($rename['source'])) {
  264. return $file;
  265. }
  266. if (!isset($rename['target']) || $rename['target'] == '*') {
  267. $rename['target'] = $rename['source'];
  268. }
  269. if (is_dir($rename['target'])) {
  270. $name = basename($rename['source']);
  271. $last = $rename['target'][strlen($rename['target']) - 1];
  272. if (($last != '/') && ($last != '\\')) {
  273. $rename['target'] .= DIRECTORY_SEPARATOR;
  274. }
  275. $rename['target'] .= $name;
  276. }
  277. if ($rename['randomize']) {
  278. $info = pathinfo($rename['target']);
  279. $newTarget = $info['dirname'] . DIRECTORY_SEPARATOR .
  280. $info['filename'] . uniqid('_');
  281. if (isset($info['extension'])) {
  282. $newTarget .= '.' . $info['extension'];
  283. }
  284. $rename['target'] = $newTarget;
  285. }
  286. return $rename;
  287. }
  288. }