r99589 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99588‎ | r99589 | r99590 >
Date:22:21, 11 October 2011
Author:khorn
Status:ok (Comments)
Tags:fundraising 
Comment:
Prevents us from dying (no, really).
Instead, throws more helpful exceptions and halts the transaction process inside a payment gateway.
During the course of implementing the exceptions, it became necessary to clean up some parts of the code that deal with setting the transaction type.
r95923
Modified paths:
  • /branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php (modified) (history)

Diff [purge]

Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php
@@ -29,7 +29,7 @@
3030 $wgOut->addExtensionStyle(
3131 $wgExtensionAssetsPath . '/DonationInterface/gateway_forms/css/gateway.css?284' .
3232 $CSSVersion );
33 -
 33+
3434 // Hide unneeded interface elements
3535 $wgOut->addModules( 'donationInterface.skinOverride' );
3636
@@ -73,10 +73,7 @@
7474 * will be set as the default.
7575 */
7676 $transactionType = false;
77 - $transactionType = 'INSERT_ORDERWITHPAYMENT';
78 - $data['transaction_type'] = (isset( $data['transaction_type'] ) && !empty( $data['transaction_type'] ) ) ? $data['transaction_type'] : $transactionType;
79 - $this->adapter->setTransactionType( $data['transaction_type'] );
80 - unset( $transactionType );
 77+ $transactionType = ( isset( $data['transaction_type'] ) && !empty( $data['transaction_type'] ) ) ? $data['transaction_type'] : 'INSERT_ORDERWITHPAYMENT';
