Contributing to Magento2

The Magento2 dev team is now using Github in the traditional sense: They have an internal repo that gets pushed out to github at the end of their sprint. All commits stay intact. This is WAY better than the previous method of pushing a giant commit with everything each sprint.

Ben has a good walkthrough on submitting a pull request to the repo. He links to a few resources to get up and running on the new platform.  Alan Kent goes into more detail on the “why” of the change.

It’s not just code that has been opened up. The documentation lives on Github now too.

These are all great changes. The more eyes we have on code the better. Do your part: Install the Magento 2 developer preview and get testing

Apple Pay and Magento

The Business of Apple Pay (Alec Simonson)

On the outset, Apple Pay is very cool and could very well be the wave of the future. A lot of this hinges on “what’s under the hood” in terms of Apple’s contract with the leading credit card companies who helped with the development. If everything is open, and companies like Samsung can let their customers pay with NFC technology as well, I could see this as something that will be successful, adopted, and an example of Apple leading the way. However, if Apple goes all proprietary (as they love to do) and contractually forces these major credit cards to only use their devices, or charges other companies like Samsung to license their payment platform, or otherwise mandate that all touch-to-pay via smartphone methods are hereby known as “Apple Pay,” I could see adoption problems happening. Open standards have frequently been key to paving the way to adoption, and this has never really been Apple’s model in the past. For example, AirPlay is really cool and loved but does not work outside the environs of iOS, and can therefore never reach greater than 14.8% penetration as of this writing. So Chromecast was born, and while not nearly as simple or feature rich, it’s open to both Android and iOS and therefore has a much higher potential of adoption. Feature expansion will follow.

One of the aspects of Apple Pay that I think is great is that merchants aren’t really troubled with much of everything, since most of this is really on the backend. A new reader with NFC capabilities, and they’re off and running. Low cost or no cost adoption. Or is it? Nobody has mentioned what Apple’s commission is on this latest development. An article on Forbes suggested it may be around 0.2%, giving Apple $0.20 for every $100 spent. That’s not much, but when you consider what percentage that is of the credit card companies’ net (perhaps around 14%), it starts to look more substantial. Credit card companies like their investors, so it’s hard to imagine them not wanting to pass that extra cost onto merchants, who will be all-too-willing to share that with consumers.

All of that aside, it’s very smart and forward thinking, and early adopters will likely be looked upon with jealousy by others. From an implementation perspective, adding Apple Pay will likely be as easy as it was to add Google+, and merchants will do it. But the long-term prospects will rely highly on what sort of deal Apple made….the devil is always in the details.

The Technology of Apple Pay (Tim Broder)

