Magento Inventory Updater

This script is designed to run via the command line instead of through the browser. It moves at about the same speed as Magento’s standard import, since its just calling the same underlying commands (even though we’re updating 1 field instead of 100 its more or less the same speed).

This script cannot “time out” though so the advantage I guess would be no need for batches? Or since its command line, you could write a script to bring in pricing data from other systems, etc..

Support is available for $75/hr josh.ribakoff@gmail.com
This script was coded against Magento ver. 1.4.1.1
Download

1) Unzip to app/code/local
2) Open InventoryUpdater/config.php and set your database details
3) Open a command line in app/code/local/InventoryUpdater
4) Open sampledata.csv and edit in your QTY
5) Execute like this: php inventoryupdater.php
6) Sit back and wait, it will be a while (Magento’s API moves at about 2 seconds per product)

Support is available for $75/hr josh.ribakoff@gmail.com
This script was coded against Magento ver. 1.4.1.1
Download

Posted in Uncategorized | Leave a comment

Magento price updater script

This script is designed to run via the command line instead of through the browser. It moves at about the same speed as Magento’s standard import, since its just calling the same underlying commands (even though we’re updating 1 field instead of 100 its more or less the same speed).

This script cannot “time out” though so the advantage I guess would be no need for batches? Or since its command line, you could write a script to bring in price data from other systems, etc..

Support is available for $75/hr josh.ribakoff@gmail.com
This script was coded against Magento ver. 1.4.1.1
Download

1) Unzip to app/code/local
2) Open PriceUpdater/config.php and set your database details
3) Open a command line in app/code/local/PriceUpdater
4) Open sampledata.csv and edit in your price data
5) Execute like this: php priceupdater.php
6) Sit back and wait, it will be a while (Magento’s API moves at about 2 seconds per product)

Download
This script was coded against Magento ver. 1.4.1.1
Support is available for $75/hr josh.ribakoff@gmail.com

Posted in Uncategorized | Leave a comment

Microsoft finally comes to their senses. Sort of.

Nearly one year ago I blogged about Microsoft’s “restricted mode”. I was calling their tech support every few weeks and getting into heated arguments. I would calmly describe my XP disk was scratched and that is preventing me from using the $300 Vista product which should not rely on my 10yr old XP disk. The guy would just respond “well you shouldn’t have scratched it then”. To which I responded “wtf” (and then he started cussing me out).

Eventually after months and months of M$ screwing me over, one irate customer support tech transferred me to the wrong department, explaining “oh you want the parts department” – to which I asked “are they going to fix my issue”, to which he responded “yes for $x they will send you a replacement disk”. I didn’t want to hear it though. How could they sit there and ask me to spend another cent when I feel ripped off. I asked him that. He did not respond, just transferred me to the parts department.

Guy In parts Department: “Hello?”
Me: “Yes, my XP disk was scratched and now I can’t use my vista upgrade disk”.
Guy: “Ok no problem lets use a credit card to take care of the $30 fee….”
Me: “No, you don’t understand. I want you guys to send me a working copy of vista that I paid for”
Guy: “Ok that will be a $100 replacement fee…”
Me: “God damnt what do I have to do to get some service around here?”
Guy: “I dont understand sir, I just order new parts”
Me: “Ok listen to what I am saying. I feel ripped off by your employer. Whos neck do I need to strangle”
Guy: “Oh ok call the corporate office at this #”

So I email the corporate office and within a few days they promise to send me free copies of WIndows 7 Ultimate (one better than vista). The next morning fedex arrives and what is at my door step? A 32 bit copy of Vista. I had a voicemail where they promised me windows 7. Plus 32 bit is like an insult when I purchased 64bit vista originally. Why was it so hard for a company worth Billions of dollars to ship out a simple disk? 2 more months passed and none of my emails were answered. One day they decided to answer and they finally sent me my windows 7.

So what does it take to be able to use the software you buy from Microsoft? Apparently a year of your life wasted, 100s of phone minutes burnt up yelling at retarded Indian support agents, getting cussed out by the tech support agents and having them refuse to transfer you to their supervisor, or simply “change their voice” and try to pretend to impersonate the “supervisor”; and finally 2 months of spamming corporate asking them to abide by their promises. And if you don’t have the motivation to go thru all that? Well I guess you can just go suck on a lemon according to MS. Not to mention all the time it cost me re-installing my OS 20+ times during the last year for no reason whatsoever.

