file.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * HTML class for a file upload field
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * LICENSE: This source file is subject to version 3.01 of the PHP license
  9. * that is available through the world-wide-web at the following URI:
  10. * http://www.php.net/license/3_01.txt If you did not receive a copy of
  11. * the PHP License and are unable to obtain it through the web, please
  12. * send a note to license@php.net so we can mail you a copy immediately.
  13. *
  14. * @category HTML
  15. * @package HTML_QuickForm
  16. * @author Adam Daniel <adaniel1@eesus.jnj.com>
  17. * @author Bertrand Mansion <bmansion@mamasam.com>
  18. * @author Alexey Borzov <avb@php.net>
  19. * @copyright 2001-2009 The PHP Group
  20. * @license http://www.php.net/license/3_01.txt PHP License 3.01
  21. * @version CVS: $Id: file.php,v 1.25 2009/04/04 21:34:02 avb Exp $
  22. * @link http://pear.php.net/package/HTML_QuickForm
  23. */
  24. /**
  25. * HTML class for a file upload field
  26. *
  27. * @category HTML
  28. * @package HTML_QuickForm
  29. * @author Adam Daniel <adaniel1@eesus.jnj.com>
  30. * @author Bertrand Mansion <bmansion@mamasam.com>
  31. * @author Alexey Borzov <avb@php.net>
  32. * @version Release: 3.2.11
  33. * @since 1.0
  34. */
  35. class HTML_QuickForm_file extends HTML_QuickForm_input
  36. {
  37. // {{{ properties
  38. /**
  39. * Uploaded file data, from $_FILES
  40. * @var array
  41. */
  42. var $_value = null;
  43. // }}}
  44. // {{{ constructor
  45. /**
  46. * Class constructor
  47. *
  48. * @param string Input field name attribute
  49. * @param string Input field label
  50. * @param mixed (optional)Either a typical HTML attribute string
  51. * or an associative array
  52. * @since 1.0
  53. * @access public
  54. */
  55. public function __construct($elementName=null, $elementLabel=null, $attributes=null)
  56. {
  57. parent::__construct($elementName, $elementLabel, $attributes);
  58. $this->setType('file');
  59. } //end constructor
  60. // }}}
  61. // {{{ setSize()
  62. /**
  63. * Sets size of file element
  64. *
  65. * @param int Size of file element
  66. * @since 1.0
  67. * @access public
  68. */
  69. function setSize($size)
  70. {
  71. $this->updateAttributes(array('size' => $size));
  72. } //end func setSize
  73. // }}}
  74. // {{{ getSize()
  75. /**
  76. * Returns size of file element
  77. *
  78. * @since 1.0
  79. * @access public
  80. * @return int
  81. */
  82. function getSize()
  83. {
  84. return $this->getAttribute('size');
  85. } //end func getSize
  86. // }}}
  87. // {{{ freeze()
  88. /**
  89. * Freeze the element so that only its value is returned
  90. *
  91. * @access public
  92. * @return bool
  93. */
  94. function freeze()
  95. {
  96. return false;
  97. } //end func freeze
  98. // }}}
  99. // {{{ setValue()
  100. /**
  101. * Sets value for file element.
  102. *
  103. * Actually this does nothing. The function is defined here to override
  104. * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
  105. * no sane user-agent uses <input type="file">'s value for anything
  106. * (because of security implications) we implement file's value as a
  107. * read-only property with a special meaning.
  108. *
  109. * @param mixed Value for file element
  110. * @since 3.0
  111. * @access public
  112. */
  113. function setValue($value)
  114. {
  115. return null;
  116. } //end func setValue
  117. // }}}
  118. // {{{ getValue()
  119. /**
  120. * Returns information about the uploaded file
  121. *
  122. * @since 3.0
  123. * @access public
  124. * @return array
  125. */
  126. public function getValue()
  127. {
  128. return $this->_value;
  129. } // end func getValue
  130. // }}}
  131. // {{{ onQuickFormEvent()
  132. /**
  133. * Called by HTML_QuickForm whenever form event is made on this element
  134. *
  135. * @param string Name of event
  136. * @param mixed event arguments
  137. * @param object calling object
  138. * @since 1.0
  139. * @access public
  140. * @return bool
  141. */
  142. public function onQuickFormEvent($event, $arg, &$caller)
  143. {
  144. switch ($event) {
  145. case 'updateValue':
  146. if ($caller->getAttribute('method') == 'get') {
  147. throw new \Exception('Cannot add a file upload field to a GET method form');
  148. }
  149. $this->_value = $this->_findValue();
  150. $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
  151. $caller->setMaxFileSize();
  152. break;
  153. case 'addElement':
  154. $this->onQuickFormEvent('createElement', $arg, $caller);
  155. return $this->onQuickFormEvent('updateValue', null, $caller);
  156. break;
  157. case 'createElement':
  158. //$className = get_class($this);
  159. //$this &= new $className($arg[0], $arg[1], $arg[2]);
  160. break;
  161. }
  162. return true;
  163. }
  164. /**
  165. * Moves an uploaded file into the destination
  166. *
  167. * @param string Destination directory path
  168. * @param string New file name
  169. * @access public
  170. * @return bool Whether the file was moved successfully
  171. */
  172. public function moveUploadedFile($dest, $fileName = '')
  173. {
  174. if ($dest != '' && substr($dest, -1) != '/') {
  175. $dest .= '/';
  176. }
  177. $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
  178. return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName);
  179. }
  180. /**
  181. * Checks if the element contains an uploaded file
  182. *
  183. * @access public
  184. * @return bool true if file has been uploaded, false otherwise
  185. */
  186. public function isUploadedFile()
  187. {
  188. return self::_ruleIsUploadedFile($this->_value);
  189. }
  190. /**
  191. * Checks if the given element contains an uploaded file
  192. *
  193. * @param array Uploaded file info (from $_FILES)
  194. * @access private
  195. * @return bool true if file has been uploaded, false otherwise
  196. */
  197. public static function _ruleIsUploadedFile($elementValue)
  198. {
  199. if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
  200. (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
  201. return is_uploaded_file($elementValue['tmp_name']);
  202. } else {
  203. return false;
  204. }
  205. }
  206. /**
  207. * Tries to find the element value from the values array
  208. *
  209. * Needs to be redefined here as $_FILES is populated differently from
  210. * other arrays when element name is of the form foo[bar]
  211. *
  212. * @access public
  213. * @return mixed
  214. */
  215. public function _findValue(&$values = null)
  216. {
  217. if (empty($_FILES)) {
  218. return null;
  219. }
  220. $elementName = $this->getName();
  221. if (isset($_FILES[$elementName])) {
  222. return $_FILES[$elementName];
  223. } elseif (false !== ($pos = strpos($elementName, '['))) {
  224. $base = str_replace(
  225. array('\\', '\''), array('\\\\', '\\\''),
  226. substr($elementName, 0, $pos)
  227. );
  228. $idx = "['" . str_replace(
  229. array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
  230. substr($elementName, $pos + 1, -1)
  231. ) . "']";
  232. $props = array('name', 'type', 'size', 'tmp_name', 'error');
  233. $code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
  234. " return null;\n" .
  235. "} else {\n" .
  236. " \$value = array();\n";
  237. foreach ($props as $prop) {
  238. $code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
  239. }
  240. return eval($code . " return \$value;\n}\n");
  241. } else {
  242. return null;
  243. }
  244. }
  245. /**
  246. * @return string
  247. */
  248. public function getElementJS($param)
  249. {
  250. $id = $this->getAttribute('id');
  251. $ratio = '16 / 9';
  252. if (!empty($param['ratio'])) {
  253. $ratio = $param['ratio'];
  254. }
  255. return '<script>
  256. $(document).ready(function() {
  257. var $image = $("#'.$id.'_preview_image");
  258. var $input = $("[name=\''.$id.'_crop_result\']");
  259. var $cropButton = $("#'.$id.'_crop_button");
  260. var canvas = "";
  261. var imageWidth = "";
  262. var imageHeight = "";
  263. $("#'.$id.'").change(function() {
  264. var oFReader = new FileReader();
  265. oFReader.readAsDataURL(document.getElementById("'.$id.'").files[0]);
  266. oFReader.onload = function (oFREvent) {
  267. $image.attr("src", this.result);
  268. $("#'.$id.'_label_crop_image").html("'.get_lang('Preview').'");
  269. $("#'.$id.'_crop_image").addClass("thumbnail");
  270. $cropButton.removeClass("hidden");
  271. // Destroy cropper
  272. $image.cropper("destroy");
  273. $image.cropper({
  274. aspectRatio: ' . $ratio . ',
  275. responsive : true,
  276. center : false,
  277. guides : false,
  278. movable: false,
  279. zoomable: false,
  280. rotatable: false,
  281. scalable: false,
  282. crop: function(e) {
  283. // Output the result data for cropping image.
  284. $input.val(e.x+","+e.y+","+e.width+","+e.height);
  285. }
  286. });
  287. };
  288. });
  289. $("#'.$id.'_crop_button").on("click", function() {
  290. var canvas = $image.cropper("getCroppedCanvas");
  291. var dataUrl = canvas.toDataURL();
  292. $image.attr("src", dataUrl);
  293. $image.cropper("destroy");
  294. $cropButton.addClass("hidden");
  295. return false;
  296. });
  297. });
  298. </script>';
  299. }
  300. public function toHtml()
  301. {
  302. $js = '';
  303. if (isset($this->_attributes['crop_image'])) {
  304. $ratio = '16 / 9';
  305. if (!empty($this->_attributes['crop_ratio'])) {
  306. $ratio = $this->_attributes['crop_ratio'];
  307. }
  308. $js = $this->getElementJS(array('ratio' => $ratio));
  309. }
  310. if ($this->_flagFrozen) {
  311. return $this->getFrozenHtml();
  312. } else {
  313. return $js.$this->_getTabs() . '<input' . $this->_getAttrString($this->_attributes) . ' />';
  314. }
  315. } //end func toHtml
  316. }