class-wc-product-download.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <?php
  2. /**
  3. * Represents a file which can be downloaded.
  4. *
  5. * @package WooCommerce/Classes
  6. * @version 3.0.0
  7. * @since 3.0.0
  8. */
  9. defined( 'ABSPATH' ) || exit;
  10. /**
  11. * Product download class.
  12. */
  13. class WC_Product_Download implements ArrayAccess {
  14. /**
  15. * Data array.
  16. *
  17. * @since 3.0.0
  18. * @var array
  19. */
  20. protected $data = array(
  21. 'id' => '',
  22. 'name' => '',
  23. 'file' => '',
  24. );
  25. /**
  26. * Returns all data for this object.
  27. *
  28. * @return array
  29. */
  30. public function get_data() {
  31. return $this->data;
  32. }
  33. /**
  34. * Get allowed mime types.
  35. *
  36. * @return array
  37. */
  38. public function get_allowed_mime_types() {
  39. return apply_filters( 'woocommerce_downloadable_file_allowed_mime_types', get_allowed_mime_types() );
  40. }
  41. /**
  42. * Get type of file path set.
  43. *
  44. * @param string $file_path optional.
  45. * @return string absolute, relative, or shortcode.
  46. */
  47. public function get_type_of_file_path( $file_path = '' ) {
  48. $file_path = $file_path ? $file_path : $this->get_file();
  49. if ( 0 === strpos( $file_path, 'http' ) || 0 === strpos( $file_path, '//' ) ) {
  50. return 'absolute';
  51. } elseif ( '[' === substr( $file_path, 0, 1 ) && ']' === substr( $file_path, -1 ) ) {
  52. return 'shortcode';
  53. } else {
  54. return 'relative';
  55. }
  56. }
  57. /**
  58. * Get file type.
  59. *
  60. * @return string
  61. */
  62. public function get_file_type() {
  63. $type = wp_check_filetype( strtok( $this->get_file(), '?' ), $this->get_allowed_mime_types() );
  64. return $type['type'];
  65. }
  66. /**
  67. * Get file extension.
  68. *
  69. * @return string
  70. */
  71. public function get_file_extension() {
  72. $parsed_url = wp_parse_url( $this->get_file(), PHP_URL_PATH );
  73. return pathinfo( $parsed_url, PATHINFO_EXTENSION );
  74. }
  75. /**
  76. * Check if file is allowed.
  77. *
  78. * @return boolean
  79. */
  80. public function is_allowed_filetype() {
  81. if ( 'relative' !== $this->get_type_of_file_path() ) {
  82. return true;
  83. }
  84. return ! $this->get_file_extension() || in_array( $this->get_file_type(), $this->get_allowed_mime_types(), true );
  85. }
  86. /**
  87. * Validate file exists.
  88. *
  89. * @return boolean
  90. */
  91. public function file_exists() {
  92. if ( 'relative' !== $this->get_type_of_file_path() ) {
  93. return true;
  94. }
  95. $file_url = $this->get_file();
  96. if ( '..' === substr( $file_url, 0, 2 ) || '/' !== substr( $file_url, 0, 1 ) ) {
  97. $file_url = realpath( ABSPATH . $file_url );
  98. } elseif ( substr( WP_CONTENT_DIR, strlen( untrailingslashit( ABSPATH ) ) ) === substr( $file_url, 0, strlen( substr( WP_CONTENT_DIR, strlen( untrailingslashit( ABSPATH ) ) ) ) ) ) {
  99. $file_url = realpath( WP_CONTENT_DIR . substr( $file_url, 11 ) );
  100. }
  101. return apply_filters( 'woocommerce_downloadable_file_exists', file_exists( $file_url ), $this->get_file() );
  102. }
  103. /*
  104. |--------------------------------------------------------------------------
  105. | Setters
  106. |--------------------------------------------------------------------------
  107. */
  108. /**
  109. * Set ID.
  110. *
  111. * @param string $value Download ID.
  112. */
  113. public function set_id( $value ) {
  114. $this->data['id'] = wc_clean( $value );
  115. }
  116. /**
  117. * Set name.
  118. *
  119. * @param string $value Download name.
  120. */
  121. public function set_name( $value ) {
  122. $this->data['name'] = wc_clean( $value );
  123. }
  124. /**
  125. * Set previous_hash.
  126. *
  127. * @deprecated 3.3.0 No longer using filename based hashing to keep track of files.
  128. * @param string $value Previous hash.
  129. */
  130. public function set_previous_hash( $value ) {
  131. wc_deprecated_function( __FUNCTION__, '3.3' );
  132. $this->data['previous_hash'] = wc_clean( $value );
  133. }
  134. /**
  135. * Set file.
  136. *
  137. * @param string $value File.
  138. */
  139. public function set_file( $value ) {
  140. switch ( $this->get_type_of_file_path( $value ) ) {
  141. case 'absolute':
  142. $this->data['file'] = esc_url_raw( $value );
  143. break;
  144. default:
  145. $this->data['file'] = wc_clean( $value );
  146. break;
  147. }
  148. }
  149. /*
  150. |--------------------------------------------------------------------------
  151. | Getters
  152. |--------------------------------------------------------------------------
  153. */
  154. /**
  155. * Get id.
  156. *
  157. * @return string
  158. */
  159. public function get_id() {
  160. return $this->data['id'];
  161. }
  162. /**
  163. * Get name.
  164. *
  165. * @return string
  166. */
  167. public function get_name() {
  168. return $this->data['name'];
  169. }
  170. /**
  171. * Get previous_hash.
  172. *
  173. * @deprecated 3.3.0 No longer using filename based hashing to keep track of files.
  174. * @return string
  175. */
  176. public function get_previous_hash() {
  177. wc_deprecated_function( __FUNCTION__, '3.3' );
  178. return $this->data['previous_hash'];
  179. }
  180. /**
  181. * Get file.
  182. *
  183. * @return string
  184. */
  185. public function get_file() {
  186. return $this->data['file'];
  187. }
  188. /*
  189. |--------------------------------------------------------------------------
  190. | ArrayAccess/Backwards compatibility.
  191. |--------------------------------------------------------------------------
  192. */
  193. /**
  194. * OffsetGet.
  195. *
  196. * @param string $offset Offset.
  197. * @return mixed
  198. */
  199. public function offsetGet( $offset ) {
  200. switch ( $offset ) {
  201. default:
  202. if ( is_callable( array( $this, "get_$offset" ) ) ) {
  203. return $this->{"get_$offset"}();
  204. }
  205. break;
  206. }
  207. return '';
  208. }
  209. /**
  210. * OffsetSet.
  211. *
  212. * @param string $offset Offset.
  213. * @param mixed $value Value.
  214. */
  215. public function offsetSet( $offset, $value ) {
  216. switch ( $offset ) {
  217. default:
  218. if ( is_callable( array( $this, "set_$offset" ) ) ) {
  219. return $this->{"set_$offset"}( $value );
  220. }
  221. break;
  222. }
  223. }
  224. /**
  225. * OffsetUnset.
  226. *
  227. * @param string $offset Offset.
  228. */
  229. public function offsetUnset( $offset ) {}
  230. /**
  231. * OffsetExists.
  232. *
  233. * @param string $offset Offset.
  234. * @return bool
  235. */
  236. public function offsetExists( $offset ) {
  237. return in_array( $offset, array_keys( $this->data ), true );
  238. }
  239. }