Posted in Uncategorized | Leave a comment

Magento Censorship Unacceptable.

First of all I love Magento as a software product. I just don’t like some aspects about the Magento company. This isn’t easy for me to do either since I rely on Magento to make a living and trashing them is in my financial worst interest. I think its great to use Magento, just wouldn’t recommend becoming an “Enterprise” customer with them. Here is why.

Magento has chosen to censor one of its developers (me). I had an important forum post message shedding light on the company. They have resulted in barbarian tactics in futile attempts to suppress my important message. They would tell me they’re going to handle my issue and then delete my post. A second time, they told me they were going to handle my issue and it would take some time, and then they deleted my post. Additionally, they banned me in a “sneaky” way. They didn’t want to deal with me. I was a rat that was squealing and they wanted to censor me.


They don’t want me on their forums anymore, :-(

I will not be silenced. Here is my message. Please post this up on their forums with distracting titles. Send the message that the more they silence us the louder we will cry.

So my question to Magento is; how can you ethically sell someone a software for $10,000, with “1,700 quality extensions” as your sales pitch. And then turn around in the developer’s face and say “you cannot see the code though”.

So in other words Varien is letting these people pay the $10k, and doesn’t care that I’m sending refunds left & right, and that they have upset customers who cannot use modules, left and right. I await Variens response. Maybe they will censor me like they’ve done in the past?

Read my full message along with proof of their censorship.

Posted in Uncategorized | 6 Comments

Isolating/Testing Legacy Javascript Code (w/ jquery’s bind & trigger)

So I started writing some javascript code. Didn’t test it (tsk tsk). Then I started writing tests.

Then a user reported a bug in an untested part. Since I am writing tests now I resist the urge to fix it quickly, and take the time to understand the problem.

Here is how our little regression happened. First I had this little function that ran when the user clicked the submit button. It did some “stuff” and then submitted the form.

submitVafForm = function()
{
    if( jQuery('#categorySelect').val() != '?' )
    {
        jQuery('#vafForm').attr( 'action', jQuery('#categorySelect').val() );
    }
    document.vafForm.submit();
}

Basically this element “categorySelect” contained the URL that the form should post to. But then some users were saying it did not work (when the form got submitted the “meta data” I was storing in that select box was messing up the GET parameters. No problem I though, I’ll just add one last line of jquery to clear out the value after I’m done reading it:

jQuery('#categorySelect').html('


');

Boom. Job done. Right? I pushed the code.

But then I forgot about the fact that some users do not use this category chooser. In that case a hidden element was placed on the page so there would be a “NULL” value. However in Internet Explorer only, trying to call .html() on a hidden element threw a javascript error and crashed my application.

Hmmm great. That’s what I get for not writing a test for that. So once I am to this point how to dig myself out of the hole I have dug myself in?

Jquery’s bind & trigger. You see I can easily write a unit test that replicates the issue, all I’d have to do is click that button, I don’t even need an assertion:

$("#vafSubmit").trigger("click");

Done. Function gets called. Only problem… the test page actually gets redirected because the form submit is actually happening.

This is where javascript really really shines. How do we isolate that single .submit() line from the rest of the code? I want to test that part, without that last line running. Well I could use lambda, but I choose a more natural approach. Jquery’s bind & trigger functions.

You see we can just extract the bit we don’t want running during test into an event handler:

submitVafForm = function()
    {
        if( jQuery('#categorySelect').val() != '?' )
        {
            jQuery('#vafForm').attr( 'action', jQuery('#categorySelect').val() );
        }
        var chooser = jQuery('#categorySelect');
        if( !chooser.is('input') ) {
            chooser.html('


');
        }
        jQuery().trigger("vafSubmit");
        return false;
    }

    jQuery().bind("vafSubmit", function() {
        document.vafForm.submit();
    })

So now instead of submitting the form we fire an event. By default that event is bound to the anonymous function that submits the form. During test we can unbind this event so that code does not fire.

jQuery().unbind("vafSubmit");

And there you have it. In an OOP language with inheritence we would simply create the concept of a “test specific sub class”. In jquery we have events which are a better solution in my opinion because it results in a cleaner separation of test code from production code.

Posted in Uncategorized | Leave a comment

New Guerilla Marketing Campaign by Hollywood, “The Union” “Artiforg”

There is a new guerilla marketing campaign running on the digg homepage. Upon clicking it it takes you to this humorous site claiming to sell you prosthetic organs for half a million bucks. After a while I was starting to get frustrated as to who is behind it. This was probably their marketing tactic. Heh.

After digging for a little while, I tried to use their contact form to contact them. I got an error from their site. But I was also able to see it was making calls to a 3rd party domain (The Visionare Group). Looking at their portfolio they seem to have an impressive history being contracted by Hollywood.

On their fake little site if you click “Financing terms and conditions” it takes you to this link: http://www.repomenarecoming.com/

I thought this part was particularly funny:

“Repo Man:

Occassionally, customers enrolled in our financing plans default on their payments. That’s when we call on our team of Repo Men-our very own version of the Navy Seals”

Their hoax of a job description continues, with job details:

-interface with debtors; communicate options for artiforg(sig) removal

- recover merchandise from the field in a timely manner

- adept in handling both tasers and scalpels

- proficiency in one or more of the folliwng: karate, kung fu, etc..

According to IMDB it is Up 25% in popularity this week. I guess this types of campaigns work. All I know is when the Movie “2012″ was running ads on TV saying the world was going to end, that’s not cool. These types of marketing campaigns are funny, but where do you draw the line? Do you think as we enter a new digital age that new laws will need to be made against causing panic? Similar to yelling “fire” in a movie theater?

I guess I blew your “cover”, Visionaire Group! Maybe next time use a throw away domain to host your Guerrilla client’s contact forms! The premise behind the movie is neat though, not sure if I’m too fond of the marketing. Kind of annoying.

Posted in Uncategorized | 1 Comment

Javascript Unit Testing, Test Pages (test classes).

I have known about javascript testing for a while, about a year. I mostly wrote it off as something “too advanced” for me. I looked at it as overkill, and in the past just have not had the time to take it seriously, despite TDD changing the way I do things server side.

Well I finally took the plunge. At first I took a look at qUnit. Right away I liked/hated some things about qunit. Most of all I hated that everyone seemed to be using multiple assertions per test function. And not the honest usage of a “guard” assertion here or there. They were blatantly testing distinct features from within the same method.

Not to gripe about their choice of style, but for me I had an extra requirement. Back when I thought js testing was not needed I coupled lots of PHP code with my javascript file. Depending on settings in PHP different js sections get created, and I want to test that. To do this I need each group of tests to live in it’s own page. I needed each page to run one after the other so each page can change some state on server side. I need them to run one after the other, synchronously so that the tests do not interact via the “global” state that is changing on the server.

After reading through both the source code of qunit and jsunit, here is what I found

jsunit supports test pages
jsunit does NOT support asynchronous tests.
qunit supports asynchronous tests
qunit does NOT support test pages.

After finding the relevant parts of both test frameworks, I decided it would be easier to hack in test page support for qunit, rather then to try to add asynch support for jsunit.

First all of my files live *outside* of the web root since I am testing a plugin for Magento. So first I created a file that can include them, which is how jsunit works, each test page has a URL. Then I wrote up this quick code. You can see there is an array of file names. runSuite() runs the “currentPage”. it loads the page by loading the test page into an iframe. When it is complete it uses qunit hooks to alert the “runner”.

Simply open your qunit pages and place this callback:

QUnit.done = function (failures, total) {
top.testPageComplete( ‘<?=basename(__FILE__)?>’, failures, total );
};

This simply tells my runner (below) when the page is done. It says which page, and how many tests/failures happened.

Then create the runner and load it in your browser:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
“http://www.w3.org/TR/html4/loose.dtd”>
<html>
<head>
<style type=”text/css”>
a{
display: block;
}
</style>
<script src=”http://localhost.vehiclefits.com/skin/adminhtml/default/default/jquery-1.3.2.min.js”> </script>
<script type=”text/javascript”>
var testPages = new Array( ‘ajaxTestJsMMY.php’, ‘ajaxTestJsMMTC.php’, ‘ajaxTestJsMMYdisabled.php’ );

var currentPage = 0;

var iframeForLink = function( link ) {
return $(link).next(‘iframe’);
}

var toggleIframe = function( link ) {
iframeForLink( link ).toggle();
}

var bindToggles = function() {
$(‘.pageFrameToggle’).unbind(‘click’);
$(‘.pageFrameToggle’).click( function() {
toggleIframe(this);
});
}

var loadPage = function(page) {
var pageName = testPages[page];
$(‘#testPageContainer’).append( ‘<a href=”#”>’ + pageName + ‘</a>’ );
bindToggles();
$(‘#testPageContainer’).append( ‘<iframe src=”/vafJsTest.php?file=’ + pageName + ‘” width=”500″ height=”500″></iframe>’ );
}

var areMorePages = function() {
return currentPage < testPages.length;
}

var runCurrentPage = function() {
loadPage( currentPage );
currentPage++;
}

var getPageIndex = function( pageName ) {
var i = 0;
while( i < testPages.length ) {
if( pageName == testPages[i] ) {
return i;
}
i++;
}
return false;
}

var testPageComplete = function( testPage, failures, total ) {
var result = failures + ‘ failures, ‘ + total + ‘ total<br />’;
//$(‘#testPageResults’).append( testPage + ‘ ‘ + result );
var selector = ‘.page’ + getPageIndex( testPage );
$(selector).append( ‘ | ‘ + result ).click();
if( areMorePages() ) {
runCurrentPage();
}
}

var runSuite = function() {
runCurrentPage();
}
$(document).ready( runSuite );

</script>
</head>
<body>
<div id=”testPageResults”></div>
<div id=”testPageContainer”></div>
</body>
</html>

So once it again it just loops thru the array of test Pages, and “includes” their url via the iframe. It does it serially so that no page begins before the previous completely finishes. And best of all it does it with the core qUnit stuff, without changing it… Qunit rocks for asynchronous testing.

Which is another topic. I’ll have to give a ping back to Anup Shah for teaching me that art.

Posted in Uncategorized | 1 Comment

Phing ** Work-Around

When you use this in a fileset tag in PHING:

<include name="Vaf/**" />

You would expect it to include Vaf/foo.php, but not Vaffoo/bar.php

This works on windows, but not on Linux? Reading the manual I see "In patterns, one asterisk (*) maps to a part of a file/directory name"… so I found a way to exploit that feature to overcome the bug. The work around I found is to use two include tags:

<include name="Vaf/*" />
<include name="Vaf/*/**" />

Gotta love software. Basically the double asterisk seems to cause the forward slash preceding it to be ignored by PHING, that is why this hack is needed to keep your build file portable.

Posted in Uncategorized | Leave a comment

PHP Pitfalls Part 2 – Code Blocks

In PHP blocks may stand on their own line. For this reason if you take the following code:


public function foo()
{
$array = array( 1, 2, 3 );
$copy = array();
for( ; $value = current( $array ); next( $array ) );
{
array_push( $copy, $value );
}
print_r( $copy );
}

And run it you will get an array like this:
Array( 0 => bool(false) )

Why is this? Take a look at the line with the for loop, see the semicolon at the end? PHP basically evaluates $value to equal false and then runs the array_push line only one time. Not that you would intentionally put a semicolon at the end of the loop but stuff happens.

Posted in PHP | Leave a comment

How the Data Mapper pattern enhances code refactoring

We all know code needs to be refactored. Duplication sometimes need to be factored out. Sometimes we think of a more clear name for a method or variable and wish to rename something. Sometimes we accidentally use names that are ambiguous together and need to rename something, etc…

Using the data mapper pattern it is much easier to “make and go” with your refactorings. I am talking about defect localization. In TDD we use small isolated unit tests to drive the creation of production code (test first development). A common property of a good test suite is generally considered to be defect localization. If you are adding a feature to one part of the system, and that breaks something in another part of the system, the tests should tell you what broke, and should tell you specifically. Instead of pointing you to the general component it should point you to exactly which method the defect is introduced. This way you can respond faster and remain “agile” (as much of a buzz word that is).

Here’s how the data mapper comes into play. We have this object called the Employer:


/** @param Employer_Size */
public function setSize( $size )
{
$this->size = $size;
}

/** @return Employer_Size */
public function getSize()
{
return $this->size;
}

I want to simply rename that method to EnrollmentSize, because in this context we are actually referring to the approximate number of enrolled students at an employer’s school.

The first step is to have tests that cover this method in all layers:


function testSize()
{
$size = new Employer_Size;
$this->employer->setSize( $size );
$this->assertSame( $size, $this->employer->getSize() );
}

Test the objects.


function testSize()
{
$this->assertSameModel( $this->expected->getEnrollmentSize(), $this->actual->getEnrollmentSize() );
}

Test the data mapper for the Employer & Employer_Size classes.

Once we have this part under test, we need not worry about the fact the column is named ‘size_id’ in the database when we go to rename things in the code. The data mapper’s unit test saves & reloads the object, and each test method verifies that each mapping did its saving & loading.

So the first thing I did was search my code base for occurrences of “getSize”. There are a few but they are all luckily the ones I am intending to rename. So I go ahead and do a find & replace in my code, for both getSize and setSize. They have been renamed to getEnrollmentSize and setEnrollmentSize

I run my tests. I get failures, which I expected. The tests are telling me that the Employer_Mapper cannot find that old method Employer->getSize. That is what we expected, but if for some reason we thought we were done the tests let us know we still have work left to do.

In the data mapper I make a small change. I simply pass an option telling it that we have renamed the method and to use the new method name instead.

Before:

->addSingle( 'enrollment_size', 'Employer_Size' );

After:

->addSingle( 'enrollment_size', 'Employer_Size', array( 'property' => 'EnrollmentSize' ) );

Then I run the tests again. We passed (for the Mappers tests). We still have a failure in the EmployerTest. It tells me that this other method ->hasSize() was referencing the old ->getSize() method. We better update that reference to ->getSize(). We should also rename ->hasSize() to ->hasEnrollmentSize() to keep our code consistent with itself.

Before:

/** @return bool */
public function hasSize()
{
if( $this->getSize() instanceof Shuffler_Null )
{
return false;
}
return true;
}

After:

/** @return bool */
public function hasEnrollmentSize()
{
if( $this->getEnrollmentSize() instanceof Shuffler_Null )
{
return false;
}
return true;
}

I also rename its usages in my tests.

We still have not renamed the size_id in the employer table. We still have not renamed the Employer_Size class to Employer_EnrollmentSize. In TDD we work in these small, isolated steps. Because I run my tests before and after renaming the method, I prove to myself that the method can be renamed.

I run all my tests. They all pass. So now we can confidently tell our users that we *safely* made a refactoring. Our tests prove that if we push this update it will not cause any problems for our users.

I know I am not breaking any of the other many classes that use that method. That is how bugs are introduced. If we had just gone thru and started renaming everything, later on you will have a “bunch of places that needs to be updated”.

The way TDD differs from traditional development is that you do not let the code become “out of date with itself” for more than about 5 minutes maximum.

We could save renaming the database column until the next “major update”. That would in fact be a wise project management strategy. Batching your database updates allows your users to make wise decisions like scheduling the updates for non-peak hours, but in the mean time you can make minor tweaks to the code like renaming stuff.

Or depending on your project you could go ahead and rename the size_id column now. The only import thing is that we were able to make a small isolated change, and run the tests before & after. Then we can safely commit our code without breaking anything.

In programming, if you just go thru and make these types of changes, even if you are only making small changes to the code “for a few minutes”, it is funny how you can easily end up with hours of work going around to “update all the places it was used”. TDD is like risk management. If you force yourself to work in smaller change sets, the worst tragedy that could happen is reverting 5 minutes of work and taking a break.

Without the tests you could easily be trying to debug that code for hours to see which parts of your changes were related to the ‘bug’. If you work in small isolated change sets, reverting 5 minutes of code is no big deal. If you went around and made a bunch of changes without running your tests, you might be inclined to put in so much work that you become emotionally attached to the new code, and will spend hours debugging it since you are reluctant to revert it.

So the moral of this post is work in small change sets, and don’t be afraid to revert that sucker.

Posted in PHP, Testing, Uncategorized | Leave a comment