Validator.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. namespace Gedmo\Uploadable\Mapping;
  3. use Gedmo\Exception\InvalidMappingException;
  4. use Gedmo\Exception\UploadableCantWriteException;
  5. use Gedmo\Exception\UploadableInvalidPathException;
  6. use Doctrine\Common\Persistence\Mapping\ClassMetadata;
  7. /**
  8. * This class is used to validate mapping information
  9. *
  10. * @author Gustavo Falco <comfortablynumb84@gmail.com>
  11. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  12. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  13. */
  14. class Validator
  15. {
  16. const UPLOADABLE_FILE_MIME_TYPE = 'UploadableFileMimeType';
  17. const UPLOADABLE_FILE_NAME = 'UploadableFileName';
  18. const UPLOADABLE_FILE_PATH = 'UploadableFilePath';
  19. const UPLOADABLE_FILE_SIZE = 'UploadableFileSize';
  20. const FILENAME_GENERATOR_SHA1 = 'SHA1';
  21. const FILENAME_GENERATOR_ALPHANUMERIC = 'ALPHANUMERIC';
  22. const FILENAME_GENERATOR_NONE = 'NONE';
  23. /**
  24. * Determines if we should throw an exception in the case the "allowedTypes" and
  25. * "disallowedTypes" options are BOTH set. Useful for testing purposes
  26. *
  27. * @var bool
  28. */
  29. public static $enableMimeTypesConfigException = true;
  30. /**
  31. * List of types which are valid for UploadableFileMimeType field
  32. *
  33. * @var array
  34. */
  35. public static $validFileMimeTypeTypes = array(
  36. 'string',
  37. );
  38. /**
  39. * List of types which are valid for UploadableFileName field
  40. *
  41. * @var array
  42. */
  43. public static $validFileNameTypes = array(
  44. 'string',
  45. );
  46. /**
  47. * List of types which are valid for UploadableFilePath field
  48. *
  49. * @var array
  50. */
  51. public static $validFilePathTypes = array(
  52. 'string',
  53. );
  54. /**
  55. * List of types which are valid for UploadableFileSize field for ORM
  56. *
  57. * @var array
  58. */
  59. public static $validFileSizeTypes = array(
  60. 'decimal',
  61. );
  62. /**
  63. * List of types which are valid for UploadableFileSize field for ODM
  64. *
  65. * @var array
  66. */
  67. public static $validFileSizeTypesODM = array(
  68. 'float',
  69. );
  70. /**
  71. * Whether to validate if the directory of the file exists and is writable, useful to disable it when using
  72. * stream wrappers which don't support is_dir (like Gaufrette)
  73. *
  74. * @var bool
  75. */
  76. public static $validateWritableDirectory = true;
  77. public static function validateFileNameField(ClassMetadata $meta, $field)
  78. {
  79. self::validateField($meta, $field, self::UPLOADABLE_FILE_NAME, self::$validFileNameTypes);
  80. }
  81. public static function validateFileMimeTypeField(ClassMetadata $meta, $field)
  82. {
  83. self::validateField($meta, $field, self::UPLOADABLE_FILE_MIME_TYPE, self::$validFileMimeTypeTypes);
  84. }
  85. public static function validateFilePathField(ClassMetadata $meta, $field)
  86. {
  87. self::validateField($meta, $field, self::UPLOADABLE_FILE_PATH, self::$validFilePathTypes);
  88. }
  89. public static function validateFileSizeField(ClassMetadata $meta, $field)
  90. {
  91. if ($meta instanceof \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo) {
  92. self::validateField($meta, $field, self::UPLOADABLE_FILE_SIZE, self::$validFileSizeTypesODM);
  93. } else {
  94. self::validateField($meta, $field, self::UPLOADABLE_FILE_SIZE, self::$validFileSizeTypes);
  95. }
  96. }
  97. public static function validateField($meta, $field, $uploadableField, $validFieldTypes)
  98. {
  99. if ($meta->isMappedSuperclass) {
  100. return;
  101. }
  102. $fieldMapping = $meta->getFieldMapping($field);
  103. if (!in_array($fieldMapping['type'], $validFieldTypes)) {
  104. $msg = 'Field "%s" to work as an "%s" field must be of one of the following types: "%s".';
  105. throw new InvalidMappingException(sprintf($msg,
  106. $field,
  107. $uploadableField,
  108. implode(', ', $validFieldTypes)
  109. ));
  110. }
  111. }
  112. public static function validatePath($path)
  113. {
  114. if (!is_string($path) || $path === '') {
  115. throw new UploadableInvalidPathException('Path must be a string containing the path to a valid directory.');
  116. }
  117. if (!self::$validateWritableDirectory) {
  118. return;
  119. }
  120. if (!is_dir($path) && !@mkdir($path, 0777, true)) {
  121. throw new UploadableInvalidPathException(sprintf('Unable to create "%s" directory.',
  122. $path
  123. ));
  124. }
  125. if (!is_writable($path)) {
  126. throw new UploadableCantWriteException(sprintf('Directory "%s" does is not writable.',
  127. $path
  128. ));
  129. }
  130. }
  131. public static function validateConfiguration(ClassMetadata $meta, array &$config)
  132. {
  133. if (!$config['filePathField'] && !$config['fileNameField']) {
  134. throw new InvalidMappingException(sprintf('Class "%s" must have an UploadableFilePath or UploadableFileName field.',
  135. $meta->name
  136. ));
  137. }
  138. $refl = $meta->getReflectionClass();
  139. if ($config['pathMethod'] !== '' && !$refl->hasMethod($config['pathMethod'])) {
  140. throw new InvalidMappingException(sprintf('Class "%s" doesn\'t have method "%s"!',
  141. $meta->name,
  142. $config['pathMethod']
  143. ));
  144. }
  145. if ($config['callback'] !== '' && !$refl->hasMethod($config['callback'])) {
  146. throw new InvalidMappingException(sprintf('Class "%s" doesn\'t have method "%s"!',
  147. $meta->name,
  148. $config['callback']
  149. ));
  150. }
  151. $config['maxSize'] = (double) $config['maxSize'];
  152. if ($config['maxSize'] < 0) {
  153. throw new InvalidMappingException(sprintf('Option "maxSize" must be a number >= 0 for class "%s".',
  154. $meta->name
  155. ));
  156. }
  157. if (self::$enableMimeTypesConfigException && ($config['allowedTypes'] !== '' && $config['disallowedTypes'] !== '')) {
  158. $msg = 'You\'ve set "allowedTypes" and "disallowedTypes" options. You must set only one in class "%s".';
  159. throw new InvalidMappingException(sprintf($msg,
  160. $meta->name
  161. ));
  162. }
  163. $config['allowedTypes'] = $config['allowedTypes'] ? (strpos($config['allowedTypes'], ',') !== false ?
  164. explode(',', $config['allowedTypes']) : array($config['allowedTypes'])) : false;
  165. $config['disallowedTypes'] = $config['disallowedTypes'] ? (strpos($config['disallowedTypes'], ',') !== false ?
  166. explode(',', $config['disallowedTypes']) : array($config['disallowedTypes'])) : false;
  167. if ($config['fileNameField']) {
  168. self::validateFileNameField($meta, $config['fileNameField']);
  169. }
  170. if ($config['filePathField']) {
  171. self::validateFilePathField($meta, $config['filePathField']);
  172. }
  173. if ($config['fileMimeTypeField']) {
  174. self::validateFileMimeTypeField($meta, $config['fileMimeTypeField']);
  175. }
  176. if ($config['fileSizeField']) {
  177. self::validateFileSizeField($meta, $config['fileSizeField']);
  178. }
  179. switch ((string) $config['filenameGenerator']) {
  180. case self::FILENAME_GENERATOR_ALPHANUMERIC:
  181. case self::FILENAME_GENERATOR_SHA1:
  182. case self::FILENAME_GENERATOR_NONE:
  183. break;
  184. default:
  185. $ok = false;
  186. if (class_exists($config['filenameGenerator'])) {
  187. $refl = new \ReflectionClass($config['filenameGenerator']);
  188. if ($refl->implementsInterface('Gedmo\Uploadable\FilenameGenerator\FilenameGeneratorInterface')) {
  189. $ok = true;
  190. }
  191. }
  192. if (!$ok) {
  193. $msg = 'Class "%s" needs a valid value for filenameGenerator. It can be: SHA1, ALPHANUMERIC, NONE or ';
  194. $msg .= 'a class implementing FileGeneratorInterface.';
  195. throw new InvalidMappingException(sprintf($msg,
  196. $meta->name
  197. ));
  198. }
  199. }
  200. }
  201. }