https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103512
Revision: 103512
Author: khorn
Date: 2011-11-17 21:54:41 +0000 (Thu, 17 Nov 2011)
Log Message:
-----------
MFT r103506, r103501, r103499, r103491, r103416, r103385, r103288, r103246,
r103076, r103024
Modified Paths:
--------------
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphans.php
Added Paths:
-----------
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphanlogs/
Copied:
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php
(from rev 103246,
trunk/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php)
===================================================================
---
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php
(rev 0)
+++
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php
2011-11-17 21:54:41 UTC (rev 103512)
@@ -0,0 +1,205 @@
+<?php
+
+class GlobalCollectOrphanAdapter extends GlobalCollectAdapter {
+
+ //Data we know to be good, that we always want to re-assert after a
load or an addData.
+ //so far: order_id, i_order_id, and the utm data we pull from
contribution tracking.
+ protected $hard_data = array();
+
+ public function unstage_data( $data = array(), $final = true ){
+ $unstaged = array();
+ foreach ( $data as $key=>$val ){
+ if (is_array($val)){
+ $unstaged += $this->unstage_data( $val, false );
+ } else {
+ if (array_key_exists($key, $this->var_map)){
+ //run the unstage data functions.
+ $unstaged[$this->var_map[$key]] = $val;
+ //this would be EXTREMELY bad to put in
the regular adapter.
+
$this->staged_data[$this->var_map[$key]] = $val;
+ } else {
+ //$unstaged[$key] = $val;
+ }
+ }
+ }
+ if ($final){
+ $this->stageData('response');
+ }
+ foreach ($unstaged as $key=>$val){
+ $unstaged[$key] = $this->staged_data[$key];
+ }
+ return $unstaged;
+ }
+
+ public function loadDataAndReInit( $data ){
+ $this->batch = true; //or the hooks will accumulate badness.
+
+ //re-init all these arrays, because this is a batch thing.
+ $this->hard_data = array();
+ $this->transaction_results = array();
+ $this->raw_data = array();
+ $this->staged_data = array();
+
+ $this->hard_data['order_id'] = $data['order_id'];
+ $this->hard_data['i_order_id'] = $data['order_id'];
+
+ $this->dataObj = new DonationData( get_called_class(), false,
$data );
+
+ $this->raw_data = $this->dataObj->getData();
+
+ $this->hard_data = array_merge( $this->hard_data,
$this->getUTMInfoFromDB() );
+ $this->reAddHardData();
+
+ $this->staged_data = $this->raw_data;
+
+ $this->setPostDefaults();
+ $this->defineTransactions();
+ $this->defineErrorMap();
+ $this->defineVarMap();
+ $this->defineDataConstraints();
+ $this->defineAccountInfo();
+ $this->defineReturnValueMap();
+
+ $this->stageData();
+
+ //have to do this again here.
+ $this->reAddHardData();
+ }
+
+ public function addData($dataArray){
+ parent::addData($dataArray);
+ $this->reAddHardData();
+ }
+
+ private function reAddHardData(){
+ //anywhere else, and this would constitute abuse of the system.
+ //so don't do it.
+ foreach ($this->hard_data as $key => $val){
+ $this->raw_data[$key] = $val;
+ $this->staged_data[$key] = $val;
+ }
+ }
+
+ public function do_transaction($transaction){
+ switch ($transaction){
+ case 'SET_PAYMENT':
+ case 'CANCEL_PAYMENT':
+
self::log($this->getData_Raw('contribution_tracking_id') . ": CVV: " .
$this->getData_Raw('cvv_result') . ": AVS: " .
$this->getData_Raw('avs_result'));
+ //and then go on, unless you're testing, in
which case:
+// return "NOPE";
+// break;
+ default:
+ return parent::do_transaction($transaction);
+ break;
+ }
+ }
+
+ public static function log( $msg, $log_level = LOG_INFO, $nothing =
null ) {
+ $identifier = 'orphans:' . self::getIdentifier() .
"_gateway_trxn";
+
+ // if we're not using the syslog facility, use wfDebugLog
+ if ( !self::getGlobal( 'UseSyslog' ) ) {
+ wfDebugLog( $identifier, $msg );
+ return;
+ }
+
+ // otherwise, use syslogging
+ openlog( $identifier, LOG_ODELAY, LOG_SYSLOG );
+ syslog( $log_level, $msg );
+ closelog();
+ }
+
+ public function getUTMInfoFromDB(){
+
+ $db =
ContributionTrackingProcessor::contributionTrackingConnection();
+
+ if ( !$db ) {
+ die("There is something terribly wrong with your
Contribution Tracking database. fixit.");
+ return null;
+ }
+
+ $ctid = $this->getData_Raw('contribution_tracking_id');
+
+ $data = array();
+
+ // if contrib tracking id is not already set, we need to insert
the data, otherwise update
+ if ( $ctid ) {
+ $res = $db->select( 'contribution_tracking',
+ array(
+ 'utm_source',
+ 'utm_campaign',
+ 'utm_medium',
+ 'ts'
+ ),
+ array('id' => $ctid)
+ );
+ foreach ($res as $thing){
+ $data['utm_source'] = $thing->utm_source;
+ $data['utm_campaign'] = $thing->utm_campaign;
+ $data['utm_medium'] = $thing->utm_medium;
+ $data['ts'] = $thing->ts;
+ $msg = '';
+ foreach ($data as $key => $val){
+ $msg .= "$key = $val ";
+ }
+ $this->log("$ctid: Found UTM Data. $msg");
+ echo $msg;
+ return $data;
+ }
+ }
+
+ //if we got here, we can't find anything else...
+ $this->log("$ctid: FAILED to find UTM Source value. Using
default.");
+ return $data;
+ }
+
+
+ /**
+ * Copying this here because it's the fastest way to bring in an actual
timestamp.
+ */
+ protected function doStompTransaction() {
+ if ( !$this->getGlobal( 'EnableStomp' ) ){
+ return;
+ }
+ $this->debugarray[] = "Attempting Stomp Transaction!";
+ $hook = '';
+
+ $status = $this->getTransactionWMFStatus();
+ switch ( $status ) {
+ case 'complete':
+ $hook = 'gwStomp';
+ break;
+ case 'pending':
+ case 'pending-poke':
+ $hook = 'gwPendingStomp';
+ break;
+ }
+ if ( $hook === '' ) {
+ $this->debugarray[] = "No Stomp Hook Found for
WMF_Status $status";
+ return;
+ }
+
+
+ if (!is_null($this->getData_Raw('ts'))){
+ $timestamp = strtotime($this->getData_Raw('ts')); //I
hate that this works.
+ } else {
+ $timestamp = time();
+ }
+
+ // send the thing.
+ $transaction = array(
+ 'response' => $this->getTransactionMessage(),
+ 'date' => $timestamp,
+ 'gateway_txn_id' => $this->getTransactionGatewayTxnID(),
+ //'language' => '',
+ );
+ $transaction += $this->getData_Raw();
+
+ try {
+ wfRunHooks( $hook, array( $transaction ) );
+ } catch ( Exception $e ) {
+ self::log( "STOMP ERROR. Could not add message. " .
$e->getMessage() , LOG_CRIT );
+ }
+ }
+
+}
\ No newline at end of file
Property changes on:
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphanlogs
___________________________________________________________________
Added: svn:ignore
+ globalcollect.2
globalcollect.1
globalcollect
globalcollect.6
globalcollect.5
globalcollect.4
2011-11-11:17:59:48-globalcollect
order_ids.txt
globalcollect.3
globalcollect.7
Modified:
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphans.php
===================================================================
---
trunk/extensions/DonationInterface/globalcollect_gateway/scripts/orphans.php
2011-11-14 20:43:15 UTC (rev 103024)
+++
branches/fundraising/deployment/payments_1.17/extensions/DonationInterface/globalcollect_gateway/scripts/orphans.php
2011-11-17 21:54:41 UTC (rev 103512)
@@ -1,4 +1,6 @@
<?php
+//If you want to use this script, you will have to add the following line to
LocalSettings.php:
+//$wgAutoloadClasses['GlobalCollectOrphanAdapter'] = $IP .
'/extensions/DonationInterface/globalcollect_gateway/scripts/orphan_adapter.php';
//TODO: Something that is not specific to anybody's install, here.
global $IP;
@@ -8,26 +10,226 @@
require_once( "$IP/maintenance/Maintenance.php" );
class GlobalCollectOrphanRectifier extends Maintenance {
+
+ protected $killfiles = array();
+ protected $order_ids = array();
+ protected $max_per_execute = 3;
+
+
function execute(){
-
- //load in and chunk the list of XML. Phase 1: From a file
- //for each chunk, load it into a GC adapter, and have it parse
as if it were a response.
+ $order_ids = file('orphanlogs/order_ids.txt',
FILE_SKIP_EMPTY_LINES);
+ foreach ($order_ids as $key=>$val){
+ $order_ids[$key] = trim($val);
+ }
+ foreach ($order_ids as $id){
+ $this->order_ids[$id] = $id; //easier to unset this
way.
+ }
+ $outstanding_count = count($this->order_ids);
+ echo "Order ID count: " . $outstanding_count . "\n";
- //load that response into DonationData, and run the thing that
completes the transaction,
- //as if we were coming from resultSwitcher.
- //(Note: This should only work if we're sitting at one of the
designated statuses)
+ $files = $this->getAllLogFileNames();
+ $payments = array();
+ foreach ($files as $file){
+ if (count($payments) < $this->max_per_execute){
+ $file_array = $this->getLogfileLines( $file );
+ $payments =
array_merge($this->findTransactionLines($file_array), $payments);
+ if (count($payments) === 0){
+ $this->killfiles[] = $file;
+ echo print_r($this->killfiles, true);
+ }
+ }
+ }
$data = array(
- 'test' => 'something',
- 'othertest' => 'otherthing'
+ 'wheeee' => 'yes'
);
- $adapter = new GlobalCollectAdapter(array('external_data' =>
$data));
+ $adapter = new GlobalCollectOrphanAdapter(array('external_data'
=> $data));
+ $adapter->setCurrentTransaction('INSERT_ORDERWITHPAYMENT');
+ $var_map = $adapter->defineVarMap();
+
+ $xml = new DomDocument;
+
+ //fields that have generated notices if they're not there.
+ $additional_fields = array(
+ 'card_num',
+ 'comment',
+ 'size',
+ 'utm_medium',
+ 'utm_campaign',
+ 'referrer',
+ 'mname',
+ 'fname2',
+ 'lname2',
+ 'street2',
+ 'city2',
+ 'state2',
+ 'country2',
+ 'zip2',
+ );
+
+
+ foreach ($payments as $key => $payment_data){
+ $xml->loadXML($payment_data['xml']);
+ $parsed = $adapter->getResponseData($xml);
+ $payments[$key]['parsed'] = $parsed;
+ $payments[$key]['unstaged'] =
$adapter->unstage_data($parsed);
+ $payments[$key]['unstaged']['contribution_tracking_id']
= $payments[$key]['contribution_tracking_id'];
+ $payments[$key]['unstaged']['i_order_id'] =
$payments[$key]['unstaged']['order_id'];
+ foreach ($additional_fields as $val){
+ if (!array_key_exists($val,
$payments[$key]['unstaged'])){
+ $payments[$key]['unstaged'][$val] =
null;
+ }
+ }
+ }
+
+ // ADDITIONAL: log out what you did here, to... somewhere.
+ // Preferably *before* you rewrite the Order ID file.
+
+ //we may need to unset some hooks out here. Like... recaptcha.
Makes no sense.
+ $i = 0;
+ foreach($payments as $payment_data){
+ if ($i < $this->max_per_execute){
+ ++$i;
+
$adapter->loadDataAndReInit($payment_data['unstaged']);
+ $results =
$adapter->do_transaction('Confirm_CreditCard');
+ if ($results['status']){
+ $adapter->log(
$payment_data['unstaged']['contribution_tracking_id'] . ": FINAL: " .
$results['action']);
+
unset($this->order_ids[$payment_data['unstaged']['order_id']]);
+ } else {
+ $adapter->log(
$payment_data['unstaged']['contribution_tracking_id'] . ": ERROR: " .
$results['message']);
+ if (strpos($results['message'],
"GET_ORDERSTATUS reports that the payment is already complete.")){
+
unset($this->order_ids[$payment_data['unstaged']['order_id']]);
+ }
+ }
+ echo $results['message'] . "\n";
+ }
+ }
+
+ if ($outstanding_count != count($this->order_ids)){
+ $this->rewriteOrderIds();
+ }
}
+
+ function getAllLogFileNames(){
+ $files = array();
+ if ($handle = opendir(dirname(__FILE__) . '/orphanlogs/')){
+ while ( ($file = readdir($handle)) !== false ){
+ if (trim($file, '.') != '' && $file !=
'order_ids.txt' && $file != '.svn'){
+ $files[] = dirname(__FILE__) .
'/orphanlogs/' . $file;
+ }
+ }
+ }
+ closedir($handle);
+ return $files;
+ }
+
+ function findTransactionLines($file){
+ $lines = array();
+ $orders = array();
+ $contrib_id_finder = array();
+ foreach ($file as $line_no=>$line_data){
+ if (strpos($line_data,
'<XML><REQUEST><ACTION>INSERT_ORDERWITHPAYMENT') === 0){
+ $lines[$line_no] = $line_data;
+ } elseif (strpos($line_data, 'Raw XML Response')){
+ $contrib_id_finder[] = $line_data;
+ } elseif (strpos(trim($line_data), '<ORDERID>') === 0){
+ $contrib_id_finder[] = trim($line_data);
+ }
+ }
+
+ $order_ids = $this->order_ids;
+ foreach ($lines as $line_no=>$line_data){
+ if (count($orders) < $this->max_per_execute){
+ $pos1 = strpos($line_data, '<ORDERID>') + 9;
+ $pos2 = strpos($line_data, '</ORDERID>');
+ if ($pos2 > $pos1){
+ $tmp = substr($line_data, $pos1,
$pos2-$pos1);
+ if (isset($order_ids[$tmp])){
+ $orders[$tmp] =
trim($line_data);
+ unset($order_ids[$tmp]);
+ }
+ }
+ }
+ }
+
+ //reverse the array, so we find the last instance first.
+ $contrib_id_finder = array_reverse($contrib_id_finder);
+ foreach ($orders as $order_id => $xml){
+ $contribution_tracking_id = '';
+ $finder = array_search("<ORDERID>$order_id</ORDERID>",
$contrib_id_finder);
+
+ //now search forward (which is actually backward) to
the "Raw XML" line, so we can get the contribution_tracking_id
+ //TODO: Some kind of (in)sanity check for this. Just
because we've found it one step backward doesn't mean...
+ //...but it's kind of good. For now.
+ $explode_me = false;
+ while (!$explode_me){
+ ++$finder;
+ if (strpos($contrib_id_finder[$finder], "Raw
XML Response")){
+ $explode_me =
$contrib_id_finder[$finder];
+ }
+ }
+ if (strlen($explode_me)){
+ $explode_me = explode(': ', $explode_me);
+ $contribution_tracking_id =
trim($explode_me[1]);
+ $orders[$order_id] = array(
+ 'xml' => $xml,
+ 'contribution_tracking_id' =>
$contribution_tracking_id,
+ );
+ }
+ }
+
+ return $orders;
+ }
+
+ function rewriteOrderIds() {
+ $file = fopen('orphanlogs/order_ids.txt', 'w');
+ $outstanding_orders = implode("\n", $this->order_ids);
+ fwrite($file, $outstanding_orders);
+ fclose($file);
+ }
+
+ function getLogfileLines( $file ){
+ $array = array(); //surprise!
+ $array = file($file, FILE_SKIP_EMPTY_LINES);
+ //now, check about 50 lines to make sure we're not seeing any
of that #012, #015 crap.
+ $checkcount = 50;
+ if (count($array) < $checkcount){
+ $checkcount = count($array);
+ }
+ $convert = false;
+ for ($i=0; $i<$checkcount; ++$i){
+ if( strpos($array[$i], '#012') || strpos($array[$i],
'#015') ){
+ $convert = true;
+ break;
+ }
+ }
+ if ($convert) {
+ $array2 = array();
+ foreach ($array as $line){
+ if (strpos($line, '#012')){
+ $line = str_replace('#012', "\n",
$line);
+ }
+ if (strpos($line, '#015') ){
+ $line = str_replace('#015', "\r",
$line);
+ }
+ $array2[] = $line;
+ }
+ $newfile = implode("\n", $array2);
+
+ $handle = fopen($file, 'w');
+ fwrite($handle, $newfile);
+ fclose($handle);
+ $array = file($file, FILE_SKIP_EMPTY_LINES);
+ }
+
+ return $array;
+ }
+
}
+$maintClass = "GlobalCollectOrphanRectifier";
+require_once( "$IP/maintenance/doMaintenance.php" );
-$maintClass = "GlobalCollectOrphanRectifier";
-require_once( "$IP/maintenance/doMaintenance.php" );
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs