r97776 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r97775‎ | r97776 | r97777 >
Date:01:10, 22 September 2011
Author:pgehres
Status:reverted (Comments)
Tags:
Comment:
Adding webitects form for this week as well as a few changes to RapidHTML
Modified paths:
  • /trunk/extensions/DonationInterface/payflowpro_gateway/forms/RapidHtml.php (modified) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/html/webitects_2_3step.html (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php (modified) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/validate_input.js (modified) (history)

Diff [purge]

Index: trunk/extensions/DonationInterface/payflowpro_gateway/validate_input.js
@@ -39,6 +39,67 @@
4040 document.getElementById('payflowpro_gateway-form-submit-paypal').style.display = 'none';
4141 }
4242
 43+/*
 44+ * Validates the personal information fields
 45+ *
 46+ * @input form The form containing the inputs to be checked
 47+ *
 48+ * @return boolean true if no errors, false otherwise (also uses an alert() to notify the user)
 49+ */
 50+function validate_personal( form ){
 51+
 52+ // TODO: this form should only report a single error for the email address?
 53+
 54+ var output = '';
 55+ var currField = '';
 56+ var i = 0;
 57+ var msg = [ 'EmailAdd', 'Fname', 'Lname', 'Street', 'City', 'Zip'];
 58+ var fields = [ "emailAdd","fname","lname","street","city","zip" ],
 59+ numFields = fields.length;
 60+ for( i = 0; i < numFields; i++ ) {
 61+ if( document.getElementById( fields[i] ).value == '' ) {
 62+ currField = window['payflowproGatewayErrorMsg'+ msg[i]];
 63+ output += payflowproGatewayErrorMsgJs + ' ' + currField + '.\r\n';
 64+ }
 65+ }
 66+ var stateField = document.getElementById( 'state' );
 67+ var countryField = document.getElementById( 'country' );
 68+ if( stateField.options[stateField.selectedIndex].value == 'YY' ) {
 69+ output += payflowproGatewayErrorMsgJs + ' ' + window['payflowproGatewayErrorMsgState'] + '.\r\n';
 70+ }
 71+
 72+ if( countryField.type == "select" ){ // country is a dropdown select
 73+ if( countryField.options[countryField.selectedIndex].value == '' ) {
 74+ output += payflowproGatewayErrorMsgJs + ' ' + window['payflowproGatewayErrorMsgCountry'] + '.\r\n';
 75+ }
 76+ }
 77+ else{ // country is a hidden or text input
 78+ if( countryField.value == '' ) {
 79+ output += payflowproGatewayErrorMsgJs + ' ' + window['payflowproGatewayErrorMsgCountry'] + '.\r\n';
 80+ }
 81+ }
 82+
 83+ //set state to "outside us"
 84+ if ( form.country.value != 'US' ) {
 85+ form.state.value = 'XX';
 86+ }
 87+
 88+ // validate email address
 89+ var apos = form.emailAdd.value.indexOf("@");
 90+ var dotpos = form.emailAdd.value.lastIndexOf(".");
 91+
 92+ if( apos < 1 || dotpos-apos < 2 ) {
 93+ output += payflowproGatewayErrorMsgEmail;
 94+ }
 95+
 96+ if( output ) {
 97+ alert( output );
 98+ return false;
 99+ }
 100+
 101+ return true;
 102+}
 103+
