Adding website/store filter to category product grid in Magento

It appears the Magento developers didn’t think this one through enitrely as this to me is something that should be there by standard. Not everyone has a multi-website set up and products that span two stores, yet that’s the very reason this kind of thing can be a pain to add on not just here but also in the main catalog view and in other views like reports.

website_filter

I am detailing this by editing core files, this is not the correct way and should be added via a module or local override, which in this case would be very little extra work,  but in essence the steps you need to take are modifying/overriding

Mage_Adminhtml_Block_Catalog_Category_Tab_Product

First find the function

_addColumnFilterToCollection

Add the following if statement at the top, this is checking for our column which we later add and looking up the website ID’s

 if ($column->getId() == 'website_id') {
            $this->getCollection()->joinField('websites',
                'catalog/product_website',
                'website_id',
                'product_id=entity_id',
                null,
                'left');
            return parent::_addColumnFilterToCollection($column);
        }

At the bottom of the function you need to modify the lines like so, to bring in the website names.

parent::_prepareCollection();
$this->getCollection()->addWebsiteNamesToResult();
return $this;

Next add a new function directly underneath the above, this is a custom column callback for our new column which we add next, which is simply a way of adding more criteria onto our $collection, in this case we add the store filter.

   protected function _websiteFilter($collection, $column)
    {

        if (!$value = $column->getFilter()->getValue()) {
            return $this;
        }

        $store = Mage::app()->getWebsite($value);
        $collection->addStoreFilter($value);

        return $this;
    }

Finally add the website column, with our custom filter callback

  if (!Mage::app()->isSingleStoreMode()) {
                         $this->addColumn('websites',
                                 array(
                                     'header'=> Mage::helper('catalog')->__('Websites'),
                     'width' => '100px',
                     'sortable'  => false,
                     'index'     => 'websites',
                     'type'      => 'options',
                     'options'   => Mage::getModel('core/website')->getCollection()->toOptionHash(),
                                     'filter_condition_callback' => array($this, '_websiteFilter'),
             ));
         }

And you’re done.

Module_Helper_Data not found any module magento

If you receive the Helper_Data.. not found message when trying to install a new module either manually or through the Downloader and get this message it’s simply a case of disabling Compilation mode before enabling the new module.

Quick and simple one, might be overlooked if you don’t tend to use Compilation mode, but that’s all you need to do simply disable compilation mode.

 

Magento getFinalPrice by customer group

If you use group pricing you will find that getFinalPrice does not return the correct price.

This is easy to correct by adding

$product->setCustomerGroupId(0);

Before calling getFinalPrice(); 0 being the default customer group or replace with the group of your choice.

Optimising WordPress for PageSpeed Insights

Recently I was commissioned to optimise a WordPress site on behalf of an SEO agency. This usually consists of reports from Google’s pagespeed insights and there’s a number of things you can do to increase the speed.

pagespeed

Before you start you should first check that the foundations are correct.

Enqueue

For example all JS and CSS files are properly enqueued in WordPress we will later need to work on minifying and combining these into one file.

HTML Structure

Ensure important page elements are near the top, move your html around if required and ensure that your CSS files are ordered in the way the page loads you might want to break the css up into two files. The first loading important structure e.g header, body content etc.. The second appearing in the footer loading the remaining part of the site.

Onto the optimisation

Optimise images

The next thing you want to look at is image optimisation there’s a plugin you can install that optimises all image uploads as you upload them which in turn utilises some command line tools to compress images e.g optipng and jpegoptim. You also need to run these tools on the existing image library.

Set an expiry on assets through nginx or apache or alternatively just use Cloudflare or any CDN of your choice.

Minify HTML

HTML Minify https://github.com/cferdinandi/html-minify does a decent job of minimising your html.

Minify CSS/JS

You then need to install a plugin to combine your css/js and again work on the order here to ensure the right delivery.

Blocking

Fonts are often blocking resources, consider using Google’s Font API instead and anything else that isn’t critical either defer or move to the bottom of the page.

A lot of the above can also be achieved in part of in full by Google’s pagespeed module you’ll achieve better results though by doing each part onsite.

Image resizing

If you have any scripts that work with images e.g sizing images on the fly or creating thumbnails and have a very large amount of images either through the creation of different sizes or in total watch out for anything that reads the folder they are contained in as this can put a serious performance hit on your server.

Magento collection filtered

Here’s a simple setup for a product collection with the following filters used in most of my modules, ideal for things like product feeds etc.

It has the following filters

– By Store
– Must have price > 0
– Must cost > 0
– Only simple products
– Visible either Catalog,Search or Both

$visibility = array(
    Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
    Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG,
    Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH
);

