For discussion -- Stripe integration
Summary: various stripe stuff, including - external stripe library - payment form - test controller to play with payment form, sample business logic My main questions / discussion topics are... - is the stripe PHP library too big? (ie should I write something more simple just for phabricator?) -- if its cool, what is the best way to include the client? (ie should I make it a submodule rather than the flat copy here?) - is the JS I wrote (too) ridiculous? -- particularly unhappy with the error message stuff being in JS *but* it seemed the best choice given the most juicy error messages come from the stripe JS such that the overall code complexity is lowest this way. - how should the stripe JS be included? -- flat copy like I did here? -- some sort of external? -- can we just load it off stripe servers at request time? (I like that from the "if stripe is down, stripe is down" perspective) - wasn't sure if the date control was too silly and should just be baked into the form? -- for some reason I feel like its good to be prepared to walk away from Stripe / switch providers here, though I think this is on the wrong side of pragmatic Test Plan: - played around with sample client form Reviewers: epriestley Reviewed By: epriestley CC: aran Differential Revision: https://secure.phabricator.com/D2096
This commit is contained in:
@@ -993,6 +993,19 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'disk' => '/rsrc/js/application/repository/repository-crossreference.js',
|
||||
),
|
||||
'javelin-behavior-stripe-payment-form' =>
|
||||
array(
|
||||
'uri' => '/res/b77a4b16/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-json',
|
||||
3 => 'stripe-core',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
|
||||
),
|
||||
'javelin-behavior-view-placeholder' =>
|
||||
array(
|
||||
'uri' => '/res/5b89bdf5/rsrc/js/javelin/ext/view/ViewPlaceholder.js',
|
||||
@@ -2022,6 +2035,24 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'disk' => '/rsrc/js/raphael/g.raphael.line.js',
|
||||
),
|
||||
'stripe-core' =>
|
||||
array(
|
||||
'uri' => '/res/3b0f0ad4/rsrc/js/stripe/stripe_core.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/js/stripe/stripe_core.js',
|
||||
),
|
||||
'stripe-payment-form-css' =>
|
||||
array(
|
||||
'uri' => '/res/e2358ded/rsrc/css/application/phortune/stripe-payment-form.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/phortune/stripe-payment-form.css',
|
||||
),
|
||||
'syntax-highlighting-css' =>
|
||||
array(
|
||||
'uri' => '/res/5669beb6/rsrc/css/core/syntax.css',
|
||||
|
||||
@@ -914,6 +914,10 @@ phutil_register_library_map(array(
|
||||
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
|
||||
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
|
||||
'PhabricatorXHProfProfileView' => 'applications/xhprof/view/base',
|
||||
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/monthyearexpiry',
|
||||
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/base',
|
||||
'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/paymentform',
|
||||
'PhortuneStripeTestPaymentFormController' => 'applications/phortune/stripe/controller/testpaymentform',
|
||||
'PhrictionActionConstants' => 'applications/phriction/constants/action',
|
||||
'PhrictionChangeType' => 'applications/phriction/constants/changetype',
|
||||
'PhrictionConstants' => 'applications/phriction/constants/base',
|
||||
@@ -1712,6 +1716,10 @@ phutil_register_library_map(array(
|
||||
'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView',
|
||||
'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView',
|
||||
'PhabricatorXHProfProfileView' => 'AphrontView',
|
||||
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
|
||||
'PhortuneStripeBaseController' => 'PhabricatorController',
|
||||
'PhortuneStripePaymentFormView' => 'AphrontView',
|
||||
'PhortuneStripeTestPaymentFormController' => 'PhortuneStripeBaseController',
|
||||
'PhrictionActionConstants' => 'PhrictionConstants',
|
||||
'PhrictionChangeType' => 'PhrictionConstants',
|
||||
'PhrictionContent' => 'PhrictionDAO',
|
||||
|
||||
@@ -412,6 +412,12 @@ class AphrontDefaultApplicationConfiguration
|
||||
'edit/(?P<phid>[^/]+)/' => 'PhabricatorFlagEditController',
|
||||
'delete/(?P<id>\d+)/' => 'PhabricatorFlagDeleteController',
|
||||
),
|
||||
|
||||
'/phortune/' => array(
|
||||
'stripe/' => array(
|
||||
'testpaymentform/' => 'PhortuneStripeTestPaymentFormController',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhortuneMonthYearExpiryControl extends AphrontFormControl {
|
||||
private $user;
|
||||
private $monthValue;
|
||||
private $yearValue;
|
||||
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
private function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setMonthInputValue($value) {
|
||||
$this->monthValue = $value;
|
||||
return $this;
|
||||
}
|
||||
private function getMonthInputValue() {
|
||||
return $this->monthValue;
|
||||
}
|
||||
private function getCurrentMonth() {
|
||||
return phabricator_format_local_time(
|
||||
time(),
|
||||
$this->getUser(),
|
||||
'm');
|
||||
}
|
||||
|
||||
public function setYearInputValue($value) {
|
||||
$this->yearValue = $value;
|
||||
return $this;
|
||||
}
|
||||
private function getYearInputValue() {
|
||||
return $this->yearValue;
|
||||
}
|
||||
private function getCurrentYear() {
|
||||
return phabricator_format_local_time(
|
||||
time(),
|
||||
$this->getUser(),
|
||||
'Y');
|
||||
}
|
||||
|
||||
protected function getCustomControlClass() {
|
||||
return 'aphront-form-control-text';
|
||||
}
|
||||
|
||||
protected function renderInput() {
|
||||
if (!$this->getUser()) {
|
||||
throw new Exception('You must setUser() before render()!');
|
||||
}
|
||||
|
||||
// represent months like a credit card does
|
||||
$months = array(
|
||||
'01' => '01',
|
||||
'02' => '02',
|
||||
'03' => '03',
|
||||
'04' => '04',
|
||||
'05' => '05',
|
||||
'06' => '06',
|
||||
'07' => '07',
|
||||
'08' => '08',
|
||||
'09' => '09',
|
||||
'10' => '10',
|
||||
'11' => '11',
|
||||
'12' => '12',
|
||||
);
|
||||
|
||||
$current_year = $this->getCurrentYear();
|
||||
$years = range($current_year, $current_year + 20);
|
||||
$years = array_combine($years, $years);
|
||||
|
||||
if ($this->getMonthInputValue()) {
|
||||
$selected_month = $this->getMonthInputValue();
|
||||
} else {
|
||||
$selected_month = $this->getCurrentMonth();
|
||||
}
|
||||
$months_sel = AphrontFormSelectControl::renderSelectTag(
|
||||
$selected_month,
|
||||
$months,
|
||||
array(
|
||||
'sigil' => 'month-input',
|
||||
));
|
||||
|
||||
$years_sel = AphrontFormSelectControl::renderSelectTag(
|
||||
$this->getYearInputValue(),
|
||||
$years,
|
||||
array(
|
||||
'sigil' => 'year-input',
|
||||
));
|
||||
|
||||
return self::renderSingleView(
|
||||
array(
|
||||
$months_sel,
|
||||
$years_sel
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/select');
|
||||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
||||
|
||||
phutil_require_source('PhortuneMonthYearExpiryControl.php');
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhortuneStripeBaseController extends PhabricatorController {
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
$page = $this->buildStandardPageView();
|
||||
|
||||
$page->setApplicationName('Phortune - Stripe');
|
||||
$page->setBaseURI('/phortune/stripe/');
|
||||
$page->setTitle(idx($data, 'title'));
|
||||
$page->appendChild($view);
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
return $response->setContent($page->render());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhortuneStripeBaseController.php');
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhortuneStripeTestPaymentFormController
|
||||
extends PhortuneStripeBaseController {
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$title = 'Test Payment Form';
|
||||
$error_view = null;
|
||||
$card_number_error = null;
|
||||
$card_cvc_error = null;
|
||||
$card_expiration_error = null;
|
||||
$stripe_key = $request->getStr('stripeKey');
|
||||
if (!$stripe_key) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle('Missing stripeKey parameter in URI');
|
||||
}
|
||||
|
||||
if (!$error_view && $request->isFormPost()) {
|
||||
$card_errors = $request->getStr('cardErrors');
|
||||
$stripe_token = $request->getStr('stripeToken');
|
||||
if ($card_errors) {
|
||||
$raw_errors = json_decode($card_errors);
|
||||
list($card_number_error,
|
||||
$card_cvc_error,
|
||||
$card_expiration_error,
|
||||
$messages) = $this->parseRawErrors($raw_errors);
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle('There were errors processing your card.')
|
||||
->setErrors($messages);
|
||||
} else if (!$stripe_token) {
|
||||
// this shouldn't happen, so show the user a very generic error
|
||||
// message and log that this error occurred...!
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle('There was an unknown error processing your card.')
|
||||
->setErrors(array('Please try again.'));
|
||||
$error = 'payment form submitted but no stripe token and no errors';
|
||||
$this->logStripeError($error);
|
||||
} else {
|
||||
// success -- do something with $stripe_token!!
|
||||
}
|
||||
} else if (!$error_view) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||
->setTitle(
|
||||
'If you are using a test stripe key, use 4242424242424242, '.
|
||||
'any three digits for CVC, and any valid expiration date to '.
|
||||
'test!');
|
||||
}
|
||||
|
||||
$view = id(new AphrontPanelView())
|
||||
->setWidth(AphrontPanelView::WIDTH_FORM)
|
||||
->setHeader($title);
|
||||
|
||||
$form = id(new PhortuneStripePaymentFormView())
|
||||
->setUser($user)
|
||||
->setStripeKey($stripe_key)
|
||||
->setCardNumberError($card_number_error)
|
||||
->setCardCVCError($card_cvc_error)
|
||||
->setCardExpirationError($card_expiration_error);
|
||||
|
||||
$view->appendChild($form);
|
||||
|
||||
return
|
||||
$this->buildStandardPageResponse(
|
||||
array(
|
||||
$error_view,
|
||||
$view,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stripe JS and calls to Stripe handle all errors with processing this
|
||||
* form. This function takes the raw errors - in the form of an array
|
||||
* where each elementt is $type => $message - and figures out what if
|
||||
* any fields were invalid and pulls the messages into a flat object.
|
||||
*
|
||||
* See https://stripe.com/docs/api#errors for more information on possible
|
||||
* errors.
|
||||
*/
|
||||
private function parseRawErrors($errors) {
|
||||
$card_number_error = null;
|
||||
$card_cvc_error = null;
|
||||
$card_expiration_error = null;
|
||||
$messages = array();
|
||||
foreach ($errors as $index => $error) {
|
||||
$type = key($error);
|
||||
$msg = reset($error);
|
||||
$messages[] = $msg;
|
||||
switch ($type) {
|
||||
case 'number':
|
||||
case 'invalid_number':
|
||||
case 'incorrect_number':
|
||||
$card_number_error = true;
|
||||
break;
|
||||
case 'cvc':
|
||||
case 'invalid_cvc':
|
||||
case 'incorrect_cvc':
|
||||
$card_cvc_error = true;
|
||||
break;
|
||||
case 'expiry':
|
||||
case 'invalid_expiry_month':
|
||||
case 'invalid_expiry_year':
|
||||
$card_expiration_error = true;
|
||||
break;
|
||||
case 'card_declined':
|
||||
case 'expired_card':
|
||||
case 'duplicate_transaction':
|
||||
case 'processing_error':
|
||||
// these errors don't map well to field(s) being bad
|
||||
break;
|
||||
case 'invalid_amount':
|
||||
case 'missing':
|
||||
default:
|
||||
// these errors only happen if we (not the user) messed up so log it
|
||||
$error = sprintf(
|
||||
'error_type: %s error_message: %s',
|
||||
$type,
|
||||
$msg
|
||||
);
|
||||
$this->logStripeError($error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// append a helpful "fix this" to the messages to be displayed to the user
|
||||
if (count($messages) == 1) {
|
||||
$messages[] = 'Please fix this error and try again.';
|
||||
} else {
|
||||
$messages[] = 'Please fix these errors and try again.';
|
||||
}
|
||||
|
||||
return array(
|
||||
$card_number_error,
|
||||
$card_cvc_error,
|
||||
$card_expiration_error,
|
||||
$messages
|
||||
);
|
||||
}
|
||||
|
||||
private function logStripeError($message) {
|
||||
phlog('STRIPE-ERROR '.$message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/phortune/stripe/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/phortune/stripe/view/paymentform');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'error');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhortuneStripeTestPaymentFormController.php');
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhortuneStripePaymentFormView extends AphrontView {
|
||||
private $user;
|
||||
private $stripeKey;
|
||||
private $cardNumberError;
|
||||
private $cardCVCError;
|
||||
private $cardExpirationError;
|
||||
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
private function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setStripeKey($key) {
|
||||
$this->stripeKey = $key;
|
||||
return $this;
|
||||
}
|
||||
private function getStripeKey() {
|
||||
return $this->stripeKey;
|
||||
}
|
||||
|
||||
public function setCardNumberError($error) {
|
||||
$this->cardNumberError = $error;
|
||||
return $this;
|
||||
}
|
||||
private function getCardNumberError() {
|
||||
return $this->cardNumberError;
|
||||
}
|
||||
|
||||
public function setCardCVCError($error) {
|
||||
$this->cardCVCError = $error;
|
||||
return $this;
|
||||
}
|
||||
private function getCardCVCError() {
|
||||
return $this->cardCVCError;
|
||||
}
|
||||
|
||||
public function setCardExpirationError($error) {
|
||||
$this->cardExpirationError = $error;
|
||||
return $this;
|
||||
}
|
||||
private function getCardExpirationError() {
|
||||
return $this->cardExpirationError;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$form_id = celerity_generate_unique_node_id();
|
||||
require_celerity_resource('stripe-payment-form-css');
|
||||
require_celerity_resource('aphront-tooltip-css');
|
||||
Javelin::initBehavior('phabricator-tooltips');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setID($form_id)
|
||||
->setUser($this->getUser())
|
||||
->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setLabel('')
|
||||
->setValue(
|
||||
javelin_render_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'credit-card-logos',
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => 'We support Visa, Mastercard, American Express, '.
|
||||
'Discover, JCB, and Diners Club.',
|
||||
'size' => 440,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Card Number')
|
||||
->setDisableAutocomplete(true)
|
||||
->setSigil('number-input')
|
||||
->setError($this->getCardNumberError())
|
||||
)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('CVC')
|
||||
->setDisableAutocomplete(true)
|
||||
->setSigil('cvc-input')
|
||||
->setError($this->getCardCVCError())
|
||||
)
|
||||
->appendChild(
|
||||
id(new PhortuneMonthYearExpiryControl())
|
||||
->setLabel('Expiration')
|
||||
->setUser($this->getUser())
|
||||
->setError($this->getCardExpirationError())
|
||||
)
|
||||
->appendChild(
|
||||
javelin_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'hidden' => true,
|
||||
'name' => 'stripeToken',
|
||||
'sigil' => 'stripe-token-input',
|
||||
)
|
||||
)
|
||||
)
|
||||
->appendChild(
|
||||
javelin_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'hidden' => true,
|
||||
'name' => 'cardErrors',
|
||||
'sigil' => 'card-errors-input'
|
||||
)
|
||||
)
|
||||
)
|
||||
->appendChild(
|
||||
phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'hidden' => true,
|
||||
'name' => 'stripeKey',
|
||||
'value' => $this->getStripeKey(),
|
||||
)
|
||||
)
|
||||
)
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Submit Payment')
|
||||
);
|
||||
|
||||
Javelin::initBehavior(
|
||||
'stripe-payment-form',
|
||||
array(
|
||||
'stripePublishKey' => $this->getStripeKey(),
|
||||
'root' => $form_id,
|
||||
)
|
||||
);
|
||||
|
||||
return $form->render();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/phortune/control/monthyearexpiry');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/markup');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/control/text');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhortuneStripePaymentFormView.php');
|
||||
@@ -18,19 +18,39 @@
|
||||
|
||||
final class AphrontFormTextControl extends AphrontFormControl {
|
||||
|
||||
private $disableAutocomplete;
|
||||
private $sigil;
|
||||
|
||||
public function setDisableAutocomplete($disable) {
|
||||
$this->disableAutocomplete = $disable;
|
||||
return $this;
|
||||
}
|
||||
private function getDisableAutocomplete() {
|
||||
return $this->disableAutocomplete;
|
||||
}
|
||||
public function getSigil() {
|
||||
return $this->sigil;
|
||||
}
|
||||
public function setSigil($sigil) {
|
||||
$this->sigil = $sigil;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getCustomControlClass() {
|
||||
return 'aphront-form-control-text';
|
||||
}
|
||||
|
||||
protected function renderInput() {
|
||||
return phutil_render_tag(
|
||||
return javelin_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'text',
|
||||
'name' => $this->getName(),
|
||||
'value' => $this->getValue(),
|
||||
'disabled' => $this->getDisabled() ? 'disabled' : null,
|
||||
'id' => $this->getID(),
|
||||
'type' => 'text',
|
||||
'name' => $this->getName(),
|
||||
'value' => $this->getValue(),
|
||||
'disabled' => $this->getDisabled() ? 'disabled' : null,
|
||||
'autocomplete' => $this->getDisableAutocomplete() ? 'off' : null,
|
||||
'id' => $this->getID(),
|
||||
'sigil' => $this->getSigil(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/form/control/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('AphrontFormTextControl.php');
|
||||
|
||||
Reference in New Issue
Block a user