Uploader.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. /**
  3. *
  4. * PHP Pro Bid $Id$ XxTUuSvDVKH2GhOIp78MNxpYcfn9g6mJlgyQA0C4rlE=
  5. *
  6. * @link http://www.phpprobid.com
  7. * @copyright Copyright (c) 2017 Online Ventures Software & CodeCube SRL
  8. * @license http://www.phpprobid.com/license Commercial License
  9. *
  10. * @version 7.10 [rev.7.10.01]
  11. */
  12. /**
  13. * A class used to upload and process uploaded files
  14. *
  15. * If an uploaded file is an image, the image will be resized based on settings from the config file.
  16. * If a file is not an image, it is only uploaded.
  17. *
  18. * All files will be renamed to avoid file name conflicts.
  19. *
  20. */
  21. namespace Ppb\Model;
  22. use Cube\Controller\Front,
  23. Cube\Db\Expr,
  24. Ppb\Service,
  25. Ppb\View\Helper\Thumbnail as ThumbnailHelper;
  26. class Uploader
  27. {
  28. /**
  29. * prohibited extension replacement
  30. */
  31. const PROHIBITED_EXTENSION_REPLACEMENT = 'invalid';
  32. /**
  33. *
  34. * prohibited extensions
  35. *
  36. * @var array
  37. */
  38. protected $_prohibitedExtensions = array(
  39. 'php', 'exe', 'htm', 'js', 'pl', 'cgi', 'wml', 'perl'
  40. );
  41. /**
  42. *
  43. * the image upload process
  44. * if we have an image, we will resize it to a default maximum size
  45. *
  46. * @param string $tempFile
  47. * @param string $rawFileName
  48. * @param string $uploadType
  49. * @param string|null $watermarkText watermark text
  50. *
  51. * @return string|null return the file name or null if the upload was unsuccessful
  52. */
  53. public function upload($tempFile, $rawFileName, $uploadType = null, $watermarkText = null)
  54. {
  55. $fileName = $this->_generateFileName($rawFileName, $uploadType);
  56. $targetFile = $this->_generateTargetPath($fileName, $uploadType);
  57. $result = move_uploaded_file($tempFile, $targetFile);
  58. if ($result) {
  59. $image = new ThumbnailHelper();
  60. if ($image->isImage($targetFile)) {
  61. $image->setWidth(ThumbnailHelper::MAX_WIDTH)
  62. ->setHeight(false);
  63. $image->imageSmartRotate($targetFile);
  64. list($imgWidth, $imgHeight, $imgType) = @getimagesize($targetFile);
  65. if ($imgWidth > ThumbnailHelper::MAX_WIDTH) {
  66. $output = $image->createResizedImage($targetFile, false);
  67. $image->imageOutputFunction($output, $targetFile);
  68. }
  69. if (!empty($watermarkText)) {
  70. $image->addWatermark($targetFile, $watermarkText);
  71. }
  72. }
  73. return $fileName;
  74. }
  75. return false;
  76. }
  77. /**
  78. *
  79. * remove a local file
  80. * only delete if the file is not used anymore.
  81. *
  82. * @param string $fileName
  83. * @param string $uploadType
  84. *
  85. * @return $this
  86. */
  87. public function remove($fileName, $uploadType)
  88. {
  89. $listingsMediaService = new Service\ListingsMedia();
  90. $uploadType = preg_replace('#[^a-z]+#i', '', $uploadType);
  91. $select = $listingsMediaService->getTable()
  92. ->select(array('nb_rows' => new Expr('count(*)')))
  93. ->where('value = ?', $fileName)
  94. ->where('type = ?', $uploadType);
  95. $nbUploads = $listingsMediaService->getTable()->getAdapter()->fetchOne($select);
  96. $targetPath = $this->_generateTargetPath($fileName, $uploadType);
  97. if ($uploadType == 'image') {
  98. $this->_removeCacheFiles($fileName, $targetPath);
  99. }
  100. // remove file
  101. if (!$nbUploads) {
  102. @unlink($targetPath);
  103. }
  104. return $this;
  105. }
  106. /**
  107. *
  108. * remove cache files corresponding to the target image
  109. *
  110. * @param string $fileName
  111. * @param string $targetPath
  112. *
  113. * @return $this
  114. */
  115. protected function _removeCacheFiles($fileName, $targetPath = null)
  116. {
  117. if ($targetPath === null) {
  118. $targetPath = $this->_generateTargetPath($fileName, 'image');
  119. }
  120. // remove cache files for images
  121. $directory = __DIR__ . '/../../../' . \Ppb\Utility::getFolder('cache');
  122. $handler = opendir($directory);
  123. $pathInfo = pathinfo($targetPath);
  124. $baseName = (isset($pathInfo['filename'])) ? $pathInfo['filename'] : null;
  125. if ($baseName) {
  126. while ($file = readdir($handler)) {
  127. if ($file != "." && $file != "..") {
  128. if (strpos($file, $baseName) === 0) {
  129. @unlink($directory . DIRECTORY_SEPARATOR . $file);
  130. }
  131. }
  132. }
  133. }
  134. return $this;
  135. }
  136. /**
  137. *
  138. * get the target path of an uploaded file
  139. *
  140. * @param string $fileName
  141. * @param string $uploadType
  142. *
  143. * @return string
  144. */
  145. protected function _generateTargetPath($fileName, $uploadType = null)
  146. {
  147. // for now we only have images and videos, that go in the "uploads" folder
  148. $uploadType = preg_replace('#[^a-z]+#i', '', $uploadType);
  149. switch ($uploadType) {
  150. case 'download':
  151. $settings = Front::getInstance()->getBootstrap()->getResource('settings');
  152. $targetPath = __DIR__ . '/../../../' . $settings['digital_downloads_folder'] . DIRECTORY_SEPARATOR;
  153. break;
  154. default:
  155. $targetPath = \Ppb\Utility::getPath('uploads') . DIRECTORY_SEPARATOR;
  156. break;
  157. }
  158. return str_replace('//', '/', $targetPath) . $fileName;
  159. }
  160. /**
  161. *
  162. * set a unique file name for the uploaded file, so that no files are overwritten
  163. *
  164. * @param string $rawFileName
  165. * @param string $uploadType
  166. *
  167. * @return string
  168. */
  169. protected function _generateFileName($rawFileName, $uploadType = null)
  170. {
  171. $pathInfo = pathinfo($rawFileName);
  172. $tempName = preg_replace("/[^a-zA-Z0-9_-]/", '', $pathInfo['filename']);
  173. $fileExtension = $pathInfo['extension'];
  174. foreach ($this->_prohibitedExtensions as $prohibitedExtension) {
  175. if (stristr($fileExtension, $prohibitedExtension)) {
  176. $fileExtension = self::PROHIBITED_EXTENSION_REPLACEMENT;
  177. }
  178. }
  179. if (strpos($tempName, 'image') === 0 || $uploadType == 'download') {
  180. $tempName .= '-' . (int)(microtime(true) * 100);
  181. }
  182. $fileName = $tempName . '.' . $fileExtension;
  183. while (file_exists($this->_generateTargetPath($fileName))) {
  184. if (preg_match('#\((\d+)\)#', $fileName, $matches)) {
  185. $fileName = preg_replace('#\((\d+)\)#', '(' . ($matches[1] + 1) . ')', $fileName);
  186. }
  187. else {
  188. $fileName = $tempName . '-(1)' . '.' . $fileExtension;
  189. }
  190. }
  191. return $fileName;
  192. }
  193. }