Script to reset all customer passwords in Magento

The following script was created to reset all customer passwords in a Magento store. It creates the new password from the first 3 characters of the customer’s current e-mail address, and a random 3 digit number. The total password length is 6 characters, but it can easily be modified. It also stores all the passwords to a tab-delimited file, this way you can refer to it later. All of this is just subjective, so you will want to tailor it to suit your exact needs.

For obvious security reasons, you will want to remove this script after you use it, or at the very least put it in a protected directory of some kind.

<?php
/************************
 *    / '_ __/_   _/_
 * ()()/(-( /( ()(/(-
 *   _/              
 *       since 2007
 *
 * Created by Foundco
 * All rights reserved unless otherwise specified under contract.
 * http://www.foundco.com/
 * @author Christopher Hogan <mailing address removed>
 * @copyright 2012 and beyond.
 ******************************/



error_reporting(E_ALL | E_STRICT);
$mageFilename = 'app/Mage.php';
if (!file_exists($mageFilename)) {
    echo $mageFilename." was not found";
    exit;
}
require_once $mageFilename;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app();

$passwordLength = 10;

/****
  If you are just resetting one customer by customer_id:
****/


//$customer_id = 10;
//$customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter('entity_id', array('eq' => $customer_id));

/****
  If you are resetting all customers:
****/


$customer_id = 10;
$customers = Mage::getModel('customer/customer')->getCollection();

/****
  Now loop through the customers and create the passwords
****/


foreach ($customers as $customer){
    // $customer->generatePassword($passwordLength)
    // $customer->sendNewAccountEmail();
        $password = strtoupper(substr( $customer->getEmail(), 0, 3)).rand(111,999);
        $customer->setPassword($password)->save();
        $line_data = $customer->getEmail(). "\t". $customer->getPassword();
        $line[] = $line_data;
        echo $line_data."\n";
}
$content = implode("\n", $line);

// store all the passwords to a file:
file_put_contents('./accounts.csv', $content);
echo "COMPLETE!";
?>

Create a PHP5 URL Shortener

I had a need to create a very basic URL shortening system. Below is the PHP5 code which generates a new string and checks it in the database using Doctrine 1.2. If it exists it will try again, if not it stores it in the database and returns it for use on a page. This could be very handy for sites which need to pass a lot of information back and forth easily, or re-use it on social networks.

function genRandomString() {
$length = 5;
$characters = ’0123456789abcdefghijklmnopqrstuvwxyz’;
$string =;
 
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters))];
}
 
return $string;
}
function generate($url) {
$string = genRandomString();
$record = Doctrine_Core::getTable($this->model)->findOneByName($string);
if ($record instanceOf Doctrine_Record) {
$new = Database_Model_Url();
$new->code = $string;
$new->url = $url;
$new->save();
return $string;
} else generate();
}
 
$string = generate($url);

Amazon Price Scraping

Amazon Feeds from Magento (among other sites)

Running a software company means that you have to be dynamic, creative, and most of all innovative. I strive every day to create unique and interesting new ways to do business online. Many of my clients sell their products on Amazon, Google Merchant Central, Shopping.com, Pricegrabber, NextTag, and other shopping sites.

Amazon is by far the most powerful, and so I focus much of my efforts on creating software specifically for their portal. I’ve created very lightweight programs that move data from CSV, XML, and other formats to Amazon AWS using the Amazon Inventory API. I’ve also created programs that push data from Magento directly to Amazon, and do this automatically, updating every few hours like clockwork. Some of my customers sell hundreds of thousands of products on Amazon due to this technology.

Doctrine ORM and Magento

I’m a strong believer in the power of Doctrine ORM in combination with Zend Framework, and I was an early adopter of this technology in production environments. More recently, I’ve been using Doctrine to generate models for Magento and then using these models in the development of advanced information scraping systems for price matching my client’s products against Amazon’s merchants. I prefer to use Doctrine because the documentation is awesome, the object model makes sense, and it is far easier to utilize outside of the Magento core.

What is price matching?
Price matching is when you take product data from your database and change it to just slightly below the lowest pricing available on Amazon, depending upon certain rules. The challenge here is that most products from distributors don’t have an ASIN (Amazon product id) number to check against. Here are the operations of my script to collect data about Amazon products:

  • Loops through all SKUs in catalog_product_entity
  • For each SKU, gets a name, asin, group, new/used price, url, manufacturer from Amazon
  • If name, manufacturer, and asin exist it stores the entry in an array
  • It loops through all the entries for each sku and it checks for _any_ of the following:
    • Does full product name match?
    • Does manufacture name match?
    • Does the product group match?
    • (break the product name into words) Do any words match?
    • If any of the following are true, it will add the entry to the database
  • If successful, it enters the data into attributes inside Magento:
    • scrape_amazon_name
    • scrape_amazon_asin
    • scrape_amazon_group
    • scrape_amazon_new_price
    • scrape_amazon_used_price
    • scrape_amazon_manufacturer
  • If the data already exists, or partial data exists it updates the data
  • If the data is null or corrupt, it ignores it

Data Harvesting
As you can see from the above instructions, my system first imports all the data that’s possible. This process is called harvesting. After all the data is harvested, I utilize a feed exporter to create a CSV file specifically in the Amazon format and push it via Amazon AWS encrypted upload.