$storeId = 1;
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->getEntity()->setStoreId($storeId);

// Reset the select.
$collection->getSelect()->reset();

// Update table name.
$reflectionMethod = new ReflectionMethod($collection, '_initSelect');
$reflectionMethod->setAccessible(true);
$reflectionMethod->invoke($collection);

$collection
 ->addAttributeToSelect('sku')
 ->addAttributeToSelect('name')
 ->addAttributeToSelect('description')
 ->addAttributeToSelect('small_image')
 ->addAttributeToSelect('manufacturer')
 ->addAttributeToSelect('msrp')
 ->addAttributeToFilter('visibility', $visibility)
 ->addAttributeToFilter('status', '1')
 ->addAttributeToFilter('type_id', array('eq' => 'simple'))
 ->addFinalPrice()
 ->setPageSize(900000)
 ->setCurPage(1);

Full Stack Frontend catchup & workflow

I have come to the realisation recently I’m more of a full stack developer. Taking some time recently to run through the recent developments in frontend if you haven’t explored this area for a while you will find it’s moved on quite a bit.

What you need to know:

Get familiar with npm and node-js because you will be using them a lot, of course it isn’t the only package manager out there and more for frontend dev’s is bower the debate is still out on which is best. If you want a good explanation of both see this Stackoverflow answer what’s the difference between node-js and bower? you can of course use the tools together.

Just like composer for php and other languages that now user composer type tools these help you manage your dependencies.

Along with these you can use further bundled packages that in their own way try to speed up development e.g INIT and Yeoman. INIT bundles together HTML5 Boilerplate, Bower and Grunt and some other things to give you a head start there are many others out there. Yeoman sort of serves as library manager for installing these, all of the above act like a scaffolding for a new project.

If you’ve barely touched Grunt , you would be better starting off writing your own Grunt config and learning about how underlying tools work you would be surprised how easy it is.

There’s also Gulp which is very similar to Grunt it’s good to give both a try as different agencies may have a preference. What they allow you to do is pull off some impressive automation into your development for example maintaining a /build folder structure from the same source dir and having different process’s, files, settings etc for each e.g a testing scenario vs a live build. Some common tasks like css/js compression, whitespace removal, concatenating a bunch of files together basically giving you a squeaky clean page structure which can be run every time you make changes to your project through a one line command.

But the really clever stuff is automating things like changing your URL’s to a CDN , compressing images, minifying html etc.. Roll in automated testing, compiling sass, less, copying files, compiling html and even run other command line tools.

There’s still some lively debate about which is best, but they both have good support and achieve the same outcome only currently gulp has some performance advantages that I think only apply to large projects, so as always it may be a decision based on the project.

What else is current:

JS

Most dev’s will have worked on some project or another that used Angular, Backbone or some other MVC based framework I gave Agility.js a go last year, Angular is definitely looking pretty strong and backed by Google it’s likely to grow further it’s pretty popular in job listings as well.

ECMAScript was released this month (June 17th 2015) what it brings to JS is classes and a ton of other features see http://es6-features.org/ or there’s a good overview of the main changes with some examples here or view the full spec you don’t have to wait till it’s safe to use it, there are many compilers (Babeljs) that offer backward compatibility allowing you to use it today.

CSS/HTML

There’s still plenty of frameworks popping up with Bootstrap, Foundation, Semantic UI, Pure, Inuit, UI Kit all serve different needs some more basic than others, my framework of choice for frontend websites is Foundation as the name suggests it feels solid and seems to offer just the right balance of components but not feeling too bloated.

By now your very familiar with transitions, drop-shadows and all that CSS3 brought, CSS4 is on the horizon it’s still a working draft so it’s not worth spending more than a glance on what it might have to offer at this stage as you would still have to polyfill some of CSS3’s features for older browsers.