43104 function validate_form( form ) {
44105 if( form == null ){
45106 form = document.payment
Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php
@@ -79,6 +79,7 @@
8080 $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
8181
8282 // @fixme can this be moved into the form generators?
 83+ // @fixme this is broken on MW 1.16, executes before jQuery load
8384 $js = <<<EOT
8485 <script type="text/javascript">
8586 jQuery(document).ready(function() {
Index: trunk/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/html/webitects_2_3step.html
@@ -0,0 +1,486 @@
 2+<!-- load styles from original first steps -->
 3+<link rel="stylesheet" href="@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/css/lp1.css" />
 4+<!--[if lt IE 7]><style type="text/css">body{behavior:url("/w/skins-1.17/vector/csshover.min.htc")}</style><![endif]-->
 5+<!-- start Webitects styles -->
 6+<link rel="stylesheet" href="@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/css/Webitects.css" />
 7+<style type="text/css">
 8+ #errorMessages { font-size: 0.75em; color: #FF0000; }
 9+ /* Force vertical scrollbar
 10+ html { overflow-y: scroll; }
 11+ */
 12+ /* Accordion */
 13+ #accordion h3 { background: #FFFFFF; border: none; font-size: 1.1em; margin: 0; padding: 0.5em 0.9em; outline: 0; }
 14+ .accordion-content { padding: 0.9em; }
 15+ #step2accordion { display:none; }
 16+
 17+ /* Callouts */
 18+ .call-l, .call-r { width: 270px; }
 19+
 20+ /* Layout */
 21+ #appeal { float: left; width: 100%; }
 22+ #appeal-content { padding-right: 380px; }
 23+ .clear { clear: both; }
 24+ #donate { float: left; margin-left: -350px; width: 350px; }
 25+ #donate-content { background-color: #FFFFFF; border: 1px solid #000000; padding: 1em 0;
 26+ font-size: 0.95em;
 27+ }
 28+ #amount-table-white label { font-size: 1.1em; }
 29+
 30+ #donate-body { width: 348px; }
 31+ #donate-body h3 { font-size: 17px; }
 32+
 33+ #step1wrapper, #step2wrapper, #step3wrapper { width: 325px; }
 34+ /* Initially hide steps 2 and 3 */
 35+ #step2wrapper, #step2header, #step3wrapper, #step3header { display: none; }
 36+ #where-content { font-size: 13px; line-height: 19px; width: 325px; }
 37+
 38+ #amountErrorMessages, #billingErrorMessages, #paymentErrorMessages { color: #F00; }
 39+
 40+</style>
 41+<!--[if lt IE 7]><style>
 42+/* style for IE6 + IE5.5 + IE5.0 */
 43+.gainlayout { height: 0; }
 44+</style><![endif]-->
 45+
 46+<!--[if IE 7]><style>
 47+.gainlayout { zoom: 1; height: 1%; }
 48+</style><![endif]-->
 49+
 50+<div class="ltr">
 51+ <div id="appeal">
 52+ <div id="appeal-content">
 53+ <h2 id="appeal-head"> <span class="mw-headline" id="From_Wikipedia_programmer_Brandon_Harris">From Wikipedia programmer Brandon Harris</span></h2>
 54+ <div id="appeal-body" class="plainlinks">
 55+ <p>I feel like I'm living the first line of my obituary.</p>
 56+ <p>I don't think there will be anything else that I do in my life as important as what I do now for Wikipedia. We're not just building an encyclopedia, we're working to make people free. When we have access to free knowledge, we are better people. We understand the world is bigger than us, and we become infected with tolerance and understanding.</p>
 57+ <p>Wikipedia is the 5th largest website in the world. I work at the small non-profit that keeps it on the web. We don't run ads because doing so would sacrifice our independence. The site is not and should never be a propaganda tool.</p>
 58+ <p>Our work is possible because of donations from our readers. Will you help protect Wikipedia by donating $5, $10, $20 or whatever you can afford?</p>
 59+ <p>I work at the Wikimedia Foundation because everything in my soul tells me it's the right thing to do. I've worked at huge tech companies, doing some job to build some crappy thing that's designed to steal money from some kid who doesn't know it. I would come home from work crushed.</p>
 60+ <p>You might not know this, but the Wikimedia Foundation operates with a very small staff. Most other top-ten sites have tens of thousands of people and massive budgets. But they produce a fraction of what we pull off with sticks and wire.</p>
 61+ <p>When you give to Wikipedia, you're supporting free knowledge around the world. You're not only leaving a legacy for your children and for their children, you're elevating people around the world who have access to this treasure. You're assuring that one day everyone else will too.</p>
 62+ <p>Thank you,</p>
 63+ <p><strong>Brandon Harris</strong><br /></p>
 64+ <p>Programmer, Wikimedia Foundation</p>
 65+ </div>
 66+ </div>
 67+ </div>
 68+
 69+ <div id="donate">
 70+ <div id="donate-content">
 71+ <div id="donate-body" style="padding: 0 1em;">
 72+ <div id="step1header"><h3>Donation amount <span id="selected-amount"></span> <span class="mute" id="change-amount" style="display: none;">(<a href="#">Change</a>)</span></h3></div>
 73+
 74+ <form method="post" name="paypalcontribution">
 75+ <div id="step1wrapper">
 76+ <div id="amountErrorMessages" class="small"></div>
 77+ <table id="amount-table-white">
 78+ <tr>
 79+ <td><label><input type="radio" name="amountRadio" value="5" /> $5</label></td>
 80+ <td><label><input type="radio" name="amountRadio" value="10" /> $10</label></td>
 81+ <td><label><input type="radio" name="amountRadio" value="20" /> $20</label></td>
 82+ <td><label><input type="radio" name="amountRadio" value="35" /> $35</label></td>
 83+ </tr>
 84+ <tr>
 85+ <td><label><input type="radio" name="amountRadio" value="50" /> $50</label></td>
 86+ <td><label><input type="radio" name="amountRadio" value="100" /> $100</label></td>
 87+ <td><label><input type="radio" name="amountRadio" value="250" /> $250</label></td>
 88+ <td><label><input type="radio" name="amountRadio" id="input_amount_other" value="other" /> $<input type="text" class="txt-sm hint" name="amountGiven" size="4" id="other-amount" title="Other..." onfocus="this.form.input_amount_other.checked=true;"/></label></td>
 89+ </tr>
 90+ </table>
 91+
 92+ <p class="donate-options">
 93+ <input class="btn" id="cc" type="button" value="Donate by Credit Card" /><br />
 94+ <input class="btn" id="pp" type="button" value="Donate via PayPal"/><span id='loading'></span>
 95+ </p>
 96+ </div>
 97+ <div id="step2header"><h3>Billing Address <span class="mute" id="change-billing" style="display: none;">(<a href="#">Change</a>)</span></h3></div>
 98+ <div id="step2wrapper">
 99+ <div id="billing-content" class="gainlayout">
 100+ <div id="billingErrorMessages" class="small"></div>
 101+ <div class="name-fields">
 102+ <span class="name-first"><input class="txt hint" id="fname" name="fname" title="First name" value="@fname" /></span>
 103+ <span class="name-last"><input class="txt hint" id="lname" name="lname" title="Last name" value="@lname" /></span>
 104+ </div>
 105+ <div class="loc-fields">
 106+ <span class="loc-street"><input class="txt hint" id="street" name="street" title="Street address" value="@street" /></span>
 107+ <span class="loc-city"><input class="txt hint" id="city" name="city" title="City" value="@city" /></span>
 108+ <span class="loc-state">
 109+ <select id="state" name="state" class="txt" value="@state" >
 110+ <option value=""></option>
 111+ <option value="AK">AK</option><option value="AL">AL</option><option value="AR">AR</option><option value="AZ">AZ</option><option value="CA">CA</option><option value="CO">CO</option><option value="CT">CT</option><option value="DC">DC</option><option value="DE">DE</option><option value="FL">FL</option><option value="GA">GA</option><option value="HI">HI</option><option value="IA">IA</option><option value="ID">ID</option><option value="IL">IL</option><option value="IN">IN</option><option value="KS">KS</option><option value="KY">KY</option><option value="LA">LA</option><option value="MA">MA</option><option value="MD">MD</option><option value="ME">ME</option><option value="MI">MI</option><option value="MN">MN</option><option value="MO">MO</option><option value="MS">MS</option><option value="MT">MT</option><option value="NC">NC</option><option value="ND">ND</option><option value="NE">NE</option><option value="NH">NH</option><option value="NJ">NJ</option><option value="NM">NM</option><option value="NV">NV</option><option value="NY">NY</option><option value="OH">OH</option><option value="OK">OK</option><option value="OR">OR</option><option value="PA">PA</option><option value="PR">PR</option><option value="RI">RI</option><option value="SC">SC</option><option value="SD">SD</option><option value="TN">TN</option><option value="TX">TX</option><option value="UT">UT</option><option value="VA">VA</option><option value="VT">VT</option><option value="WA">WA</option><option value="WI">WI</option><option value="WV">WV</option><option value="WY">WY</option><option value="AA">AA</option><option value="AE">AE</option><option value="AP">AP</option>
 112+ </select>
 113+ </span>
 114+ <span class="loc-postal"><input class="txt hint" id="zip" name="zip" title="Zip" value="@zip"/></span>
 115+ </div>
 116+ <p><input class="txt hint" title="Email address" id="emailAdd" name="emailAdd" value="@emailAdd"/></p>
 117+
 118+ <dl class="">
 119+ <dt><span class="label">Select credit card</span></dt>
 120+ <dd class="field" style="margin-bottom: 0;">
 121+ <ul class="options-h" id="cards" style="margin: 0;">
 122+ <li><input id="cc-visa" name="cardtype" type="radio" value="Visa" class="cardradio" /> <label for="cc-visa"><img alt="Visa" src="@script_path/extensions/DonationInterface/payflowpro_gateway/includes/card-visa.png" /></label></li>
 123+ <li><input id="cc-mastercard" name="cardtype" type="radio" value="MasterCard" class="cardradio" /> <label for="cc-mastercard"><img alt="MasterCard" src="@script_path/extensions/DonationInterface/payflowpro_gateway/includes/card-mastercard.png" /></label></li>
 124+ <li><input id="cc-amex" name="cardtype" type="radio" value="American Express" class="cardradio" /> <label for="cc-amex"><img alt="American Express" src="@script_path/extensions/DonationInterface/payflowpro_gateway/includes/card-amex.png" /></label></li>
 125+ <li><input id="cc-discover" name="cardtype" type="radio" value="Discover" class="cardradio" /> <label for="cc-discover"><img alt="Discover" src="@script_path/extensions/DonationInterface/payflowpro_gateway/includes/card-discover.png" /></label></li>
 126+ </ul>
 127+ <div id="paymentContinue" style="margin-top: 10px; display: none;"><button>Continue</button></div>
 128+ </dd>
 129+ </dl>
 130+ </div>
 131+ </div>
 132+ <div id="step3header"><h3>Payment Information <span class="mute" id="change-payment" style="display: none;">(<a href="#">Change</a>)</span></h3></div>
 133+ <div id="step3wrapper" style="display: none;">
 134+ <div id="payment" class="gainlayout">
 135+ <div id="paymentErrorMessages" class="small"></div>
 136+ <dl class="form">
 137+ <dt><span class="label"><label for="card_num">Card number</label></span></dt>
 138+ <dd class="field"><input class="txt" id="card_num" name="card_num" value="@card_num"/></dd>
 139+
 140+ <dt></dt>
 141+ <dd class="field">
 142+ <div class="l" style="margin-right: 5%;">
 143+ <span class="label">Expiration date</span>
 144+ <select id="mos" name="mos">
 145+ <option value="">Month</option>
 146+ <option value="01">01 - January</option>
 147+ <option value="02">02 - February</option>
 148+ <option value="03">03 - March</option>
 149+ <option value="04">04 - April</option>
 150+ <option value="05">05 - May</option>
 151+ <option value="06">06 - June</option>
 152+ <option value="07">07 - July</option>
 153+ <option value="08">08 - August</option>
 154+ <option value="09">09 - September</option>
 155+ <option value="10">10 - October</option>
 156+ <option value="11">11 - November</option>
 157+ <option value="12">12 - December</option>
 158+ </select>
 159+
 160+ <select id="year" name="year">
 161+ <option value="">Year</option>
 162+ <option value="2011">2011</option>
 163+ <option value="2012">2012</option>
 164+ <option value="2013">2013</option>
 165+ <option value="2014">2014</option>
 166+ <option value="2015">2015</option>
 167+ <option value="2016">2016</option>
 168+ <option value="2017">2017</option>
 169+ <option value="2018">2018</option>
 170+ <option value="2019">2019</option>
 171+ <option value="2020">2020</option>
 172+ </select>
 173+ </div>
 174+ <div class="l">
 175+ <label class="label" for="cvv">Security code</label>
 176+ <input class="txt-sm" id="cvv" name="cvv" value="@cvv"/>
 177+ <a class="mute" href="#" id="where">Where?</a>
 178+ </div>
 179+
 180+ <div class="clear" id="codes" style="display: none;"><img alt="Security codes" src="@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/images/security-code.png" /></div>
 181+ </dd>
 182+
 183+ <dt></dt>
 184+ <dd class="field">
 185+ <input id="submitcreditcard" class="btn" type="button" value="Submit donation" />
 186+ <p class="mute"><img alt="" src="@script_path/extensions/DonationInterface/payflowpro_gateway/includes/padlock.gif" /> Your credit card will be securely processed.</p>
 187+ </dd>
 188+ </dl>
 189+ </div>
 190+ </div>
 191+
 192+ <input type="hidden" name="gateway" value="payflowpro" id="gateway" />
 193+ <input type="hidden" name="returnto" value="Thank_You/en" />
 194+
 195+ <input type="hidden" value="@card" name="card" id="card">
 196+
 197+ <input type="hidden" value="@amount" name="amount" />
 198+ <input type="hidden" value="US" name="country" id="country" />
 199+ <input type="hidden" value="@expiration" name="expiration" id="expiration"/>
 200+ <input type="hidden" value="@currency_code" name="currency" />
 201+ <input type="hidden" value="@currency_code" name="currency_code" />
 202+ <input type="hidden" value="@utm_source" name="utm_source"/>
 203+ <input type="hidden" value="@utm_medium" name="utm_medium"/>
 204+ <input type="hidden" value="@utm_campaign" name="utm_campaign"/>
 205+ <input type="hidden" value="@language" name="language"/>
 206+ <input type="hidden" value="@referrer" name="referrer"/>
 207+ <input type="hidden" value="@comment" name="comment"/>
 208+ <input type="hidden" value="@comment-option" name="comment-option"/>
 209+ <input type="hidden" value="@email-opt" name="email-opt"/>
 210+ <input type="hidden" value="processed" name="payment_method"/>
 211+ <input type="hidden" value="@token" name="token"/>
 212+ <input type="hidden" value="@order_id" name="order_id"/>
 213+ <input type="hidden" value="@numAttempt" name="numAttempt"/>
 214+ <input type="hidden" value="@contribution_tracking_id" name="contribution_tracking_id"/>
 215+ <input type="hidden" value="@data_hash" name="data_hash"/>
 216+ <input type="hidden" value="@owa_session" name="owa_session"/>
 217+ <input type="hidden" value="@owa_ref" name="owa_ref"/>
 218+ </form>
 219+ <div id="where-content">
 220+ <hr>
 221+ <h3>Where your donation goes</h3>
 222+ <p><strong>Technology:</strong> Servers, bandwidth, maintenance, development. Wikipedia is the #5 website in the world and it runs on a fraction of what other top websites spend.</p>
 223+ <p><strong>People:</strong> The other top 10 website have thousands of employees. We have fewer than 100, making your donation a great investment in a highly-efficient not-for-profit organization.</p>
 224+ </div>
 225+ </div>
 226+ </div>
 227+ <p>We do not store your credit card information, and your personal data is subject to our <a target="_blank" href="https://www.mediawiki.org//wikimediafoundation.org/wiki/Donor_policy"> donor privacy policy</a>.</p>
 228+ <p><a href="https://www.mediawiki.org//wikimediafoundation.org/wiki/Ways_to_Give/en">More information or other ways to give</a><br /><a href="https://www.mediawiki.org//wikimediafoundation.org/wiki/FAQ/en">Answers to frequently asked questions</a></p>
 229+ </div>
 230+</div>
 231+
 232+ <!-- load jquery (newer) -->
 233+ <script type='text/javascript' src='@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/js/jquery.js'></script>
 234+ <script type='text/javascript' src='@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/js/jquery.ui.core.js'></script>
 235+ <script type='text/javascript' src='@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/js/jquery.ui.widget.js'></script>
 236+ <script type='text/javascript' src='@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/js/jquery.ui.accordion.js'></script>
 237+ <script type='text/javascript' src='@script_path/extensions/DonationInterface/payflowpro_gateway/forms/rapidhtml/js/jquery.ezpz_hint.js'></script>
 238+ <script type="text/javascript">
 239+ ( function( $ ){
 240+ window.onload = function (){
 241+ // ensure all jQuery instances are set to 1.4.2
 242+ jQuery = $;
 243+ $j = $;
 244+
 245+ // This form is radically broken in IE6
 246+ // Redirecting them to another page
 247+ // TODO: handle this in the banner
 248+ if (jQuery.browser.msie && jQuery.browser.version.substr(0,1)<7){
 249+ //get the current querystring
 250+ var qs = window.location.search.substring(1);
 251+ // redirect IE6 people to another form
 252+ window.location.replace("https://wikimediafoundation.org/wiki/Special:LandingCheck?language=en&landing_page=L11_ExtraInfo_0902_N&utm_campaign=C_0916_Webitects_US_ie6&utm_source=B_BR_0916_US&country_code=US&referrer=webitects2");
 253+ }
 254+
 255+
 256+ // check for RapidHtml errors and display, if any
 257+ var amountErrors = ['#general|escape','#retryMsg|escape','#amount|escape'],
 258+ amountErrorString = "";
 259+ var billingErrors = ['#fname|escape','#lname|escape','#city|escape','#country|escape',
 260+ '#street|escape','#state|escape','#zip|escape','#emailAdd|escape'],
 261+ billingErrorString = "";
 262+ var paymentErrors = ['#card_num|escape','#card|escape','#cvv|escape'],
 263+ paymentErrorString = "";
 264+
 265+ // generate formatted errors to display
 266+ var temp = []
 267+ for( var e in amountErrors )
 268+ if( amountErrors[e] != "" )
 269+ temp[temp.length] = amountErrors[e];
 270+ amountErrorString = temp.join( "<br />" );
 271+
 272+ temp = []
 273+ for( var e in billingErrors )
 274+ if( billingErrors[e] != "" )
 275+ temp[temp.length] = billingErrors[e];
 276+ billingErrorString = temp.join( "<br />" );
 277+
 278+ temp = []
 279+ for( var e in paymentErrors )
 280+ if( paymentErrors[e] != "" )
 281+ temp[temp.length] = paymentErrors[e];
 282+ paymentErrorString = temp.join( "<br />" );
 283+
 284+ // show the errors
 285+ var prevError = false;
 286+ if( amountErrorString != ""){
 287+ $("#amountErrorMessages").html( amountErrorString );
 288+ prevError = true;
 289+ showStep1(); // should be default, but ensure
 290+ }
 291+ if( billingErrorString != ""){
 292+ $("#billingErrorMessages").html( billingErrorString );
 293+ if( !prevError ){
 294+ showStep2();
 295+ prevError = true;
 296+ }
 297+ showAmount( $('input[name="amount"]') ); // lets go ahead and assume there is something to show
 298+ }
 299+ if( paymentErrorString != ""){
 300+ $("#paymentErrorMessages").html( paymentErrorString );
 301+ if( !prevError )
 302+ showStep3();
 303+ showAmount( $('input[name="amount"]') ); // lets go ahead and assume there is something to show
 304+ }
 305+
 306+ // Init inline labels
 307+ $(".hint").ezpz_hint();
 308+
 309+ $("#cc").click(function(){
 310+ if ( validateAmount() ){
 311+ showAmount( $('input[name="amount"]') );
 312+ showStep2();
 313+ }
 314+ });
 315+
 316+ $("#pp").click(function(){
 317+ if ( validateAmount() ){
 318+ // set the action to go to PayPal
 319+ /******************
 320+ ** TODO: FIX ME ** (Broken on return to form from PP and then choose CC)
 321+ ******************/
 322+ $("input[name=gateway]").val("paypal");
 323+ document.paypalcontribution.action = "https://wikimediafoundation.org/wiki/Special:ContributionTracking/en";
 324+ $("#loading").html("<img src='../images/loading.gif' /> Redirecting to PayPal…");
 325+ document.paypalcontribution.submit();
 326+ }
 327+ });
 328+ // Set the cards to progress to step 3
 329+ $(".cardradio").live("click", function() {
 330+ if ( validate_personal( document.paypalcontribution ) ){
 331+ showStep3();
 332+ }
 333+ else {
 334+ // show the continue button to indicate how to get to step 3 since they
 335+ // have already clicked on a card image
 336+ $("#paymentContinue").show();
 337+ }
 338+ });
 339+
 340+ $("#submitcreditcard").click(function(){
 341+ // set country to US TODO: make this dynamic
 342+ $('input[name="country"]').val("US");
 343+
 344+ if ( validate_cc() ){
 345+ // set the hidden expiration date input from the two selects
 346+ $('input[name="expiration"]').val(
 347+ $("select[name=mos]").val() + $('select[name="year"]').val().substring(2,4)
 348+ );
 349+
 350+ document.paypalcontribution.action = "@action";
 351+ document.paypalcontribution.submit();
 352+ }
 353+ })
 354+
 355+ // init all of the header actions
 356+ $("#step1header").click(function(){
 357+ showStep1();
 358+ });
 359+ $("#step2header").click(function(){
 360+ showStep2();
 361+ });
 362+ $("#step3header").click(function(){
 363+ showStep3();
 364+ });
 365+
 366+ function showStep1(){
 367+ // show the correct sections
 368+ $("#step1wrapper").slideDown();
 369+ $("#step2wrapper").slideUp();
 370+ $("#step3wrapper").slideUp();
 371+ $("#change-amount").hide();
 372+ $("#change-billing").show();
 373+ $("#change-payment").show();
 374+ $("#step1header").show(); // just in case
 375+ }
 376+ function showStep2(){
 377+ // show the correct sections
 378+ $("#step1wrapper").slideUp();
 379+ $("#step2wrapper").slideDown();
 380+ $("#step3wrapper").slideUp();
 381+ $("#change-amount").show();
 382+ $("#change-billing").hide();
 383+ $("#change-payment").show();
 384+ $("#step2header").show(); // just in case
 385+ }
 386+ function showStep3(){
 387+ // show the correct sections
 388+ $("#step1wrapper").slideUp();
 389+ $("#step2wrapper").slideUp();
 390+ $("#step3wrapper").slideDown();
 391+ $("#change-amount").show();
 392+ $("#change-billing").show();
 393+ $("#change-payment").hide();
 394+ $("#step3header").show(); // just in case
 395+ }
 396+
 397+
 398+ // Fix behavior of images in labels
 399+ // TODO: check that disabling this is okay in things other than Chrome
 400+// $("label img").live("click", function() { $("#" + $(this).parents( "label" ).attr( "for" )).click(); });
 401+
 402+ // Display selected amount
 403+ function showAmount(e){
 404+ $("#selected-amount").html( "($" + e.val() + ")" );
 405+ $("#change-amount").show();
 406+ }
 407+
 408+ // Set selected amount to amount
 409+ $('input[name="amountRadio"]').click( function(){
 410+ setAmount( $(this) );
 411+ });
 412+ // reset the amount field when "other" is changed
 413+ $("#other-amount").change(function(){
 414+ setAmount( $(this) );
 415+ });
 416+ // set the hidden amount input to the value of the selected element
 417+ function setAmount(e){
 418+ $("input[name=amount]").val( e.val() );
 419+ }
 420+
 421+ // show the CVV help image on click
 422+ $("#where").click(function(){
 423+ $("#codes").toggle();
 424+ return false;
 425+ });
 426+
 427+ function validateAmount(){
 428+ var minimums = {
 429+ 'USD' : 1
 430+ };
 431+ var error = true;
 432+ var amount = $('input[name="amount"]').val(); // get the amount
 433+ amount = amount.replace(/[,.](\d)$/, '\:$10');
 434+ amount = amount.replace(/[,.](\d)(\d)$/, '\:$1$2');
 435+ amount = amount.replace(/[,.]/g, '');
 436+ amount = amount.replace(/:/, '.');
 437+ $('input[name="amount"]').val( amount ); // set the new amount back into the form
 438+
 439+ // Check amount is a real number, sets error as true (good) if no issues
 440+ error = ( amount == null || isNaN( amount ) || amount.value <= 0 );
 441+
 442+ // Check amount is at least the minimum
 443+ var currency = 'USD'; // hard-coded for these forms and tests
 444+ $('input[name="currency"]').val( currency );
 445+ if ( typeof( minimums[currency] ) == 'undefined' ) {
 446+ minimums[currency] = 1;
 447+ }
 448+ if ( amount < minimums[currency] || error ) {
 449+ alert( 'You must contribute at least $1'.replace('$1', minimums[currency] + ' ' + currency ) );
 450+ error = true;
 451+ }
 452+ return !error;
 453+ }
 454+ function validate_cc(){
 455+ // reset the errors
 456+ $("#paymentErrorMessages").html('');
 457+ var error = false;
 458+ if( $('input[name="card_num"]').val() == '' ){
 459+ $("#paymentErrorMessages").append( "Please enter a valid credit card number" );
 460+ error = true;
 461+ }
 462+ if( $('select[name="mos"]').val() == '' ){
 463+ if( $("#paymentErrorMessages").html() != "" )
 464+ $("#paymentErrorMessages").append( "<br />" );
 465+ $("#paymentErrorMessages").append( "Please enter a valid month for the expiration date" );
 466+ error = true;
 467+ }
 468+ if( $('select[name="year"]').val() == '' ){
 469+ if( $("#paymentErrorMessages").html() != "" )
 470+ $("#paymentErrorMessages").append( "<br />" );
 471+ $("#paymentErrorMessages").append( "Please enter a valid year for the expiration date" );
 472+ error = true;
 473+ }
 474+ if( $('input[name="cvv"]').val() == '' ){
 475+ if( $("#paymentErrorMessages").html() != "" )
 476+ $("#paymentErrorMessages").append( "<br />" );
 477+ $("#paymentErrorMessages").append( "Please enter a valid security code" );
 478+ error = true;
 479+ }
 480+ return !error;
 481+ }
 482+ }
 483+ })(jQuery);
 484+ </script>
 485+<!-- Wikimedia Project logo
 486+<li id="footer-copyrightico"><a href="https://www.mediawiki.org//wikimediafoundation.org/"><img src="//bits.wikimedia.org/images/wikimedia-button.png" width="88" height="31" alt="Wikimedia Foundation"/></a></li>
 487+ -->
\ No newline at end of file
Index: trunk/extensions/DonationInterface/payflowpro_gateway/forms/RapidHtml.php
@@ -1,265 +1,285 @@
22 <?php
33
4 -class PayflowProGateway_Form_RapidHtml extends PayflowProGateway_Form {
5 -
6 - /**
7 - * Full path of HTML form to load
8 - * @var string
9 - */
10 - protected $html_file_path = '';
11 -
12 - /**
13 - * Tokens used in HTML form for data replacement
14 - *
15 - * Note that these NEED to be in the same order as the variables in $data in
16 - * order for str_replace to work as expected
17 - * @var array
18 - */
19 - protected $data_tokens = array(
20 - '@amount', // => $amount,
21 - '@amountOther', // => $wgRequest->getText( 'amountOther' ),
22 - '@emailAdd', //'email' => $wgRequest->getText( 'emailAdd' ),
23 - '@fname', // => $wgRequest->getText( 'fname' ),
24 - '@mname', // => $wgRequest->getText( 'mname' ),
25 - '@lname', // => $wgRequest->getText( 'lname' ),
26 - '@street', // => $wgRequest->getText( 'street' ),
27 - '@city', // => $wgRequest->getText( 'city' ),
28 - '@state', // => $wgRequest->getText( 'state' ),
29 - '@zip', // => $wgRequest->getText( 'zip' ),
30 - '@country', // => $wgRequest->getText( 'country' ),
31 - '@card_num', // => str_replace( ' ', '', $wgRequest->getText( 'card_num' ) ),
32 - '@card', // => $wgRequest->getText( 'card' ),
33 - '@expiration', // => $wgRequest->getText( 'mos' ) . substr( $wgRequest->getText( 'year' ), 2, 2 ),
34 - '@cvv', // => $wgRequest->getText( 'cvv' ),
35 - '@currency_code', //'currency' => $wgRequest->getText( 'currency_code' ),
36 - '@payment_method', // => $wgRequest->getText( 'payment_method' ),
37 - '@order_id', // => $order_id,
38 - '@numAttempt', // => $numAttempt,
39 - '@referrer', // => ( $wgRequest->getVal( 'referrer' ) ) ? $wgRequest->getVal( 'referrer' ) : $wgRequest->getHeader( 'referer' ),
40 - '@utm_source', // => self::getUtmSource(),
41 - '@utm_medium', // => $wgRequest->getText( 'utm_medium' ),
42 - '@utm_campaign', // => $wgRequest->getText( 'utm_campaign' ),
43 - // try to honr the user-set language (uselang), otherwise the language set in the URL (language)
44 - '@language', // => $wgRequest->getText( 'uselang', $wgRequest->getText( 'language' ) ),
45 - '@comment-option', // => $wgRequest->getText( 'comment-option' ),
46 - '@comment', // => $wgRequest->getText( 'comment' ),
47 - '@email-opt', // => $wgRequest->getText( 'email-opt' ),
48 - '@test_string', // => $wgRequest->getText( 'process' ), // for showing payflow string during testing
49 - '@token', // => $token,
50 - '@contribution_tracking_id', // => $wgRequest->getText( 'contribution_tracking_id' ),
51 - '@data_hash', // => $wgRequest->getText( 'data_hash' ),
52 - '@action', // => $wgRequest->getText( 'action' ),
53 - '@gateway', // => 'payflowpro', // this may need to become dynamic in the future
54 - '@owa_session', // => $wgRequest->getText( 'owa_session', null ),
55 - '@owa_ref', // => $owa_ref,
56 - // Not actually data tokens, but available to you in html form:
57 - // @captcha -> the captcha form
58 - // @script_path -> maps to $wgScriptPath
59 - // @action -> generate correct form action for this form
60 - );
61 -
62 - /**
63 - * Error field names used as tokens
64 - * @var array
65 - */
66 - protected $error_tokens = array(
67 - '#general',
68 - '#retryMsg',
69 - '#amount',
70 - '#card_num',
71 - '#card',
72 - '#cvv',
73 - '#fname',
74 - '#lname',
75 - '#city',
76 - '#country',
77 - '#street',
78 - '#state',
79 - '#zip',
80 - '#emailAdd',
81 - );
82 -
83 - public function __construct( &$form_data, &$form_errors ) {
84 - global $wgRequest;
85 - parent::__construct( $form_data, $form_errors );
 4+class PayflowProGateway_Form_RapidHtml extends PayflowProGateway_Form
 5+{
866
87 - $this->loadValidateJs();
88 -
89 - // set html-escaped filename.
90 - $this->set_html_file_path( htmlspecialchars( $wgRequest->getText( 'ffname', 'default' )));
91 -
92 - // fix general form error messages so it's not an array of msgs
93 - if ( is_array( $form_errors[ 'general' ] ) && count( $form_errors[ 'general' ] )) {
94 - $general_errors = "";
95 - foreach ( $form_errors[ 'general' ] as $general_error ) {
96 - $general_errors .= "<p class='creditcard'>$general_error</p>";
97 - }
98 - $form_errors[ 'general' ] = $general_errors;
99 - }
100 -
101 - // if this form needs to support squid cacheing, handle the magic
102 - $this->handle_cacheability();
103 - }
104 -
105 - /**
106 - * Return the HTML form with data added
107 - */
108 - public function getForm() {
109 - $html = $this->load_html();
110 - return $this->add_data( $html );
111 - }
112 -
113 - /**
114 - * Load the HTML form from a file into a string
115 - * @return string
116 - */
117 - public function load_html() {
118 - return file_get_contents( $this->html_file_path );
119 - }
120 -
121 - /**
122 - * Add data into the HTML form
123 - *
124 - * @param string $html Form with tokens as placehodlers for data
125 - * @return string The HTML form with real data in it
126 - */
127 - public function add_data( $html ) {
128 - global $wgScriptPath;
 7+ /**
 8+ * Full path of HTML form to load
 9+ * @var string
 10+ */
 11+ protected $html_file_path = '';
12912
130 - /**
131 - * This is a hack and should be replaced with something more performant.
132 - */
133 - $form = $html;
134 -
135 - // handle form action
136 - $form = str_replace( "@action", $this->getNoCacheAction(), $form );
 13+ /**
 14+ * Tokens used in HTML form for data replacement
 15+ *
 16+ * Note that these NEED to be in the same order as the variables in $data in
 17+ * order for str_replace to work as expected
 18+ * @var array
 19+ */
 20+ protected $data_tokens = array(
 21+ '@amount', // => $amount,
 22+ '@amountOther', // => $wgRequest->getText( 'amountOther' ),
 23+ '@emailAdd', //'email' => $wgRequest->getText( 'emailAdd' ),
 24+ '@fname', // => $wgRequest->getText( 'fname' ),
 25+ '@mname', // => $wgRequest->getText( 'mname' ),
 26+ '@lname', // => $wgRequest->getText( 'lname' ),
 27+ '@street', // => $wgRequest->getText( 'street' ),
 28+ '@city', // => $wgRequest->getText( 'city' ),
 29+ '@state', // => $wgRequest->getText( 'state' ),
 30+ '@zip', // => $wgRequest->getText( 'zip' ),
 31+ '@country', // => $wgRequest->getText( 'country' ),
 32+ '@card_num', // => str_replace( ' ', '', $wgRequest->getText( 'card_num' ) ),
 33+ '@card', // => $wgRequest->getText( 'card' ),
 34+ '@expiration', // => $wgRequest->getText( 'mos' ) . substr( $wgRequest->getText( 'year' ), 2, 2 ),
 35+ '@cvv', // => $wgRequest->getText( 'cvv' ),
 36+ '@currency_code', //'currency' => $wgRequest->getText( 'currency_code' ),
 37+ '@payment_method', // => $wgRequest->getText( 'payment_method' ),
 38+ '@order_id', // => $order_id,
 39+ '@numAttempt', // => $numAttempt,
 40+ '@referrer', // => ( $wgRequest->getVal( 'referrer' ) ) ? $wgRequest->getVal( 'referrer' ) : $wgRequest->getHeader( 'referer' ),
 41+ '@utm_source', // => self::getUtmSource(),
 42+ '@utm_medium', // => $wgRequest->getText( 'utm_medium' ),
 43+ '@utm_campaign', // => $wgRequest->getText( 'utm_campaign' ),
 44+ // try to honr the user-set language (uselang), otherwise the language set in the URL (language)
 45+ '@language', // => $wgRequest->getText( 'uselang', $wgRequest->getText( 'language' ) ),
 46+ '@comment-option', // => $wgRequest->getText( 'comment-option' ),
 47+ '@comment', // => $wgRequest->getText( 'comment' ),
 48+ '@email-opt', // => $wgRequest->getText( 'email-opt' ),
 49+ '@test_string', // => $wgRequest->getText( 'process' ), // for showing payflow string during testing
 50+ '@token', // => $token,
 51+ '@contribution_tracking_id', // => $wgRequest->getText( 'contribution_tracking_id' ),
 52+ '@data_hash', // => $wgRequest->getText( 'data_hash' ),
 53+ '@action', // => $wgRequest->getText( 'action' ),
 54+ '@gateway', // => 'payflowpro', // this may need to become dynamic in the future
 55+ '@owa_session', // => $wgRequest->getText( 'owa_session', null ),
 56+ '@owa_ref', // => $owa_ref,
 57+ // Not actually data tokens, but available to you in html form:
 58+ // @captcha -> the captcha form
 59+ // @script_path -> maps to $wgScriptPath
 60+ // @action -> generate correct form action for this form
 61+ );
13762
138 - // replace data
139 - foreach ( $this->data_tokens as $token ) {
140 - $key = substr( $token, 1, strlen( $token )); //get the token string w/o the '@'
141 - if ( $key == 'emailAdd' ) $key = 'email';
142 - if ( $key == 'currency_code' ) $key = 'currency';
143 - if ( array_key_exists( $key, $this->form_data )) {
144 - $replace = $this->form_data[ $key ];
145 - } else {
146 - $replace = '';
147 - }
148 - $form = str_replace( $token, $replace, $form );
149 - }
150 -
151 - // replace errors
152 - $form = str_replace( $this->error_tokens, $this->form_errors, $form );
 63+ /**
 64+ * Error field names used as tokens
 65+ * @var array
 66+ */
 67+ protected $error_tokens = array(
 68+ '#general',
 69+ '#retryMsg',
 70+ '#amount',
 71+ '#card_num',
 72+ '#card',
 73+ '#cvv',
 74+ '#fname',
 75+ '#lname',
 76+ '#city',
 77+ '#country',
 78+ '#street',
 79+ '#state',
 80+ '#zip',
 81+ '#emailAdd',
 82+ );
15383
154 - // handle captcha
155 - $form = str_replace( "@captcha", $this->getCaptchaHtml(), $form );
156 -
157 - // handle script path
158 - $form = str_replace( "@script_path", $wgScriptPath, $form );
159 -
160 - $form = $this->fix_dropdowns( $form );
161 -
162 - return $form;
163 - }
 84+ public function __construct(&$form_data, &$form_errors)
 85+ {
 86+ global $wgRequest;
 87+ parent::__construct($form_data, $form_errors);
16488
165 - /**
166 - * Set dropdowns to 'selected' where appropriate
167 - *
168 - * This is basically a hackish fix to make sure that dropdowns stay
169 - * 'sticky' on form submit. This could no doubt be better.
170 - * @param $html
171 - * @return string
172 - */
173 - public function fix_dropdowns( $html ) {
174 - // currency code
175 - $start = strpos( $html, 'name="currency_code"' );
176 - if ( $start ) {
177 - $currency_code = $this->form_data[ 'currency' ];
178 - $end = strpos( $html, '</select>', $start );
179 - $str = substr( $html, $start, ( $end - $start ));
180 - $str = str_replace( 'value="' . $currency_code . '"', 'value="' . $currency_code . '" selected="selected"', $str );
181 - $html = substr_replace( $html, $str, $start, $end-$start );
182 - }
183 -
184 - // mos
185 - $month = substr( $this->form_data[ 'expiration' ], 0, 2 );
186 - $start = strpos( $html, 'name="mos"' );
187 - if ( $start ) {
188 - $end = strpos( $html, '</select>', $start );
189 - $str = substr( $html, $start, ( $end - $start ));
190 - $str = str_replace( 'value="' . $month . '"', 'value="' . $month . '" selected="selected"', $str );
191 - $html = substr_replace( $html, $str, $start, $end-$start );
192 - }
193 -
194 - // year
195 - $year = substr( $this->form_data[ 'expiration' ], 2, 2 );
196 - $start = strpos( $html, 'name="year"' );
197 - if ( $start ) {
198 - $end = strpos( $html, '</select>', $start );
199 - $str = substr( $html, $start, ( $end - $start ));
200 - // dbl extra huge hack alert! note the '20' prefix...
201 - $str = str_replace( 'value="20' . $year . '"', 'value="20' . $year . '" selected="selected"', $str );
202 - $html = substr_replace( $html, $str, $start, $end-$start );
203 - }
204 -
205 - // state
206 - $state = $this->form_data[ 'state' ];
207 - $start = strpos( $html, 'name="state"' );
208 - if ( $start ) {
209 - $end = strpos( $html, '</select>', $start );
210 - $str = substr( $html, $start, ( $end - $start ));
211 - $str = str_replace( 'value="' . $state . '"', 'value="' . $state . '" selected="selected"', $str );
212 - $html = substr_replace( $html, $str, $start, $end-$start );
213 - }
214 -
215 - //country
216 - $country = $this->form_data[ 'country' ];
217 - $start = strpos( $html, 'name="country"' );
218 - if ( $start ) {
219 - $end = strpos( $html, '</select>', $start );
220 - $str = substr( $html, $start, ( $end - $start ));
221 - $str = str_replace( 'value="' . $country . '"', 'value="' . $country . '" selected="selected"', $str );
222 - $html = substr_replace( $html, $str, $start, $end-$start );
223 - }
224 -
225 - return $html;
226 - }
227 -
228 - /**
229 - * Validate and set the path to the HTML file
230 - *
231 - * @param string $file_name
232 - */
233 - public function set_html_file_path( $file_name ) {
234 - global $wgPayflowHtmlFormDir, $wgPayflowAllowedHtmlForms;
 89+ $this->loadValidateJs();
23590
236 - // Get the dirname - the "/." helps ensure we get a consistent path name with no trailing slash
237 - $html_dir = dirname( $wgPayflowHtmlFormDir . "/." );
238 -
239 - if ( !is_dir( $html_dir )) {
240 - throw new MWException( 'Requested form directory does not exist.' );
241 - }
242 -
243 - // make sure our file name is clean - strip extension and any other cruft like relpaths, dirs, etc
244 - $file_info = pathinfo( $file_name );
245 - $file_name = $file_info[ 'filename' ];
246 -
247 - $full_path = $html_dir . '/' . $file_name . '.html';
248 -
249 - // ensure that the full file path is actually whitelisted and exists
250 - if ( !in_array( $full_path, $wgPayflowAllowedHtmlForms ) || !file_exists( $full_path ) ) {
251 - throw new MWException( 'Requested an unavailable or non-existent form.' );
252 - }
253 -
254 - $this->html_file_path = $full_path;
255 - }
256 -
257 - /**
258 - * Load API js if this form needs to support cacheing
259 - */
260 - public function handle_cacheability() {
261 - global $wgRequest;
262 - if ( $wgRequest->getText( '_cache_', false )) {
263 - $this->loadApiJs();
264 - }
265 - }
 91+ // set html-escaped filename.
 92+ $this->set_html_file_path(htmlspecialchars($wgRequest->getText('ffname', 'default')));
 93+
 94+ // fix general form error messages so it's not an array of msgs
 95+ if (is_array($form_errors['general']) && count($form_errors['general'])) {
 96+ $general_errors = "";
 97+ foreach ($form_errors['general'] as $general_error) {
 98+ $general_errors .= "<p class='creditcard'>$general_error</p>";
 99+ }
 100+ $form_errors['general'] = $general_errors;
 101+ }
 102+
 103+ // if this form needs to support squid cacheing, handle the magic
 104+ $this->handle_cacheability();
 105+ }
 106+
 107+ /**
 108+ * Return the HTML form with data added
 109+ */
 110+ public function getForm()
 111+ {
 112+ $html = $this->load_html();
 113+ return $this->add_data($html);
 114+ }
 115+
 116+ /**
 117+ * Load the HTML form from a file into a string
 118+ * @return string
 119+ */
 120+ public function load_html()
 121+ {
 122+ return file_get_contents($this->html_file_path);
 123+ }
 124+
 125+ /**
 126+ * Add data into the HTML form
 127+ *
 128+ * @param string $html Form with tokens as placehodlers for data
 129+ * @return string The HTML form with real data in it
 130+ */
 131+ public function add_data($html)
 132+ {
 133+ global $wgScriptPath;
 134+
 135+ /**
 136+ * This is a hack and should be replaced with something more performant.
 137+ */
 138+ $form = $html;
 139+
 140+ // handle form action
 141+ $form = str_replace("@action", $this->getNoCacheAction(), $form);
 142+
 143+ // replace data8
 144+ foreach ($this->data_tokens as $token) {
 145+ $key = substr($token, 1, strlen($token)); //get the token string w/o the '@'
 146+ if ($key == 'emailAdd') $key = 'email';
 147+ if ($key == 'currency_code') $key = 'currency';
 148+ if (array_key_exists($key, $this->form_data)) {
 149+ $replace = $this->form_data[$key];
 150+ } else {
 151+ $replace = '';
 152+ }
 153+ $form = str_replace($token, $replace, $form);
 154+ }
 155+
 156+ // @fixme why do some errors have HTML in them
 157+ // replace errors|escape with escaped versions
 158+ $escape_error_tokens = array();
 159+ foreach( $this->error_tokens as $token ){
 160+ $escape_error_tokens[] = "$token|escape";
 161+ }
 162+ $escape_errors = array();
 163+ foreach( $this->form_errors as $error ){
 164+ $escape_errors[] = addslashes($error);
 165+ }
 166+ $form = str_replace($escape_error_tokens, $escape_errors, $form);
 167+
 168+ // replace standard errors
 169+ $form = str_replace($this->error_tokens, $this->form_errors, $form);
 170+
 171+ // handle captcha
 172+ $form = str_replace("@captcha", $this->getCaptchaHtml(), $form);
 173+
 174+ // handle script path
 175+ $form = str_replace("@script_path", $wgScriptPath, $form);
 176+
 177+ $form = $this->fix_dropdowns($form);
 178+
 179+ return $form;
 180+ }
 181+
 182+ /**
 183+ * Set dropdowns to 'selected' where appropriate
 184+ *
 185+ * This is basically a hackish fix to make sure that dropdowns stay
 186+ * 'sticky' on form submit. This could no doubt be better.
 187+ * @param $html
 188+ * @return string
 189+ */
 190+ public function fix_dropdowns($html)
 191+ {
 192+ // currency code
 193+ $start = strpos($html, 'name="currency_code"');
 194+ if ($start) {
 195+ $currency_code = $this->form_data['currency'];
 196+ $end = strpos($html, '</select>', $start);
 197+ $str = substr($html, $start, ($end - $start));
 198+ $str = str_replace('value="' . $currency_code . '"', 'value="' . $currency_code . '" selected="selected"', $str);
 199+ $html = substr_replace($html, $str, $start, $end - $start);
 200+ }
 201+
 202+ // mos
 203+ $month = substr($this->form_data['expiration'], 0, 2);
 204+ $start = strpos($html, 'name="mos"');
 205+ if ($start) {
 206+ $end = strpos($html, '</select>', $start);
 207+ $str = substr($html, $start, ($end - $start));
 208+ $str = str_replace('value="' . $month . '"', 'value="' . $month . '" selected="selected"', $str);
 209+ $html = substr_replace($html, $str, $start, $end - $start);
 210+ }
 211+
 212+ // year
 213+ $year = substr($this->form_data['expiration'], 2, 2);
 214+ $start = strpos($html, 'name="year"');
 215+ if ($start) {
 216+ $end = strpos($html, '</select>', $start);
 217+ $str = substr($html, $start, ($end - $start));
 218+ // dbl extra huge hack alert! note the '20' prefix...
 219+ $str = str_replace('value="20' . $year . '"', 'value="20' . $year . '" selected="selected"', $str);
 220+ $html = substr_replace($html, $str, $start, $end - $start);
 221+ }
 222+
 223+ // state
 224+ $state = $this->form_data['state'];
 225+ $start = strpos($html, 'name="state"');
 226+ if ($start) {
 227+ $end = strpos($html, '</select>', $start);
 228+ $str = substr($html, $start, ($end - $start));
 229+ $str = str_replace('value="' . $state . '"', 'value="' . $state . '" selected="selected"', $str);
 230+ $html = substr_replace($html, $str, $start, $end - $start);
 231+ }
 232+
 233+ //country
 234+ $country = $this->form_data['country'];
 235+ $start = strpos($html, 'name="country"');
 236+ if ($start) {
 237+ $end = strpos($html, '</select>', $start);
 238+ $str = substr($html, $start, ($end - $start));
 239+ $str = str_replace('value="' . $country . '"', 'value="' . $country . '" selected="selected"', $str);
 240+ $html = substr_replace($html, $str, $start, $end - $start);
 241+ }
 242+
 243+ return $html;
 244+ }
 245+
 246+ /**
 247+ * Validate and set the path to the HTML file
 248+ *
 249+ * @param string $file_name
 250+ */
 251+ public function set_html_file_path($file_name)
 252+ {
 253+ global $wgPayflowHtmlFormDir, $wgPayflowAllowedHtmlForms;
 254+
 255+ // Get the dirname - the "/." helps ensure we get a consistent path name with no trailing slash
 256+ $html_dir = dirname($wgPayflowHtmlFormDir . "/.");
 257+
 258+ if (!is_dir($html_dir)) {
 259+ throw new MWException('Requested form directory does not exist.');
 260+ }
 261+
 262+ // make sure our file name is clean - strip extension and any other cruft like relpaths, dirs, etc
 263+ $file_info = pathinfo($file_name);
 264+ $file_name = $file_info['filename'];
 265+
 266+ $full_path = $html_dir . '/' . $file_name . '.html';
 267+
 268+ // ensure that the full file path is actually whitelisted and exists
 269+ if (!in_array($full_path, $wgPayflowAllowedHtmlForms) || !file_exists($full_path)) {
 270+ throw new MWException('Requested an unavailable or non-existent form.');
 271+ }
 272+
 273+ $this->html_file_path = $full_path;
 274+ }
 275+
 276+ /**
 277+ * Load API js if this form needs to support cacheing
 278+ */
 279+ public function handle_cacheability()
 280+ {
 281+ global $wgRequest;
 282+ if ($wgRequest->getText('_cache_', false)) {
 283+ $this->loadApiJs();
 284+ }
 285+ }
266286 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r97832Self-revert, accidental tabs->spacespgehres18:09, 22 September 2011
r97835Begining to modularize form validation. Adding the ability to escape error t...pgehres18:55, 22 September 2011
r97836Adding back webitects form for this week as well as some fixes for PayPal don...pgehres18:57, 22 September 2011

Comments

#Comment by Awjrichards (talk | contribs)   17:18, 22 September 2011

The field name 'currency' gets used in multiple places throughout here - it should be 'currency_code'. This is what is expected by DonationInterface. In the form, I see you are creating hidden fields for both 'currency' and 'currency_code', but only 'currency' is getting posted at form submission, likely due to the Javascript magic at the end of the form file.

Also, with RapidHtml forms, the PayPal redirect needs to be handled differently than with the landing pages:

+                        // set the action to go to PayPal
+			    		/******************
+		    			 ** TODO: FIX ME **  (Broken on return to form from PP and then choose CC)
+		    			 ******************/
+			    		$("input[name=gateway]").val("paypal");
+			    		document.paypalcontribution.action = "[https://wikimediafoundation.org/wiki/Special:ContributionTracking/en https://wikimediafoundation.org/wiki/Special:ContributionTracking/en]";
+						$("#loading").html("<img src='../images/loading.gif' /> Redirecting to PayPal…");
+			    		document.paypalcontribution.submit();
+					}
+			    });

iirc, the PayPal redirect should happen via DonationInterface to ensure tracking data is properly set. the 'PaypalRedirect' should get set to true and posted back to DonationInterface, which should take care of the rest.

Also, you seem to have changed from tabs -> spaces in RapidHtml.php, which I believe is why the diff is showing that the entire file changed. Besides being counter to MediaWiki convention (http://www.mediawiki.org/wiki/Coding_conventions#File_formatting), this means I cannot easily code review this file. Please fix.

Status & tagging log