Feed Export (Price Matching to Amazon’s Lowest Possible Price)
The feed generator then adjusts the pricing according to certain rules:

  • Product price is calculated against a “lowest market” percentage. This calculates the absolute lowest price the client is willing to offer
  • “Amazon Lowest Price” is then checked against “Absolute Lowest Sale Price” (A.L.S.P.)
  • If the “Amazon Lowest Price” is higher than the A.L.S.P, then it calculates 1 dollar lower than A.L.P. and stores that as the price in the feed for use in Amazon.
  • The system updates the price in the our database and freezes the product from future imports, then it archives the original import price for reference.
  • If an ASIN number exists it pushes the data to amazon using that, if not it uses MPN/ SKU or UPC

Conclusion
This type of system is wonderful because it accurately stores Amazon product data for later use, this way we can see trends in price changes. It insures that my client will always be the absolute lowest price for hundreds of thousands of products on Amazon (or Google/ Shopping.com/ PriceGrabber/ NextTag/ Bing). Whenever the system needs to update, it takes around 10 hours to harvest 100,000 products. It takes 5 minutes to export the entire data set to amazon using my feed software. This makes updating very easy and it can be accomplished in one evening. This is something that we can progressively enhance to protect against competitors throughout the market cycles, and it’s a system that is easy to upgrade in the event Magento changes it’s data model.

Upgrades
Since we utilize Doctrine, it’s all outside of Magento. So we can go ahead and upgrade Magento to a newer version any time we want. Then we just re-generate the database models and our system becomes compliant with any changes Magento made automatically. I’ll probably come back and do another article on just this topic, as it’s one I’m very interested in writing about.

Contact
For more information on any of the products or services Foundco can provide your business, submit a request for information here.

Installing & Bootstrapping Doctrine 1.2 in Zend Framework 1.11

Installing Doctrine 1.2 and Zend Framework 1.11 on Cent OS™

Note: You must have root access to perform these operations. If you don’t want to spend big bucks on a server, you can get a VPS account at a site like linode.com.

The first part is easy, you just download both of the packages to the server into your PHP include path directory. The best way to find out your include path is to do this:

php -i | grep "include_path"

Once you know your include path, change directories into it, and download the packages.

cd /usr/lib/php
wget http://framework.zend.com/releases/ZendFramework-1.11.11/ZendFramework-1.11.11.tar.gz
wget http://www.doctrine-project.org/downloads/Doctrine-1.2.4.tgz
ln -s ZendFramework-1.11.11/library/Zend/ Zend
ln -s Doctrine-1.2.4 Doctrine

As you can see I also symbolically linked the “Zend” and “Doctrine” as the include paths to their proper sub-directories.

Next you’ll want to edit the Bootstrap.php file in your Zend Framework installation (application directory).

  protected function _initLibraries () {
        $autoloader = Zend_Loader_Autoloader::getInstance();
          // Doctrine 1.2
          $autoloader->registerNamespace('Doctrine_');
        }


    protected function _initDoctrine() {

        set_include_path('/usr/lib/php/Doctrine'
        . ':' . get_include_path());

    spl_autoload_register(array('Doctrine_Core', 'autoload'));
    $config = Zend_Registry::get("config");
    if ($config->database->dsn) {
      Doctrine_Manager::connection($config->database->dsn);
      $manager = Doctrine_Manager::getInstance();
      $manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_PEAR);
      $manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);
      $manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
      return $manager;
    }
    }

Once the bootstrap is complete you’ll have a fully functioning doctrine within your Zend Framework installation. Then you’ll have to start setting up models. The easiest way to do that is to setup another namespace specifically for your database models. I like to keep them separate, because then they’re all in one place.

      // Database library  (inside directory /library/Database)
      $autoloader->registerNamespace('Database_');

I’m not going to go into too much detail about the Models, because the Doctine website does a great job of explaining those. But I’ll show you one example of a simple model with one foreign key:

<?php
/************************
 *    / '_ __/_   _/_
 * ()()/(-( /( ()(/(-
 *   _/              
 *       since 2007
 *
 * Created by Foundco
 * All rights reserved unless otherwise specified under contract.
 * http://www.foundco.com/
 * @author Christopher Hogan <mailing address removed>
 * @copyright 2011 and beyond.
 ******************************/


class Database_Model_Image extends Doctrine_Record {
  public function setTableDefinition() {
    $this->setTableName('images');
    $this->hasColumn('title','string', null, array('unique'=>false, 'notblank'=>false,'nospace'=>false,'minlength'=>0));
    $this->hasColumn('is_active','integer', null, array("default"=>0));
  }

  public function setUp() {
    $this->hasMany("Database_Model_Image_Text", array("local"=>"id","foreign"=>"image_id"));
  }
}

Zend Request Objects for Super Globals

Did you know that you can use the Zend::Request Object to pull super global information the same way you would with parameters in the _GET and _POST spaces?

For instance, in any controller just do:

$this->request->getServer('HTTP_HOST');

This will get you the HTTP_HOST instead of using the $_SERVER['HTP_HOST'] space through PHP.

Your can get parameters the same way. For instance, any get or post parameter, you can detect if it’s there like this:

if ($this->_request->has("foobar")) { dostuff(); }

To get the parameter data you just do this:

$this->data =  $this->_request->getParam("foobar");

And you can even do this for an array. This way when you create your form objects, you don’t have to get separate parameters for every single form element. You just get the one data array, and then filter it through Zend::Filter and Zend::Validator.

More on this later.

Jquery Multiple File Upload using Zend Framework

I’ve recently had to implement a system that uploads multiple images or files through a single interface and stores them into Zend Framework using Doctrine.   The best way to go about doing this is to work directly with a module inside Zend Framework.

In order to do this I had to engineer a upload handler that will act as the AJAX receiver for XHR requests sent using JSON.

You can find the tutorial on GitHub:

https://github.com/blueimp/jQuery-File-Upload/wiki/Zend-framework