Out of the gate, Pay is native app only. This leaves Magento sites at a disadvantage. In the future I’d like to see Apple open up this functionality to Safari on both mobile and desktop. Pay already has one-time number generation. This could be implemented in the browser similar to how [1Password](https://itunes.apple.com/us/app/1password-password- manager/id443987910?mt=12&at=11laRZ&ct=pro) can inject a credit card number into a form. Until something like this happens, only sites with a native app siting in front of Magento’s API will be able to take advantage.  If you are looking to investigate this space, meets.io, an unofficial Magento SDK, is a great starting point.

I’ll be curious if a developer comes up with a browser dedicated to this functionality. Tap into the Pay API and generate credit card numbers ad hoc, and bridge between Pay and e-commerce sites. Or, take it a step further and develop a custom keyboard for iOS 8. If allowed, it would be more seamless than a whole seperate browser. I say “if allowed” because there are some restrictions on what 3rd party keyboard can do. For example, they cannot touch passwords. The stock keyboard reasserts itself when tapping on a password field.

Improve your Magento workflow: Use git or mercurial

Most of our new projects at work are on mercurial and I've moved most of my personal projects over to git.  We do, unfortunately, still have one Magento install that lives in our old subversion repository.  If you've ever tried to work with a project the size of Magento in SVN with branching, you know the kind of pain this can cause. My machine at work is no slouch. An i7, 8 gigs of ram, 256 megs graphics card, and an SSD. Perfect for any number of high performance or online games, compiling, or video editing. Yet, switching branches on the mercurial project brings it to its knees.  It's honestly better to go shoot a quick game of pool while its switching rather then try to get anything done.  Eventually... we'll get it into mercurial. Anyway, to migrate a project from svn to git, use the following command: [code]git svn clone http://svn/repo/here/trunk[/code] To migrate a project from svn to hg, use the following command: hg convert http://svn/repo/here/trunk

Branching is now much, much easier and if that isn't enough for you to switch here are a few more reasons:

  • git is much easier to use than when it first came out
  • merging is exponentially smoother than SVN
  • distributed: you can branch, merge, commit, revert all locally without effecting your team until you push. All this happens locally = faster
  • you can work offline
  • can centralize only if you want to
  • branching takes on a whole new level. Create custom workflows base on release, or bug, or whatever you want
  • merging is exponentially smoother than SVN (yes, I listed this twice)
  • visual branch diagrams

Important Magento Security Update – Zend Platform Vulnerability

While doing routine sanity checks, on of our QA Engineers, Sammy Shaar, was alerted about an important Magento security update. The vulnerability potentially allows an attacker to read any file on the web server where the Zend XMLRPC functionality is enabled. This might include password files, configuration files, and possibly even databases if they are stored on the same machine as the Magento web server. To see if you site has been affected, please see this page. Luckily, Magento has released patches for all supported versions:

  • Magento Enterprise Edition and Professional Edition merchants: You may access the Zend Security Upgrade patch from Patches & Support for your product in the Downloads section of your Magento account. Account log-in is required. Download
  • Magento Community Edition merchants: Community Edition 1.4.0.0 through 1.4.1.1 Community Edition 1.4.2.0 Community Edition 1.5.0.0 through 1.7.0.1 To install the patch, place the patch file in the root of your Magento site and run the following command: patch -p0 < zendxml_fix.patch If you don't have ssh access or patch installed on your machine, please see this stack overflow post for alternative methods.

Creating a stateless request in Magento

Have you ever wanted to create a stateless request in Magento? Something that doesn't touch any of Magento's sessions?  We were having issues with some of the ajax calls on our cart and checkout pages mucking with the user's cart and had get stateless on these calls.  The issue we were having was our checkout page was loading, then a javascript include was going out and bringing code from a 3rd party relevance engine into our dom, which was in turn calling back an ajax request to our servers.  This issue with this being that at the start of the page load, the checkout session was being set to a certain state.  This state was then being sent through the rest of the page load, and the ajax calls. Unfortunately, by the time the ajax call got back to our server, the session was different in both locations, creating a race condition.  The ajax request usually won, removing the work the full page load had done with trying to process checkout.  The good news was there was nothing in the ajax call that needed to touch the session, it was just some data lookup. So, nix the session part of that call, and our troubles should be over... Magento's api controller is the only place that implements a stateless request this but its fairly easy to do (after a bit of digging).

As long as Mage_Core_Controller_Varien_Action is a parent in your controller's hierchy, you are good to go (it probably is).  This class has a const FLAG_NO_START_SESSION which looks promising. Digging into the code a little we see that it controls whether cookies are processed or the session is started:

<?php
...
        if (!$this->getFlag('', self::FLAG_NO_START_SESSION)) {
            $checkCookie = in_array($this->getRequest()->getActionName(), $this->_cookieCheckActions);
            $checkCookie = $checkCookie &amp;&amp; !$this->getRequest()->getParam('nocookie', false);
            $cookies = Mage::getSingleton('core/cookie')->get();
            if ($checkCookie &amp;&amp; empty($cookies)) {
                $this->setFlag('', self::FLAG_NO_COOKIES_REDIRECT, true);
            }
            Mage::getSingleton('core/session', array('name' => $this->_sessionNamespace))->start();
        }

By adding to the preDispatch() method of our Action or Controller we can toggle this:

<?php
class Ai_AjaxCatalog_Controller_Action extends Mage_Core_Controller_Front_Action
{
    public function preDispatch()
    {
        $this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standard session
        parent::preDispatch();
        return $this;
    }
}

Now, any action in this controller will be stateless and not effect any sessions.

Extending a Magento Controller

We're ajaxing part of the Magento shopping cart so we need to modify/extend some of the cart controller functionality.  Sometimes when modifying controller's you have to worry about updating the routes. For this, we don't need to, we still want all the urls to be used the same way.

app/code/local/Ai/Checkout/etc/config.xml:

<config>
    <modules>
        <Ai_Checkout>
             <version>0.0.1</version>
        </Ai_Checkout>
    </modules>
...
    <frontend>
        <routers>
            <checkout>
                <use>standard</use>
                <args>
                    <module>Ai_Checkout</module>
                    <frontName>checkout</frontName>
                </args>
            </checkout>
        </routers>
    </frontend>    
</config>

app/code/local/Ai/Checkout/controllers/CartController.php:

```PHP require_once Mage::getModuleDir('controllers', 'Mage_Checkout') . DS . 'CartController.php';

class Ai_Checkout_CartController extends Mage_Checkout_CartController { public function updatePostAction() { Mage::log("NEW CONTROLLER", null, 'tim.log'); try { [/php]

Want to trace the call stack in Magento?

Update: This code is also available on Github as a Mageno module

This has helped me immensely in situations like "Where is this getting called from??!?"

Create a helper like so:

class Timbroder_Stack_Helper_Callstack extends Mage_Core_Helper_Abstract
{
    private function get_callstack($delim=&quot;\n&quot;) {
      $dt = debug_backtrace();
      $cs = '';
      foreach ($dt as $t) {
        $cs .= $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . &quot;()&quot; . $delim;
      }

      return $cs;
    }

    public function toLog() {
        Mage::log($this-&gt;get_callstack());
    }

    public function toFirePhp() {
        $stack = $this-&gt;get_callstack();
        foreach (explode(&quot;\n&quot;, $stack) as $line) {
            Mage::helper('firephp')-&gt;send($line);
        }
    }
}

That can be called from anywhere:

``PHP Mage::helper('stack/callstack')->toFirePhp(); Mage::helper('stack/callstack')->toLog();


I've also wrapped this into a module that you can drop right into your project. Details here: [https://bitbucket.org/broderboy/magento_callstack/src](https://bitbucket.org/broderboy/magento_callstack/src "https://bitbucket.org/broderboy/magento_callstack/src") Example output:

.../app/code/community/Timbroder/Stack/Helper/Callstack.php line 16 calls get_callstack() .../app/design/frontend/mongoose/default/template/catalog/cms/bikes_bmx.phtml line 12 calls toLog() .../app/design/frontend/mongoose/default/template/catalog/cms/bikes.phtml line 21 calls require_once() .../app/code/core/Mage/Core/Block/Template.php line 212 calls include() .../app/code/core/Mage/Core/Block/Template.php line 239 calls fetchView() .../app/code/core/Mage/Core/Block/Template.php line 253 calls renderView() .../app/code/core/Mage/Core/Block/Abstract.php line 668 calls _toHtml() .../app/code/core/Mage/Core/Model/Email/Template/Filter.php line 190 calls toHtml() .../lib/Varien/Filter/Template.php line 134 calls call_user_func() .../app/code/core/Mage/Core/Model/Email/Template/Filter.php line 501 calls filter() .../app/code/core/Mage/Cms/Block/Page.php line 100 calls filter() .../app/code/core/Mage/Core/Block/Abstract.php line 668 calls _toHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 513 calls toHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 460 calls _getChildHtml() .../app/code/local/Mage/Page/Block/Html/Wrapper.php line 52 calls getChildHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 668 calls _toHtml() .../app/code/core/Mage/Core/Block/Text/List.php line 43 calls toHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 668 calls _toHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 513 calls toHtml() .../app/code/core/Mage/Core/Block/Abstract.php line 464 calls _getChildHtml() .../app/design/frontend/mongoose/default/template/page/1column.phtml line 55 calls getChildHtml() .../app/code/core/Mage/Core/Block/Template.php line 212 calls include() .../app/code/core/Mage/Core/Block/Template.php line 239 calls fetchView() .../app/code/core/Mage/Core/Block/Template.php line 253 calls renderView() .../app/code/core/Mage/Core/Block/Abstract.php line 668 calls _toHtml() .../app/code/core/Mage/Core/Model/Layout.php line 529 calls toHtml() .../app/code/local/Mage/Core/Controller/Varien/Action.php line 389 calls getOutput() .../app/code/core/Mage/Cms/Helper/Page.php line 130 calls renderLayout() .../app/code/core/Mage/Cms/Helper/Page.php line 52 calls _renderPage() .../app/code/core/Mage/Cms/controllers/PageController.php line 45 calls renderPage() .../app/code/local/Mage/Core/Controller/Varien/Action.php line 418 calls viewAction() .../app/code/core/Mage/Core/Controller/Varien/Router/Standard.php line 254 calls dispatch() .../app/code/core/Mage/Core/Controller/Varien/Front.php line 177 calls match() .../app/code/core/Mage/Core/Model/App.php line 304 calls dispatch() .../app/Mage.php line 598 calls run() .../index.php line 155 calls run() ```

Thanks to nextide for some of the code

Want to dump every SQL query Magento runs?

In: lib/Zend/DB/Adapter/Adapter.php

public function query($sql, $bind = array())
{
    // connect to the database if needed
    $this->_connect();

    // is the $sql a Zend_Db_Select object?
    if ($sql instanceof Zend_Db_Select) {
        if (empty($bind)) {
            $bind = $sql->getBind();
        }

        $sql = $sql->assemble();
    }

    $time_start = microtime(true);

    // make sure $bind to an array;
    // don't use (array) typecasting because
    // because $bind may be a Zend_Db_Expr object
    if (!is_array($bind)) {
        $bind = array($bind);
    }

    // prepare and execute the statement with profiling
    $stmt = $this->prepare($sql);
    $stmt->execute($bind);

    // return the results embedded in the prepared statement object
    $stmt->setFetchMode($this->_fetchMode);

    $time_end = microtime(true);
    $time = $time_end - $time_start;

    echo "SQL[$time | $sql ]" . "\n<br />\n";
    return $stmt;
}