Merge pull request #15837 from totten/master-prtmpl
[civicrm-core.git] / CRM / Core / QuickForm / Action / Upload.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Redefine the upload action.
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 * $Id$
18 */
19 class CRM_Core_QuickForm_Action_Upload extends CRM_Core_QuickForm_Action {
20
21 /**
22 * The array of uploaded file names.
23 * @var array
24 */
25 protected $_uploadNames;
26
27 /**
28 * The directory to store the uploaded files.
29 * @var string
30 */
31 protected $_uploadDir;
32
33 /**
34 * Class constructor.
35 *
36 * @param object $stateMachine
37 * Reference to state machine object.
38 * @param string $uploadDir
39 * Directory to store the uploaded files.
40 * @param array $uploadNames
41 * Element names of the various uploadable files.
42 *
43 * @return \CRM_Core_QuickForm_Action_Upload
44 */
45 public function __construct(&$stateMachine, $uploadDir, $uploadNames) {
46 parent::__construct($stateMachine);
47
48 $this->_uploadDir = $uploadDir;
49 $this->_uploadNames = $uploadNames;
50 }
51
52 /**
53 * Upload and move the file if valid to the uploaded directory.
54 *
55 * @param CRM_Core_Form $page
56 * The CRM_Core_Form object.
57 * @param object $data
58 * The QFC data container.
59 * @param string $pageName
60 * The name of the page which index the data container with.
61 * @param string $uploadName
62 * The name of the uploaded file.
63 */
64 public function upload(&$page, &$data, $pageName, $uploadName) {
65 // make sure uploadName exists in the QF array
66 // else we skip, CRM-3427
67 if (empty($uploadName) ||
68 !isset($page->_elementIndex[$uploadName])
69 ) {
70 return;
71 }
72
73 // get the element containing the upload
74 $element = &$page->getElement($uploadName);
75 if ('file' == $element->getType()) {
76 if ($element->isUploadedFile()) {
77 // rename the uploaded file with a unique number at the end
78 $value = $element->getValue();
79
80 $newName = CRM_Utils_File::makeFileName($value['name']);
81 $status = $element->moveUploadedFile($this->_uploadDir, $newName);
82 if (!$status) {
83 CRM_Core_Error::statusBounce(ts('We could not move the uploaded file %1 to the upload directory %2. Please verify that the \'Temporary Files\' setting points to a valid path which is writable by your web server.', [
84 1 => $value['name'],
85 2 => $this->_uploadDir,
86 ]));
87 }
88 if (!empty($data['values'][$pageName][$uploadName]['name'])) {
89 @unlink($this->_uploadDir . $data['values'][$pageName][$uploadName]);
90 }
91
92 $value = [
93 'name' => $this->_uploadDir . $newName,
94 'type' => $value['type'],
95 ];
96 //CRM-19460 handle brackets if present in $uploadName, similar things we do it for all other inputs.
97 $value = $element->_prepareValue($value, TRUE);
98 $data['values'][$pageName] = HTML_QuickForm::arrayMerge($data['values'][$pageName], $value);
99 }
100 }
101 }
102
103 /**
104 * Processes the request.
105 *
106 * @param CRM_Core_Form $page
107 * CRM_Core_Form the current form-page.
108 * @param string $actionName
109 * Current action name, as one Action object can serve multiple actions.
110 */
111 public function perform(&$page, $actionName) {
112 // like in Action_Next
113 $page->isFormBuilt() or $page->buildForm();
114
115 // so this is a brain-seizure moment, so hang tight (real tight!)
116 // the above buildForm potentially changes the action function with different args
117 // so basically the rug might have been pulled from us, so we actually just check
118 // and potentially call the right one
119 // this allows standalone form uploads to work nicely
120 $page->controller->_actions['upload']->realPerform($page, $actionName);
121 }
122
123 /**
124 * Real perform.
125 *
126 * @todo document what I do.
127 *
128 * @param CRM_Core_Form $page
129 * @param string $actionName
130 *
131 * @return mixed
132 */
133 public function realPerform(&$page, $actionName) {
134 $pageName = $page->getAttribute('name');
135 $data = &$page->controller->container();
136 $data['values'][$pageName] = $page->exportValues();
137 $data['valid'][$pageName] = $page->validate();
138
139 if (!$data['valid'][$pageName]) {
140 return $page->handle('display');
141 }
142
143 foreach ($this->_uploadNames as $name) {
144 $this->upload($page, $data, $pageName, $name);
145 }
146
147 $state = &$this->_stateMachine->getState($pageName);
148 if (empty($state)) {
149 return $page->handle('display');
150 }
151
152 // the page is valid, process it before we jump to the next state
153 $page->mainProcess();
154
155 // check if destination is set, if so goto destination
156 $destination = $this->_stateMachine->getDestination();
157 if ($destination) {
158 $destination = urldecode($destination);
159 CRM_Utils_System::redirect($destination);
160 }
161 else {
162 return $state->handleNextState($page);
163 }
164 }
165
166 }