Merge pull request #11540 from eileenmcnaughton/yahoo
[civicrm-core.git] / CRM / Admin / Form / PaymentProcessor.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2017
32 */
33
34 /**
35 * This class generates form components for Payment Processor.
36 */
37 class CRM_Admin_Form_PaymentProcessor extends CRM_Admin_Form {
38 protected $_id = NULL;
39
40 protected $_testID = NULL;
41
42 protected $_fields = NULL;
43
44 protected $_ppDAO;
45
46 /**
47 * Get the name of the base entity being edited.
48 *
49 * @return string
50 */
51 public function getDefaultEntity() {
52 return 'PaymentProcessor';
53 }
54
55 public function preProcess() {
56 parent::preProcess();
57
58 if ($this->_id) {
59 $this->_ppType = CRM_Utils_Request::retrieve('pp', 'String', $this, FALSE, NULL);
60 if (!$this->_ppType) {
61 $this->_ppType = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessor',
62 $this->_id,
63 'payment_processor_type_id'
64 );
65 }
66 $this->set('pp', $this->_ppType);
67 }
68 else {
69 $this->_ppType = CRM_Utils_Request::retrieve('pp', 'String', $this, TRUE, NULL);
70 }
71
72 $this->assign('ppType', $this->_ppType);
73 $ppTypeName = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
74 $this->_ppType,
75 'name'
76 );
77 $this->assign('ppTypeName', $ppTypeName);
78
79 $this->_ppDAO = new CRM_Financial_DAO_PaymentProcessorType();
80 $this->_ppDAO->id = $this->_ppType;
81
82 $this->_ppDAO->find(TRUE);
83
84 if ($this->_id) {
85 $refreshURL = CRM_Utils_System::url('civicrm/admin/paymentProcessor',
86 "reset=1&action=update&id={$this->_id}",
87 FALSE, NULL, FALSE
88 );
89 }
90 else {
91 $refreshURL = CRM_Utils_System::url('civicrm/admin/paymentProcessor',
92 "reset=1&action=add",
93 FALSE, NULL, FALSE
94 );
95 }
96
97 //CRM-4129
98 $destination = CRM_Utils_Request::retrieve('civicrmDestination', 'String', $this);
99 if ($destination) {
100 $destination = urlencode($destination);
101 $refreshURL .= "&civicrmDestination=$destination";
102 }
103
104 $this->refreshURL = $refreshURL;
105 $this->assign('refreshURL', $refreshURL);
106
107 $this->assign('is_recur', $this->_ppDAO->is_recur);
108
109 $this->_fields = array(
110 array(
111 'name' => 'user_name',
112 'label' => $this->_ppDAO->user_name_label,
113 ),
114 array(
115 'name' => 'password',
116 'label' => $this->_ppDAO->password_label,
117 ),
118 array(
119 'name' => 'signature',
120 'label' => $this->_ppDAO->signature_label,
121 ),
122 array(
123 'name' => 'subject',
124 'label' => $this->_ppDAO->subject_label,
125 ),
126 array(
127 'name' => 'url_site',
128 'label' => ts('Site URL'),
129 'rule' => 'url',
130 'msg' => ts('Enter a valid URL'),
131 ),
132 );
133
134 if ($this->_ppDAO->is_recur) {
135 $this->_fields[] = array(
136 'name' => 'url_recur',
137 'label' => ts('Recurring Payments URL'),
138 'rule' => 'url',
139 'msg' => ts('Enter a valid URL'),
140 );
141 }
142
143 if (!empty($this->_ppDAO->url_button_default)) {
144 $this->_fields[] = array(
145 'name' => 'url_button',
146 'label' => ts('Button URL'),
147 'rule' => 'url',
148 'msg' => ts('Enter a valid URL'),
149 );
150 }
151
152 if (!empty($this->_ppDAO->url_api_default)) {
153 $this->_fields[] = array(
154 'name' => 'url_api',
155 'label' => ts('API URL'),
156 'rule' => 'url',
157 'msg' => ts('Enter a valid URL'),
158 );
159 }
160 }
161
162 /**
163 * Build the form object.
164 *
165 * @param bool $check
166 */
167 public function buildQuickForm($check = FALSE) {
168 parent::buildQuickForm();
169
170 if ($this->_action & CRM_Core_Action::DELETE) {
171 return;
172 }
173
174 $attributes = CRM_Core_DAO::getAttribute('CRM_Financial_DAO_PaymentProcessor');
175
176 $this->add('text', 'name', ts('Name'),
177 $attributes['name'], TRUE
178 );
179
180 $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', array(
181 'CRM_Financial_DAO_PaymentProcessor',
182 $this->_id,
183 'name',
184 CRM_Core_Config::domainID(),
185 ));
186
187 $this->add('text', 'description', ts('Description'),
188 $attributes['description']
189 );
190
191 $types = CRM_Core_PseudoConstant::paymentProcessorType();
192 $this->add('select', 'payment_processor_type_id', ts('Payment Processor Type'), $types, TRUE,
193 array('onchange' => "reload(true)")
194 );
195
196 // Financial Account of account type asset CRM-11515
197 $accountType = CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name = 'Asset' ");
198 $financialAccount = CRM_Contribute_PseudoConstant::financialAccount(NULL, key($accountType));
199 if ($fcount = count($financialAccount)) {
200 $this->assign('financialAccount', $fcount);
201 }
202 $this->add('select', 'financial_account_id', ts('Financial Account'),
203 array('' => ts('- select -')) + $financialAccount,
204 TRUE
205 );
206 $this->addSelect('payment_instrument_id',
207 array(
208 'entity' => 'contribution',
209 'label' => ts('Payment Method'),
210 'placeholder' => NULL,
211 )
212 );
213
214 // is this processor active ?
215 $this->add('checkbox', 'is_active', ts('Is this Payment Processor active?'));
216 $this->add('checkbox', 'is_default', ts('Is this Payment Processor the default?'));
217 $creditCardTypes = CRM_Contribute_PseudoConstant::creditCard();
218 $this->addCheckBox('accept_credit_cards', ts('Accepted Credit Card Type(s)'),
219 $creditCardTypes, NULL, NULL, NULL, NULL, '&nbsp;&nbsp;&nbsp;');
220 foreach ($this->_fields as $field) {
221 if (empty($field['label'])) {
222 continue;
223 }
224
225 $this->addField($field['name'], array('label' => $field['label']));
226
227 $fieldSpec = civicrm_api3($this->getDefaultEntity(), 'getfield', array(
228 'name' => $field['name'],
229 'action' => 'create',
230 ));
231 $this->add($fieldSpec['values']['html']['type'], "test_{$field['name']}",
232 $field['label'], $attributes[$field['name']]
233 );
234 if (!empty($field['rule'])) {
235 $this->addRule($field['name'], $field['msg'], $field['rule']);
236 $this->addRule("test_{$field['name']}", $field['msg'], $field['rule']);
237 }
238 }
239
240 $this->addFormRule(array('CRM_Admin_Form_PaymentProcessor', 'formRule'));
241 }
242
243 /**
244 * @param $fields
245 *
246 * @return array|bool
247 */
248 public static function formRule($fields) {
249
250 // make sure that at least one of live or test is present
251 // and we have at least name and url_site
252 // would be good to make this processor specific
253 $errors = array();
254
255 if (!(self::checkSection($fields, $errors) ||
256 self::checkSection($fields, $errors, 'test')
257 )
258 ) {
259 $errors['_qf_default'] = ts('You must have at least the test or live section filled');
260 }
261
262 if (!empty($errors)) {
263 return $errors;
264 }
265
266 return empty($errors) ? TRUE : $errors;
267 }
268
269 /**
270 * @param $fields
271 * @param $errors
272 * @param null $section
273 *
274 * @return bool
275 */
276 public static function checkSection(&$fields, &$errors, $section = NULL) {
277 $names = array('user_name');
278
279 $present = FALSE;
280 $allPresent = TRUE;
281 foreach ($names as $name) {
282 if ($section) {
283 $name = "{$section}_$name";
284 }
285 if (!empty($fields[$name])) {
286 $present = TRUE;
287 }
288 else {
289 $allPresent = FALSE;
290 }
291 }
292
293 if ($present) {
294 if (!$allPresent) {
295 $errors['_qf_default'] = ts('You must have at least the user_name specified');
296 }
297 }
298 return $present;
299 }
300
301 /**
302 * @return array
303 */
304 public function setDefaultValues() {
305 $defaults = array();
306
307 if (!$this->_id) {
308 $defaults['is_active'] = $defaults['is_default'] = 1;
309 $defaults['url_site'] = $this->_ppDAO->url_site_default;
310 $defaults['url_api'] = $this->_ppDAO->url_api_default;
311 $defaults['url_recur'] = $this->_ppDAO->url_recur_default;
312 $defaults['url_button'] = $this->_ppDAO->url_button_default;
313 $defaults['test_url_site'] = $this->_ppDAO->url_site_test_default;
314 $defaults['test_url_api'] = $this->_ppDAO->url_api_test_default;
315 $defaults['test_url_recur'] = $this->_ppDAO->url_recur_test_default;
316 $defaults['test_url_button'] = $this->_ppDAO->url_button_test_default;
317 $defaults['payment_instrument_id'] = $this->_ppDAO->payment_instrument_id;
318 // When user changes payment processor type, it is passed in via $this->_ppType so update defaults array.
319 if ($this->_ppType) {
320 $defaults['payment_processor_type_id'] = $this->_ppType;
321 }
322 return $defaults;
323 }
324 $domainID = CRM_Core_Config::domainID();
325
326 $dao = new CRM_Financial_DAO_PaymentProcessor();
327 $dao->id = $this->_id;
328 $dao->domain_id = $domainID;
329 if (!$dao->find(TRUE)) {
330 return $defaults;
331 }
332
333 CRM_Core_DAO::storeValues($dao, $defaults);
334 // When user changes payment processor type, it is passed in via $this->_ppType so update defaults array.
335 if ($this->_ppType) {
336 $defaults['payment_processor_type_id'] = $this->_ppType;
337 }
338 $cards = json_decode(CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessor',
339 $this->_id,
340 'accepted_credit_cards'
341 ), TRUE);
342 $acceptedCards = array();
343 if (!empty($cards)) {
344 foreach ($cards as $card => $val) {
345 $acceptedCards[$card] = 1;
346 }
347 }
348 $defaults['accept_credit_cards'] = $acceptedCards;
349 unset($defaults['accepted_credit_cards']);
350 // now get testID
351 $testDAO = new CRM_Financial_DAO_PaymentProcessor();
352 $testDAO->name = $dao->name;
353 $testDAO->is_test = 1;
354 $testDAO->domain_id = $domainID;
355 if ($testDAO->find(TRUE)) {
356 $this->_testID = $testDAO->id;
357
358 foreach ($this->_fields as $field) {
359 $testName = "test_{$field['name']}";
360 $defaults[$testName] = $testDAO->{$field['name']};
361 }
362 }
363 $defaults['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($dao->id, NULL, 'civicrm_payment_processor');
364
365 return $defaults;
366 }
367
368 /**
369 * Process the form submission.
370 */
371 public function postProcess() {
372
373 if ($this->_action & CRM_Core_Action::DELETE) {
374 CRM_Financial_BAO_PaymentProcessor::del($this->_id);
375 CRM_Core_Session::setStatus("", ts('Payment Processor Deleted.'), "success");
376 return NULL;
377 }
378
379 $values = $this->controller->exportValues($this->_name);
380 $domainID = CRM_Core_Config::domainID();
381
382 if (!empty($values['is_default'])) {
383 $query = "UPDATE civicrm_payment_processor SET is_default = 0 WHERE domain_id = $domainID";
384 CRM_Core_DAO::executeQuery($query);
385 }
386
387 $this->updatePaymentProcessor($values, $domainID, FALSE);
388 $this->updatePaymentProcessor($values, $domainID, TRUE);
389
390 $processor = civicrm_api3('payment_processor', 'getsingle', array('name' => $values['name'], 'is_test' => 0));
391 $errors = Civi\Payment\System::singleton()->checkProcessorConfig($processor);
392 if ($errors) {
393 CRM_Core_Session::setStatus($errors, 'Payment processor configuration invalid', 'error');
394 Civi::log()->error('Payment processor configuration invalid: ' . $errors);
395 CRM_Core_Session::singleton()->pushUserContext($this->refreshURL);
396 }
397 else {
398 CRM_Core_Session::setStatus(ts('Payment processor %1 has been saved.', array(1 => "<em>{$values['name']}</em>")), ts('Saved'), 'success');
399 }
400 }
401
402 /**
403 * Save a payment processor.
404 *
405 * @param array $values
406 * @param int $domainID
407 * @param bool $test
408 */
409 public function updatePaymentProcessor(&$values, $domainID, $test) {
410 if ($test) {
411 foreach (array('user_name', 'password', 'signature', 'url_site', 'url_recur', 'url_api', 'url_button', 'subject') as $field) {
412 $values[$field] = empty($values["test_{$field}"]) ? CRM_Utils_Array::value($field, $values) : $values["test_{$field}"];
413 }
414 }
415 if (!empty($values['accept_credit_cards'])) {
416 $creditCards = array();
417 $accptedCards = array_keys($values['accept_credit_cards']);
418 $creditCardTypes = CRM_Contribute_PseudoConstant::creditCard();
419 foreach ($creditCardTypes as $type => $val) {
420 if (in_array($type, $accptedCards)) {
421 $creditCards[$type] = $creditCardTypes[$type];
422 }
423 }
424 $creditCards = json_encode($creditCards);
425 }
426 else {
427 $creditCards = "NULL";
428 }
429 $params = array_merge(array(
430 'id' => $test ? $this->_testID : $this->_id,
431 'domain_id' => $domainID,
432 'is_test' => $test,
433 'is_active' => 0,
434 'is_default' => 0,
435 'is_recur' => $this->_ppDAO->is_recur,
436 'billing_mode' => $this->_ppDAO->billing_mode,
437 'class_name' => $this->_ppDAO->class_name,
438 'payment_type' => $this->_ppDAO->payment_type,
439 'payment_instrument_id' => $this->_ppDAO->payment_instrument_id,
440 'financial_account_id' => $values['financial_account_id'],
441 'accepted_credit_cards' => $creditCards,
442 ), $values);
443
444 civicrm_api3('PaymentProcessor', 'create', $params);
445 }
446
447 }