8178
8279 $this->adapter->log( '$transactionType: Default is set to: INSERT_ORDERWITHPAYMENT, this is a temporary hack for backwards compatibility.' );
8380 $this->adapter->log( 'Setting transaction type: ' . ( string ) $data['transaction_type'] );
@@ -91,7 +88,7 @@
9289 // Check form for errors
9390
9491 $options = array( );
95 - switch ( $this->adapter->getTransactionType() ) {
 92+ switch ( $transactionType ) {
9693
9794 case 'BANK_TRANSFER':
9895 $options['creditCard'] = false;
@@ -116,7 +113,7 @@
117114 } else { // The submitted form data is valid, so process it
118115 // allow any external validators to have their way with the data
119116 // Execute the proper transaction code:
120 - switch ( $this->adapter->getTransactionType() ) {
 117+ switch ( $transactionType ) {
121118
122119 case 'BANK_TRANSFER':
123120 $this->executeBankTransfer();
@@ -128,7 +125,7 @@
129126
130127 default:
131128
132 - $message = 'The transaction type [ ' . $this->adapter->getTransactionType() . ' ] was not found.';
 129+ $message = 'The transaction type [ ' . $transactionType . ' ] was not found.';
133130 throw new Exception( $message );
134131 }
135132
@@ -174,7 +171,7 @@
175172 public function executeInsertOrderWithPayment() {
176173
177174 global $wgOut;
178 -
 175+
179176 $result = $this->adapter->do_transaction( 'INSERT_ORDERWITHPAYMENT' );
180177 $this->adapter->addDonorDataToSession();
181178 //$result = $this->adapter->do_transaction( 'TEST_CONNECTION' );
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php
@@ -316,21 +316,6 @@
317317 'returnto',
318318 'order_id', //This may or may not oughta-be-here...
319319 );
320 -
321 - switch ( $this->getTransactionType() ) {
322 -
323 - case 'BANK_TRANSFER':
324 - break;
325 -
326 - case 'INSERT_ORDERWITHPAYMENT':
327 - $this->staged_vars[] = 'card_type';
328 - $this->staged_vars[] = 'card_num';
329 - break;
330 -
331 - default:
332 - $this->staged_vars[] = 'card_type';
333 - $this->staged_vars[] = 'card_num';
334 - }
335320 }
336321
337322 protected function stage_amount( $type = 'request' ) {
@@ -357,7 +342,7 @@
358343 $types = array_flip( $types );
359344 }
360345
361 - if ( array_key_exists( $this->postdata['card_type'], $types ) ) {
 346+ if ( ( array_key_exists( 'card_type', $this->postdata ) ) && array_key_exists( $this->postdata['card_type'], $types ) ) {
362347 $this->postdata['card_type'] = $types[$this->postdata['card_type']];
363348 } else {
364349 //$this->postdata['card_type'] = '';
@@ -367,7 +352,9 @@
368353
369354 protected function stage_card_num( $type = 'request' ) {
370355 //I realize that the $type isn't used. Voodoo.
371 - $this->postdata['card_num'] = str_replace( ' ', '', $this->postdata['card_num'] );
 356+ if ( array_key_exists( 'card_num', $this->postdata ) ) {
 357+ $this->postdata['card_num'] = str_replace( ' ', '', $this->postdata['card_num'] );
 358+ }
372359 }
373360
374361 protected function stage_returnto( $type = 'request' ) {
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php
@@ -1,4 +1,5 @@
22 <?php
 3+
34 /**
45 * Wikimedia Foundation
56 *
@@ -121,8 +122,7 @@
122123 *
123124 * @var array $staged_vars
124125 */
125 - protected $staged_vars = array();
126 -
 126+ protected $staged_vars = array( );
127127 protected $return_value_map;
128128 protected $postdata;
129129 protected $postdatadefaults;
@@ -149,23 +149,18 @@
150150 *
151151 * @see DonationData
152152 */
153 - public function __construct( $options = array() ) {
 153+ public function __construct( $options = array( ) ) {
154154 global $wgRequest;
155155
156156 // Extract the options
157157 extract( $options );
158 -
 158+
159159 $testData = isset( $testData ) ? $testData : false;
160160 $postDefaults = isset( $postDefaults ) ? $postDefaults : false;
161 - $transactionType = isset( $transactionType ) ? $transactionType : false;
162 -
163 - if ( $transactionType ) {
164 - $this->setTransactionType( $transactionType );
165 - }
166 -
 161+
167162 if ( !self::getGlobal( 'Test' ) ) {
168163 $this->url = self::getGlobal( 'URL' );
169 -
 164+
170165 // Only submit test data if we are in test mode.
171166 $testData = false;
172167 } else {
@@ -176,6 +171,7 @@
177172
178173 $this->postdata = $this->dataObj->getData();
179174 //TODO: Fix this a bit.
 175+
180176 $this->posted = $wgRequest->wasPosted();
181177
182178 $this->setPostDefaults( $postDefaults );
@@ -184,6 +180,11 @@
185181 $this->defineAccountInfo();
186182 $this->defineReturnValueMap();
187183
 184+ //Don't bother setting the transaction type if it's not something.
 185+ if ( $this->dataObj->isSomething( 'transaction_type' ) ) {
 186+ $this->currentTransaction( $this->postdata['transaction_type'] );
 187+ }
 188+
188189 $this->displaydata = $this->postdata;
189190 $this->stageData();
190191 }
@@ -191,15 +192,15 @@
192193 /**
193194 * Override this in children if you want different defaults.
194195 */
195 - function setPostDefaults( $options = array() ) {
 196+ function setPostDefaults( $options = array( ) ) {
196197
197198 // Extract the options
198 - if ( is_array( $options )) {
 199+ if ( is_array( $options ) ) {
199200 extract( $options );
200201 }
201202
202203 $returnTitle = isset( $returnTitle ) ? $returnTitle : Title::newFromText( 'Special:GlobalCollectGatewayResult' );
203 - $returnTo = isset( $returnTo ) ? $returnTo : $returnTitle->getFullURL();
 204+ $returnTo = isset( $returnTo ) ? $returnTo : $returnTitle->getFullURL();
204205
205206 $this->postdatadefaults = array(
206207 'order_id' => '112358' . rand(),
@@ -279,19 +280,21 @@
280281 if ( !array_key_exists( $varname, $gotten ) ) {
281282 $globalname = self::getGlobalPrefix() . $varname;
282283 global $$globalname;
283 - if ( !isset( $$globalname )) {
 284+ if ( !isset( $$globalname ) ) {
284285 $globalname = "wgDonationInterface" . $varname;
285286 global $$globalname; //set or not. This is fine.
286287 }
287288 $gotten[$varname] = $$globalname;
288289 }
289 - return $gotten[$varname];
 290+ return $gotten[$varname];
290291 }
291292
292293 function getValue( $gateway_field_name, $token = false ) {
293294 if ( empty( $this->transactions ) ) {
294295 //TODO: These dies should all throw exceptions or something less completely fatal.
295 - die( 'Transactions structure is empty! Aborting.' );
 296+ $msg = self::getGatewayName() . ': Transactions structure is empty! No transaction can be constructed.';
 297+ self::log( $msg, LOG_CRIT );
 298+ throw new MWException( $msg );
296299 }
297300 //How do we determine the value of a field asked for in a particular transaction?
298301 $transaction = $this->currentTransaction();
@@ -329,8 +332,9 @@
330333
331334 //not in the map, or hard coded. What then?
332335 //Complain furiously, for your code is faulty.
333 - //TODO: Something that plays nice with others, instead of...
334 - die( "getValue found NOTHING for $gateway_field_name, $transaction." );
 336+ $msg = self::getGatewayName() . ': Requested value ' . $gateway_field_name . ' cannot be found in the transactions structure.';
 337+ self::log( $msg, LOG_CRIT );
 338+ throw new MWException( $msg );
335339 }
336340
337341 function buildRequestNameValueString() {
@@ -418,52 +422,66 @@
419423 * that maps to a first-level key in the $transactions array.
420424 */
421425 function do_transaction( $transaction ) {
422 - $this->currentTransaction( $transaction );
423 - //update the contribution tracking data
424 - $this->incrementNumAttempt();
 426+ try {
 427+ $this->currentTransaction( $transaction );
 428+ //update the contribution tracking data
 429+ $this->incrementNumAttempt();
425430
426 - //if we're supposed to add the donor data to the session, do that.
427 - if ( $this->transaction_option( 'addDonorDataToSession' ) ) {
428 - $this->addDonorDataToSession();
429 - }
 431+ //if we're supposed to add the donor data to the session, do that.
 432+ if ( $this->transaction_option( 'addDonorDataToSession' ) ) {
 433+ $this->addDonorDataToSession();
 434+ }
430435
431 - $this->runPreProcess(); //many hooks get fired here...
432 - //TODO: Uhmmm... what if none of the validate hooks are enabled?
433 - //Currently, I think that means the transaction stops here, and that's not quite right.
434 - //...is it?
435 - // if the transaction was NOT flagged for processing by something in runPreProcess()...
436 - if ( $this->action != 'process' ) {
437 - self::log( "Transaction failed pre-process checks." . print_r( $this->getData(), true ) );
 436+ $this->runPreProcess(); //many hooks get fired here...
 437+ //TODO: Uhmmm... what if none of the validate hooks are enabled?
 438+ //Currently, I think that means the transaction stops here, and that's not quite right.
 439+ //...is it?
 440+ // if the transaction was NOT flagged for processing by something in runPreProcess()...
 441+ if ( $this->action != 'process' ) {
 442+ self::log( "Transaction failed pre-process checks." . print_r( $this->getData(), true ) );
 443+ return array(
 444+ 'status' => false,
 445+ //TODO: appropriate messages.
 446+ 'message' => "$transaction : Failed failed pre-process checks. Somebody PLEASE override me!",
 447+ 'errors' => array(
 448+ '1000000' => 'pre-process failed you.' //...stupid code.
 449+ ),
 450+ 'action' => $this->action,
 451+ );
 452+ }
 453+
 454+ // expose a hook for external handling of trxns ready for processing
 455+ if ( $this->transaction_option( 'do_processhooks' ) ) {
 456+ wfRunHooks( 'GatewayProcess', array( &$this ) ); //don't think anybody is using this yet, but you could!
 457+ }
 458+
 459+ $this->dataObj->updateContributionTracking( defined( 'OWA' ) );
 460+
 461+ if ( $this->getCommunicationType() === 'xml' ) {
 462+ $this->getStopwatch( "buildRequestXML" );
 463+ $curlme = $this->buildRequestXML();
 464+ $this->saveCommunicationStats( "buildRequestXML", $transaction );
 465+ }
 466+
 467+ if ( $this->getCommunicationType() === 'namevalue' ) {
 468+ //buildRequestNameValueString()
 469+ $this->getStopwatch( "buildRequestNameValueString" );
 470+ $curlme = $this->buildRequestNameValueString();
 471+ $this->saveCommunicationStats( "buildRequestNameValueString", $transaction );
 472+ }
 473+ } catch ( MWException $e ) {
 474+ self::log( "Malformed gateway definition. Cannot continue: Aborting.", LOG_CRIT );
438475 return array(
439476 'status' => false,
440477 //TODO: appropriate messages.
441 - 'message' => "$transaction : Failed failed pre-process checks. Somebody PLEASE override me!",
 478+ 'message' => "$transaction : Malformed gateway definition. Cannot continue: Aborting.",
442479 'errors' => array(
443 - '1000000' => 'pre-process failed you.' //...stupid code.
 480+ '1000000' => 'Faulty Code! Bad programmer. Bad!' //...please change this.
444481 ),
445482 'action' => $this->action,
446483 );
447484 }
448485
449 - // expose a hook for external handling of trxns ready for processing
450 - if ( $this->transaction_option( 'do_processhooks' ) ) {
451 - wfRunHooks( 'GatewayProcess', array( &$this ) ); //don't think anybody is using this yet, but you could!
452 - }
453 -
454 - $this->dataObj->updateContributionTracking( defined( 'OWA' ) );
455 - if ( $this->getCommunicationType() === 'xml' ) {
456 - $this->getStopwatch( "buildRequestXML" );
457 - $curlme = $this->buildRequestXML();
458 - $this->saveCommunicationStats( "buildRequestXML", $transaction );
459 - }
460 -
461 - if ( $this->getCommunicationType() === 'namevalue' ) {
462 - //buildRequestNameValueString()
463 - $this->getStopwatch( "buildRequestNameValueString" );
464 - $curlme = $this->buildRequestNameValueString();
465 - $this->saveCommunicationStats( "buildRequestNameValueString", $transaction );
466 - }
467 -
468486 //start looping here, if we're the sort of transaction that needs to do that.
469487 $stopflag = false;
470488 $counter = 0;
@@ -542,7 +560,7 @@
543561
544562 // log that the transaction is essentially complete
545563 self::log( $this->getData( 'order_id' ) . " Transaction complete." );
546 -
 564+
547565 //if we're not actively adding the donor data to the session, kill it.
548566 if ( !$this->transaction_option( 'addDonorDataToSession' ) ) {
549567 $this->unsetAllGatewaySessionData();
@@ -599,6 +617,11 @@
600618 if ( !isset( $current_transaction ) ) {
601619 return false;
602620 }
 621+ if ( empty( $this->transactions ) || !is_array( $this->transactions ) || !array_key_exists( $current_transaction, $this->transactions ) ) {
 622+ $msg = self::getGatewayName() . ': Transactions structure is malformed! ' . $current_transaction . ' transaction cannot be constructed.';
 623+ self::log( $msg, LOG_CRIT );
 624+ throw new MWException( $msg );
 625+ }
603626 return $current_transaction;
604627 }
605628
@@ -793,15 +816,15 @@
794817 */
795818 function saveCommunicationStats( $function = '', $additional = '', $vars = '' ) {
796819 $params = array( );
797 - if ( self::getGlobal( 'SaveCommStats' ) ) {
 820+ if ( self::getGlobal( 'SaveCommStats' ) ) {
798821 $db = ContributionTrackingProcessor::contributionTrackingConnection();
799 -
 822+
800823 //TODO: Actually define this table somewhere in the code, once we
801824 //are reasonably certain we know what we want to see in it.
802 - if ( !( $db->tableExists( 'communication_stats' ) ) ){
 825+ if ( !( $db->tableExists( 'communication_stats' ) ) ) {
803826 return;
804827 }
805 -
 828+
806829 $params['contribution_id'] = $this->dataObj->getVal( 'contribution_tracking_id' );
807830 $params['ts'] = $db->timestamp();
808831 $params['duration'] = $this->getStopwatch( __FUNCTION__ );
@@ -990,32 +1013,6 @@
9911014 return $ret;
9921015 }
9931016
994 - /**
995 - * Get the transaction type
996 - *
997 - * @return string|false
998 - */
999 - public function getTransactionType() {
1000 -
1001 - return $this->transaction_type;
1002 - }
1003 -
1004 - /**
1005 - * Set the transaction type
1006 - *
1007 - * @see GatewayAdapter::currentTransaction()
1008 - *
1009 - * @param string|false $transaction_type
1010 - */
1011 - public function setTransactionType( $transaction_type ) {
1012 -
1013 - $transaction_type = empty( $transaction_type ) ? false : $transaction_type;
1014 -
1015 - $this->transaction_type = $transaction_type;
1016 -
1017 - $this->currentTransaction( $this->transaction_type );
1018 - }
1019 -
10201017 public function getTransactionAllResults() {
10211018 if ( !empty( $this->transaction_results ) && is_array( $this->transaction_results ) ) {
10221019 return $this->transaction_results;

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r95923More refactoring. The new globalcollect gateway is now inheriting from the co...khorn00:43, 1 September 2011

Comments

#Comment by Awjrichards (talk | contribs)   22:17, 21 October 2011

Quibble: I'm not sure LOG_CRIT is the most appropriate log level for these, but I'm definitely open to argument.

#Comment by Khorn (WMF) (talk | contribs)   22:51, 26 October 2011

I talked you out of the quibble this morning.

Status & tagging log