Validator.php 7.0 KB

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