Mostly pain free features that you could be using:

  • SVG with IE8 Polyfill (npm install grunt-badass –save-dev)
  • vh/vw useful for fullscreen layouts (https://github.com/saabi/vminpoly)
  • Semantic markup (that’s a given by now)
  • HTML5 form (mostly ok IE9 lacks support without polyfill)

Here’s a set up for a small mainly static project I recently developed:

Technology Stack

  • Nginx
  • PHP5-FPM
  • Rackspace Load Balancer
  • Lsyncd
  • MySQL
  • Cloudflare
  • Modernizr
  • Angular JS
  • Foundation 5
  • JQuery
  • Typekit

Folder Structure

  • /project/app
  • /project/app/api
  • /project/app/assets
  • /project/app/assets/css
  • /project/app/assets/fonts
  • /project/app/assets/img
  • /project/app/assets/js
  • /project/app/views
  • /project/app/views/partials
  • /project/src
  • /project/src/js
  • /project/src/img
  • /project/src/sass

Development Tools

  • Phpstorm
  • Browserstack
  • New Relic
  • Blitz.io
  • Virtual Box
  • Ampps
  • LiveReload

gitignore

node_modules
.npm-debug.log
tmp
bower_components
.sass-cache

Grunt build tasks

grunt.registerTask('build', ['clean', 'jshint', 'sass', 'concat', 'cssmin', 'copy','uglify','htmlmin', 'cdnify', 'svgmin'])
grunt.registerTask('test', ['jshint', 'sass', 'concat', 'copy','uglify']

The benefit or running all this stuff can be seen by putting your site through Pagespeed Insights it can become an obsession to get the highest score possible but at the end the speed is worth it.

There are some caveats:

  • IE8/9 can only read a maximum of around 280kb in file size or 4096 rules so putting everything into one file might not be possible at least that’s true for CSS files
  • If your using concat and pre-minifed versions of your JS dependencies make sure to use the separator option to prevent errors
    separator: ';\n',
  • Crushing everything into one file might not be the best for your project, as if everything is efficiently structured, you can utilise the browsers connections better by splitting them into a few files e.g app.js, index.js etc.. furthermore you can use things like https://github.com/ocombe/ocLazyLoad or RequireJS to load files as you need them. But ideally if you can achieve a small file size and one file that’s the goal
  • Angular JS does not support IE8
  • SVG not supported in IE8
  • Using the html5mode in Angular did not work for me in iOS safari and other browser versions when loading a subpage.
    $locationProvider.html5Mode(true);

 

Calculating selling price from the cost price

Recently in my price matching system I had to calculate the selling price of a product in a way that also calculates a transaction fee percentage on the final selling price without knowing the selling price, and without knowing what the transaction fee is until you’ve calculated the total price. Had fun chasing your tail yet?

You can do this in Excel with circular references but you will get circular reference warnings and the only way is to allow these warnings and an iteration limit of 100.

Stepping aside from the magic of excel I was able to work out the exact formula for this and below is a calculation for anyone else struggling to work out how to do this.

$cp = 9.56; // cost price
$d = 2.50; // delivery fee
$m = 0.15; // margin 15%
$tf = 0.019; // transaction fee

$sellingPrice = (($cp+$d)*(1+($m)))/(1-((1/6)+$tf)*(1+($m)));

$costPrice = $x / (1+(.15));

echo $sellingPrice."\n";
echo $costPrice;

The end for website designers and developers?

The end for web design, not quite

ai

Update: Again I was notified by a friend “have you checked this out” a new product PageCloud read more at the end of this post

Recently a friend notified me to thegrid.io’s new AI product “a website that designs itself”, in a bid to alert me I might one day be out of a job, instead of template’s there are filters and they claim it can automatically work out the content and how best to display it no matter what you throw at it. More interesting to me was the ecommerce offering although not yet available till late 2015 claiming to “just work” you won’t need to know or do anything in relation to hosting, SSL certificates etc.. past this there aren’t any details on this just yet.

Now I have to admit I haven’t used their product or tested them other than the markup produced for any of this article as there’s no free trial. But I did look at the source code for thegrid.io’s website, the website itself claims to be built by this and anyone could in theory have the same layout filters.

Testing

I put it through Google’s Pagespeed tool to analyse some of the markup produced that’s mostly a pass on this, from the user experience POV and it would be a bit picky to complain about some of the speed optimisations as almost any site I’ve put in here Google claims can be optimised further.

Schema
what about Schema?, on this front the site doesn’t deliver as there was no Schema data where there could have been, precision coding from a computer? clearly not.

Images
All the images seem to be background images, I couldn’t find one ALT tag that’s a few points off your SEO rank and some keywords lost.

General markup review
I counted 23 H1 tags that can’t be a good thing, isn’t the AI smart enough to know there shouldn’t be so many? Matt Cutts says if your page is full of H1’s  it’s not a great idea it’s fine if your using this in sections but many are so close together I can’t see this as a positive ranking factor other elements are like this too.

Most of the page is chock full of inline CSS and JS, ok this is perfectly valid but I can’t help thinking this could have been organised a bit better and is one of the things flagged on the Google Pagespeed test

“Compacting HTML code, including any inline JavaScript and CSS contained in it, can save many bytes of data and speed up download and parse times.”

This is just the tip of the iceberg an in-depth review might reveal more problems.

Replacing creativity

Next is the question of wether you can really replace creativity with computers? Time and time again i’ve tried it myself a client chooses a template they like and try to punch and squash it into their brand and it rarely ever works, by the time you’ve spent the countless hours amending it, you may as well have designed it from scratch. At the same time providing a much richer brand experience.

I get the feeling this is how the AI would work, it can work out what a YouTube link is or someone’s face but can it decide properly on how to use it and where to place it so your really back to changing your brand and content to fit the template.

How many layout filters are available? There has to be a limit, your site is going to look exactly like someone else’s. One of the great things about web design is the freedom to create a unique feel and look for your brand not some generic repeated computer generated layouts. At least with a template you can make it your own.

I believe that websites are not getting any simpler to make.

people are now starting to realise you can’t spend $8 a month and expect your website to work for  you, investing much more in your online business is the way forward.

It’s actually getting harder to get the balance right between functional design, content strategy, creative and code structure and for that you need experienced professionals.

In the end I think this product is aimed at amateurs and business people who really don’t understand the online space, thus giving them a quick solution.

In comes PageCloud

Yep it’s the end again, since my post thegrid.io has failed to launch and a new rival has appeared with a debut video at TechCrunch’s Disruptors seminar with a tagline “the web is about to change forever”.

Now as a developer it’s hard not to scoff at the words some of these companies use, from the video which is all there is at the moment PageCloud does look a bit different in it’s approach but these tools already exist. I can already copy and paste from photoshop into gmail for example so calling the copy/paste feature a world first seems a bit over the top.

That said it looks like a great product but in terms of changing the web industry for professionals that simply isn’t going to happen anytime soon.

Magento image not loading when using cron, only getting placeholder

I have a module which sends out an email via Mailchimp with a scheduled task for Magento’s internal cron and in doing so looks up the product image.

Mage::helper('catalog/image')->init($product, 'small_image')->resize(150));

The problem being only the placeholder was being returned when the cron job was executed. To confuse matters when I ran the script in testing from the browser it would return the correct image.

This is a nasty problem at first I thought this might be the answer Sangay details there that if your config does not specify a M,GB etc that it will return the wrong calculation, but then why the different results depending on how I ran the script?

To get to the bottom of this I ran what is being run in Mage_Catalog_Helper_Image

$model = Mage::getModel('catalog/product_image');
$model->setBaseFile($this->product->getData('small_image'))->resize(600,600);
$url = $model->saveFile()->getUrl();

PHP Fatal error:  Uncaught exception 'Varien_Exception' with message 'Memory limit has been reached.' in /lib/Varien/Image/Adapter/Gd2.php:58

Returning this shows the actual exception I did not get any Exception in the Mage exception log, and not in the host’s error log. On my part a server configuration oversight as the CLI php.ini did not have the error log set up. In any case that’s the error.

Because the value returned from _convertToByte function in Mage_Catalog_Helper_Image is -1 as the CLI php.ini sets the memory_limit to -1 (unlimited).

This could be an oversight by Magento or a design feature not to run this task on unlimited memory, personally I think it’s a bug. I modified the function to the following to set a 2G limit in this case.

   if (stripos($memoryValue, 'M') !== false) {
            return (int)$memoryValue * 1024 * 1024;
        }
        elseif (stripos($memoryValue, 'KB') !== false) {
            return (int)$memoryValue * 1024;
        }
        elseif ($memoryValue == "-1") {
            return '2147483648'; //2G
        }

Clearing expired magento shopping/sales rules programatically

Here’s a nice cleanup script I use to clear out expired shopping cart rules and catalog price rules and apply those changes. It’s one of those annoying things that you would think there would be a button for.

I’ve set the expiry check to the previous day and date comparison using strtotime you might want to adjust that, and use php’s dateTime library for a more thorough comparison as this relies on your server’s timezone configuration matching magento’s and being set up correctly.

If your wondering what setState does that’s to remove the message in magento admin about un-applied rules.

require '../app/Mage.php';

umask(0);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);


$model = Mage::getModel('catalogrule/rule')
    ->getCollection();


foreach($model as $rule) {
    $today = strtotime('Yesterday');

    if(strtotime($rule->getData('to_date')) < $today) {
      $rule->delete();
    }

}

$model = Mage::getModel('salesrule/rule')
    ->getCollection();


foreach($model as $rule) {
    $today = strtotime('Yesterday');

    if(strtotime($rule->getData('to_date')) < $today) {
       $rule->delete();
    }

}

try {
    Mage::getModel('catalogrule/rule')->applyAll();
    Mage::getModel('catalogrule/flag')->loadSelf()
        ->setState(0)
        ->save();
    Mage::app()->removeCache('catalog_rules_dirty');
    echo Mage::helper('catalogrule')->__('The rules have been applied.');
} catch (Exception $e) {
    echo Mage::helper('catalogrule')->__('Unable to apply rules.');
    print_r($e);
}