Awight has uploaded a new change for review. https://gerrit.wikimedia.org/r/207029
Change subject: DO NOT MERGE Also use DonationQueue in the orphan slayer ...................................................................... DO NOT MERGE Also use DonationQueue in the orphan slayer this will be squashed with its parent Bug: T92922 Change-Id: I107406d54e5658ea68521b28bb82cf8faa0f91b7 --- M DonationInterface.php M gateway_common/gateway.adapter.php M globalcollect_gateway/scripts/orphan_adapter.php M globalcollect_gateway/scripts/orphans.php A tests/Adapter/GlobalCollect/OrphanRectifierTest.php 5 files changed, 187 insertions(+), 405 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DonationInterface refs/changes/29/207029/1 diff --git a/DonationInterface.php b/DonationInterface.php index 0e15a30..f39ce10 100644 --- a/DonationInterface.php +++ b/DonationInterface.php @@ -134,6 +134,7 @@ $wgAutoloadClasses['GlobalCollectAdapter'] = $donationinterface_dir . 'globalcollect_gateway/globalcollect.adapter.php'; $wgAutoloadClasses['GlobalCollectOrphanAdapter'] = __DIR__ . '/globalcollect_gateway/scripts/orphan_adapter.php'; + $wgAutoloadClasses['GlobalCollectOrphanRectifier'] = __DIR__ . '/globalcollect_gateway/scripts/orphans.php'; } if ( $optionalParts['Amazon'] === true ){ @@ -322,10 +323,7 @@ */ $wgDonationInterfaceOrphanCron = array( 'enable' => true, -// 'override_command_line_params' => true, -// 'function' => 'orphan_stomp', -// 'target_execute_time' => 300, -// 'max_per_execute' => '', + 'target_execute_time' => 180, ); /** diff --git a/gateway_common/gateway.adapter.php b/gateway_common/gateway.adapter.php index 2b7ee0d..f5d65d3 100644 --- a/gateway_common/gateway.adapter.php +++ b/gateway_common/gateway.adapter.php @@ -1894,7 +1894,7 @@ * * TODO: Stop saying "STOMP". */ - protected function getStompTransaction( $antiMessage = false, $recoverTimestamp = false ) { + protected function getStompTransaction( $recoverTimestamp = false ) { $transaction = array( 'gateway_txn_id' => $this->getTransactionGatewayTxnID(), 'payment_method' => $this->getData_Unstaged_Escaped( 'payment_method' ), @@ -1919,19 +1919,19 @@ // in case the transaction already had keys with those values $transaction = array_merge( $stomp_data, $transaction ); - // And now determine the date; which is annoyingly not as easy as one would like it - // if we're attempting to recover some data: ie: we're an orphan - $timestamp = null; - if ( $recoverTimestamp === true ) { - if ( !is_null( $this->getData_Unstaged_Escaped( 'date' ) ) ) { - $timestamp = $this->getData_Unstaged_Escaped( 'date' ); - } elseif ( !is_null( $this->getData_Unstaged_Escaped( 'ts' ) ) ) { - // That this works is mildly surprising - $timestamp = strtotime( $this->getData_Unstaged_Escaped( 'ts' ) ); - } + // And now determine the date; which is annoyingly not as easy as one would like it + // if we're attempting to recover some data: ie: we're an orphan + // FIXME: Can't we make this the default? + $timestamp = null; + if ( $recoverTimestamp === true ) { + if ( !is_null( $this->getData_Unstaged_Escaped( 'date' ) ) ) { + $timestamp = $this->getData_Unstaged_Escaped( 'date' ); + } elseif ( !is_null( $this->getData_Unstaged_Escaped( 'ts' ) ) ) { + // That this works is mildly surprising + $timestamp = strtotime( $this->getData_Unstaged_Escaped( 'ts' ) ); } - $transaction['date'] = ( $timestamp === null ) ? time() : $timestamp; } + $transaction['date'] = ( $timestamp === null ) ? time() : $timestamp; return $transaction; } diff --git a/globalcollect_gateway/scripts/orphan_adapter.php b/globalcollect_gateway/scripts/orphan_adapter.php index d14bbfe..0895ab8 100644 --- a/globalcollect_gateway/scripts/orphan_adapter.php +++ b/globalcollect_gateway/scripts/orphan_adapter.php @@ -150,59 +150,29 @@ } /** - * 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->getFinalStatus(); - switch ( $status ) { - case 'complete': - $hook = 'gwStomp'; - break; - case 'pending': - case 'pending-poke': - $hook = 'gwPendingStomp'; - break; - } - if ( $hook === '' ) { - $this->debugarray[] = "No Stomp Hook Found for FINAL_STATUS $status"; - return; - } - - if ( !is_null( $this->getData_Unstaged_Escaped( 'date' ) ) ) { - $timestamp = $this->getData_Unstaged_Escaped( 'date' ); - } else { - if ( !is_null( $this->getData_Unstaged_Escaped( 'ts' ) ) ) { - $timestamp = strtotime( $this->getData_Unstaged_Escaped( '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_Unstaged_Escaped(); - - try { - WmfFramework::runHooks( $hook, array( $transaction ) ); - } catch ( Exception $e ) { - $this->logger->critical( "STOMP ERROR. Could not add message. " . $e->getMessage() ); - } - } - - /** * Override live adapter with a no-op since orphan doesn't have any new info * before GET_ORDERSTATUS */ protected function pre_process_get_orderstatus() { } + + /** + * Add some extra fields to the wire message + * @see GatewayAdapter::getStompTransaction + */ + protected function getStompTransaction() { + // TODO: Why is the timestamp handled differently only for orphans? + // Rebuild the timestamp if necessary and possible, otherwise use the current time. + if ( !$this->getData_Unstaged_Escaped( 'date' ) ) { + if ( $this->getData_Unstaged_Escaped( 'ts' ) ) { + $timestamp = strtotime( $this->getData_Unstaged_Escaped( 'ts' ) ); //I hate that this works. + } else { + $timestamp = time(); + } + $this->addRequestData( array( + 'date' => $timestamp, + ) ); + } + + $transaction = parent::getStompTransaction(); + } } diff --git a/globalcollect_gateway/scripts/orphans.php b/globalcollect_gateway/scripts/orphans.php index 3e53492..105b9c6 100644 --- a/globalcollect_gateway/scripts/orphans.php +++ b/globalcollect_gateway/scripts/orphans.php @@ -13,14 +13,13 @@ require_once( "$IP/maintenance/Maintenance.php" ); class GlobalCollectOrphanRectifier extends Maintenance { - - protected $killfiles = array(); - protected $order_ids = array(); - protected $max_per_execute = 500; //only really used if you're going by-file. - protected $target_execute_time = 30; //(seconds) - only used by the stomp option. protected $adapter; - - function execute(){ + protected $logger; + protected $handled_ids = array(); + protected $removed_message_count; + protected $start_time; + + public function execute() { //have to turn this off here, until we know it's using the user's ip, and //not 127.0.0.1 during the batch process. global $wgDonationInterfaceEnableIPVelocityFilter; @@ -29,26 +28,8 @@ return; } $wgDonationInterfaceEnableIPVelocityFilter = false; - - $func = 'parse_files'; - if ( $this->getOrphanGlobal( 'override_command_line_params' ) ){ - //do that - $func = $this->getOrphanGlobal( 'function' ); - $this->target_execute_time = $this->getOrphanGlobal( 'target_execute_time' ); - $this->max_per_execute = $this->getOrphanGlobal( 'max_per_execute' ); - } else { - if ( !empty( $_SERVER['argv'][1] ) ){ - if ( $_SERVER['argv'][1] === 'stomp' ){ - $func = 'orphan_stomp'; - if ( !empty( $_SERVER['argv'][2] ) && is_numeric( $_SERVER['argv'][2] ) ){ - $this->target_execute_time = $_SERVER['argv'][2]; - } - } elseif ( is_numeric( $_SERVER['argv'][1] ) ){ - $this->max_per_execute = $_SERVER['argv'][1]; - } - } - } - + + // FIXME: Is this just to trigger batch mode? $data = array( 'wheeee' => 'yes' ); @@ -56,15 +37,10 @@ $this->logger = DonationLoggerFactory::getLogger( $this->adapter ); //Now, actually do the processing. - if ( method_exists( $this, $func ) ) { - $this->{$func}(); - } else { - echo "There's no $func in Orphan Rectifying!\n"; - die(); - } + $this->orphan_stomp(); } - - function orphan_stomp(){ + + protected function orphan_stomp(){ echo "Orphan Stomp\n"; $this->removed_message_count = 0; $this->start_time = time(); @@ -74,25 +50,9 @@ //Then, we go back and pull more... and that same one is in the list again. We should stop after one try per message per execute. //We should also be smart enough to not process things we believe we just deleted. $this->handled_ids = array(); - - //first, we need to... clean up the limbo queue. - - //building in some redundancy here. - $collider_keepGoing = true; - $am_called_count = 0; - while ( $collider_keepGoing ){ - $antimessageCount = $this->handleStompAntiMessages(); - $am_called_count += 1; - if ( $antimessageCount < 10 ){ - $collider_keepGoing = false; - } else { - sleep(2); //two seconds. - } - } - $this->logger->info( 'Removed ' . $this->removed_message_count . ' messages and antimessages.' ); - + if ( $this->keepGoing() ){ - //Pull a batch of CC orphans, keeping in mind that Things May Have Happened in the small slice of time since we handled the antimessages. + //Pull a batch of CC orphans $orphans = $this->getStompOrphans(); while ( count( $orphans ) && $this->keepGoing() ){ echo count( $orphans ) . " orphans left this batch\n"; @@ -100,24 +60,22 @@ foreach ( $orphans as $correlation_id => $orphan ) { //process if ( $this->keepGoing() ){ + // TODO: Maybe we can simplify by checking that modified time < job start time. echo "Attempting to rectify orphan $correlation_id\n"; if ( $this->rectifyOrphan( $orphan ) ){ - $this->addStompCorrelationIDToAckBucket( $correlation_id ); + $this->ackMessage( $correlation_id ); $this->handled_ids[$correlation_id] = 'rectified'; } else { $this->handled_ids[$correlation_id] = 'error'; } } } - $this->addStompCorrelationIDToAckBucket( false, true ); //ack all outstanding. if ( $this->keepGoing() ){ $orphans = $this->getStompOrphans(); } } } - $this->addStompCorrelationIDToAckBucket( false, true ); //ack all outstanding. - //TODO: Make stats squirt out all over the place. $am = 0; $rec = 0; @@ -125,9 +83,6 @@ $fe = 0; foreach( $this->handled_ids as $id=>$whathappened ){ switch ( $whathappened ){ - case 'antimessage' : - $am += 1; - break; case 'rectified' : $rec += 1; break; @@ -140,7 +95,6 @@ } } $final = "\nDone! Final results: \n"; - $final .= " $am destroyed via antimessage (called $am_called_count times) \n"; $final .= " $rec rectified orphans \n"; $final .= " $err errored out \n"; $final .= " $fe false orphans caught \n"; @@ -154,9 +108,9 @@ echo $final; } - function keepGoing(){ + protected function keepGoing(){ $elapsed = $this->getProcessElapsed(); - if ( $elapsed < $this->target_execute_time ){ + if ( $elapsed < $this->getOrphanGlobal( 'target_execute_time' ) ){ return true; } else { return false; @@ -168,188 +122,69 @@ * the cronspammer. * @return int elapsed time since start in seconds */ - function getProcessElapsed(){ + protected function getProcessElapsed(){ $elapsed = time() - $this->start_time; echo "Elapsed Time: $elapsed\n"; return $elapsed; } - function addStompCorrelationIDToAckBucket( $correlation_id, $ackNow = false ){ - static $bucket = array(); - $count = 50; //sure. Why not? - if ( $correlation_id ) { - $bucket[$correlation_id] = "'$correlation_id'"; //avoiding duplicates. - $this->handled_ids[$correlation_id] = 'antimessage'; - } - if ( count( $bucket ) && ( count( $bucket ) >= $count || $ackNow ) ){ - //ack now. - echo 'Acking ' . count( $bucket ) . " bucket messages.\n"; - $selector = 'JMSCorrelationID IN (' . implode( ", ", $bucket ) . ')'; - $ackMe = stompFetchMessages( 'cc-limbo', $selector, $count * 100 ); //This is outrageously high, but I just want to be reasonably sure we get all the matches. - $retrieved_count = count( $ackMe ); - if ( $retrieved_count ){ - stompAckMessages( $ackMe ); - $this->removed_message_count += $retrieved_count; - echo "Done acking $retrieved_count messages. \n"; - } else { - echo "Oh noes! No messages retrieved for $selector...\n"; - } - $bucket = array(); - } - + protected function ackMessage( $correlation_id ) { + $this->handled_ids[$correlation_id] = 'antimessage'; + + DonationQueue::instance()->delete( + $correlation_id, GlobalCollectAdapter::CC_LIMBO_QUEUE ); } - - function handleStompAntiMessages(){ - $selector = "antimessage = 'true' AND gateway='globalcollect'"; - $antimessages = stompFetchMessages( 'cc-limbo', $selector, 1000 ); - $count = 0; - while ( count( $antimessages ) > 10 && $this->keepGoing() ){ //if there's an antimessage, we can ack 'em all right now. - echo "Colliding " . count( $antimessages ) . " antimessages\n"; - $count += count( $antimessages ); - foreach ( $antimessages as $message ){ - //add the correlation ID to the ack bucket. - if (array_key_exists('correlation-id', $message->headers)) { - $this->addStompCorrelationIDToAckBucket( $message->headers['correlation-id'] ); - } else { - echo 'The STOMP message ' . $message->headers['message-id'] . " has no correlation ID!\n"; - } - } - $this->addStompCorrelationIDToAckBucket( false, true ); //ack all outstanding. - $antimessages = stompFetchMessages( 'cc-limbo', $selector, 1000 ); - } - $this->addStompCorrelationIDToAckBucket( false, true ); //this just acks everything that's waiting for it. - $this->logger->info( "Found $count antimessages." ); - return $count; - } - + /** - * Returns an array of **at most** 300 decoded orphans that we don't think we've rectified yet. - * @return array keys are the correlation_id, and the values are the decoded stomp message body. + * Returns an array of at most $batch_size decoded orphans that we don't + * think we've rectified yet. + * + * @return array keys are the correlation_id, and the values are the + * decoded stomp message body. */ - function getStompOrphans(){ + protected function getStompOrphans(){ + // FIXME: Expiration should be set in configuration, and enforced by + // the queue's native expiry anyway. $time_buffer = 60*20; //20 minutes? Sure. Why not? - $selector = "payment_method = 'cc' AND gateway='globalcollect'"; - echo "Fetching 300 Orphans\n"; - $messages = stompFetchMessages( 'cc-limbo', $selector, 300 ); + $batch_size = 300; + echo "Fetching {$batch_size} Orphans\n"; + + $messages = DonationQueue::instance()->popMultiple( + GlobalCollectAdapter::CC_LIMBO_QUEUE, $batch_size ); + $orphans = array(); - $false_orphans = array(); foreach ( $messages as $message ){ - //this next block will do quite a lot of antimessage collision - //when the queue is not being railed. - if ( array_key_exists('antimessage', $message->headers ) ){ - $correlation_id = $message->headers['correlation-id']; - $false_orphans[] = $correlation_id; - echo "False Orphan! $correlation_id \n"; - } else { - //legit message - if ( !array_key_exists( $message->headers['correlation-id'], $this->handled_ids ) ) { - //check the timestamp to see if it's old enough. - $decoded = json_decode($message->body, true); - if ( array_key_exists( 'date', $decoded ) ){ - $elapsed = $this->start_time - $decoded['date']; - if ( $elapsed > $time_buffer ){ - //we got ourselves an orphan! - $correlation_id = $message->headers['correlation-id']; - $order_id = explode('-', $correlation_id); - $order_id = $order_id[1]; - $decoded['order_id'] = $order_id; - $decoded = unCreateQueueMessage($decoded); - $decoded['card_num'] = ''; - $orphans[$correlation_id] = $decoded; - echo "Found an orphan! $correlation_id \n"; - } + $correlation_id = $message['correlation-id']; + if ( !array_key_exists( $correlation_id, $this->handled_ids ) ) { + //check the timestamp to see if it's old enough. + if ( array_key_exists( 'date', $message ) ) { + $elapsed = $this->start_time - $message['date']; + if ( $elapsed > $time_buffer ){ + //we got ourselves an orphan! + // FIXME: Reuse unstaging function. + $order_id = explode( '-', $correlation_id ); + $order_id = $order_id[1]; + $message['order_id'] = $order_id; + $message = $this->unCreateQueueMessage( $message ); + $message['card_num'] = ''; + $orphans[$correlation_id] = $message; + echo "Found an orphan! $correlation_id \n"; } } } } - - foreach ( $orphans as $cid => $data ){ - if ( in_array( $cid, $false_orphans ) ){ - unset( $orphans[$cid] ); - $this->addStompCorrelationIDToAckBucket( $cid ); - $this->handled_ids[ $cid ] = 'false_orphan'; - } - } - + return $orphans; } - - function parse_files(){ - //all the old stuff goes here. - $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"; - - $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 ); - } - } - } - - $this->adapter->setCurrentTransaction('INSERT_ORDERWITHPAYMENT'); - $xml = new DomDocument; - - //fields that have generated notices if they're not there. - $additional_fields = array( - 'card_num', - 'utm_medium', - 'utm_campaign', - 'referrer', - ); - - foreach ($payments as $key => $payment_data){ - $xml->loadXML($payment_data['xml']); - $parsed = $this->adapter->getResponseData($xml); - $payments[$key]['parsed'] = $parsed; - $payments[$key]['unstaged'] = $this->adapter->unstage_data($parsed); - $payments[$key]['unstaged']['contribution_tracking_id'] = $payments[$key]['contribution_tracking_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. Anything that requires user interaction would make no sense here. - $i = 0; - foreach($payments as $payment_data){ - if ($i < $this->max_per_execute){ - ++$i; - if ( $this->rectifyOrphan( $payment_data['unstaged'] ) ) { - unset( $this->order_ids[$payment_data['unstaged']['order_id']] ); - } - } - } - - if ($outstanding_count != count($this->order_ids)){ - $this->rewriteOrderIds(); - } - } - /** - * Uses the Orphan Adapter to rectify a single orphan. Returns a boolean letting the caller know if + * Uses the Orphan Adapter to rectify (complete the charge for) a single orphan. Returns a boolean letting the caller know if * the orphan has been fully rectified or not. * @param array $data Some set of orphan data. * @param boolean $query_contribution_tracking A flag specifying if we should query the contribution_tracking table or not. * @return boolean True if the orphan has been rectified, false if not. */ - function rectifyOrphan( $data, $query_contribution_tracking = true ){ + protected function rectifyOrphan( $data, $query_contribution_tracking = true ){ echo 'Rectifying Orphan ' . $data['order_id'] . "\n"; $rectified = false; @@ -382,8 +217,10 @@ /** * Gets the global setting for the key passed in. * @param type $key + * + * FIXME: Reuse GatewayAdapter::getGlobal. */ - function getOrphanGlobal( $key ){ + protected function getOrphanGlobal( $key ){ global $wgDonationInterfaceOrphanCron; if ( array_key_exists( $key, $wgDonationInterfaceOrphanCron ) ){ return $wgDonationInterfaceOrphanCron[$key]; @@ -391,123 +228,39 @@ return NULL; } } - - 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; - } - } + + /** + * Called by the orphan rectifier to change a queue message back into a gateway + * transaction array, basically undoing the mappings from createQueueMessage + * + * @param array $transaction STOMP message + * + * @return array message with queue keys remapped to gateway keys + */ + protected function unCreateQueueMessage( $transaction ) { + // For now, this function assumes that we have a complete queue message. + // TODO: Something more robust and programmatic, as time allows. This whole file is just terrible. + + $rekey = array( + 'first_name' => 'fname', + 'last_name' => 'lname', + 'street_address' => 'street', + 'state_province' => 'state', + 'postal_code' => 'zip', + 'currency' => 'currency_code', + 'gross' => 'amount', + ); + + foreach ( $rekey as $stomp => $di ){ + if ( isset( $transaction[$stomp] ) ){ + $transaction[$di] = $transaction[$stomp]; + unset($transaction[$stomp]); + }; } - closedir($handle); - return $files; + + return $transaction; } - - 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){ - $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 = 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 RUN_MAINTENANCE_IF_MAIN; diff --git a/tests/Adapter/GlobalCollect/OrphanRectifierTest.php b/tests/Adapter/GlobalCollect/OrphanRectifierTest.php new file mode 100644 index 0000000..548fc7d --- /dev/null +++ b/tests/Adapter/GlobalCollect/OrphanRectifierTest.php @@ -0,0 +1,61 @@ +<?php + +/** + * Wikimedia Foundation + * + * LICENSE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +use Psr\Log\LogLevel; + +/** + * + * @group Fundraising + * @group DonationInterface + * @group GlobalCollect + * @group OrphanSlayer + */ +class DonationInterface_Adapter_GlobalCollect_OrphanRectifierTest + extends DonationInterfaceTestCase +{ + + /** + * @param $name string The name of the test case + * @param $data array Any parameters read from a dataProvider + * @param $dataName string|int The name or index of the data set + */ + function __construct( $name = null, array $data = array(), $dataName = '' ) { + parent::__construct( $name, $data, $dataName ); + $this->testAdapterClass = 'TestingGlobalCollectOrphanAdapter'; + } + + public function setUp() { + parent::setUp(); + + $this->orphanRectifier = TestingAccessWrapper::newFromObject( + new GlobalCollectOrphanRectifier() ); + + $this->setMwGlobals( array( + 'wgDonationInterfaceEnableQueue' => true, + 'wgDonationInterfaceOrphanCron' => array( + 'enable' => true, + ), + 'wgDonationInterfaceDefaultQueueServer' => array( + 'type' => 'DonationInterface_DummyQueue', + ), + ) ); + } + + public function testGetStompOrphans() { + } +} -- To view, visit https://gerrit.wikimedia.org/r/207029 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I107406d54e5658ea68521b28bb82cf8faa0f91b7 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/DonationInterface Gerrit-Branch: master Gerrit-Owner: Awight <awi...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits