Tag Archives: php

Using widgets outside of the CMS in Magento

Magento ships with widget functionality that lets you build out data models and then reuse them on product and CMS pages. If you want to use these in a custom template however, you are out of luck.  This can be done by extending the Widget Collection class.

Create the following directory structure: app/code/local/Mage/Widget/Model/Myswql4/Widget/Instance

Copy app/code/core/Mage/Widget/Model/Myswql4/Widget/Instance/Collection.php into your new directory

The Mage_Widget_Model_Mysql4_Widget_Instance_Collection comes with a store filter but thats about it.  To be more usefull we are going to add a type filter, a title filter, and a sorter.

class Mage_Widget_Model_Mysql4_Widget_Instance_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
{
    /**
     * Constructor
     */
    protected function _construct()
    {
        parent::_construct();
        $this->_init('widget/widget_instance');
    }

    /**
     * Filter by store ids
     *
     * @param array|integer $storeIds
     * @param boolean $withDefaultStore if TRUE also filter by store id '0'
     * @return Mage_Widget_Model_Mysql4_Widget_Instance_Collection
     */
    public function addStoreFilter($storeIds = array(), $withDefaultStore = true)
    {
        if (!is_array($storeIds)) {
            $storeIds = array($storeIds);
        }
        if ($withDefaultStore && !in_array(0, $storeIds)) {
            array_unshift($storeIds, 0);
        }
        $select = $this->getSelect();
        foreach ($storeIds as $storeId) {
            $select->orWhere('FIND_IN_SET(?, `store_ids`)', $storeId);
        }
        return $this;
    }

    public function addTypeFilter($type) {
        $this->getSelect()->where('type=?', $type);
        return $this;
    }

    public function addTitleFilter($type) {
        $this->getSelect()->where('title=?', $type);
        return $this;
    }

    public function addAttributeToSort($attribute, $dir='asc') {
        $this->getSelect()->order("{$attribute} {$dir}");
        return $this;
    }
}

Now we should be able to query any widgets from any template in our system:

< ?php
$wids = Mage::getModel('widget/widget_instance')
        ->getCollection()
        ->addTypeFilter('masswidget/list')
        ->addAttributeToSort('title', 'asc')
        ->load();

foreach ($wids as $wid):
        $params = $wid->getWidgetParameters();
        echo $params['custom_param'];
        echo $wid->gettitle();
endforeach;
?>

Displaying Custom Attributes on the Product Page in Magento

At some point you may not want to use the canned attributes.phtml groupings that magento provides, or you just want to cherry pick which attributes to show on your product listing page

template/catalog/product/view.phtml

$_product = $this->getProduct();

//For the attribute bike_specs_rear_shock

$_product->getResource()->getAttribute('bike_specs_rear_shock')->getStoreLabel(); //label
$_product->getbike_specs_rear_shock(); //value

SyntaxHighlighter Evolved

I’m currently in the process of migrating gpowerd.net over to this domain and onto wordpress. SyntaxHighlighter has been upgraded quite a bit since I last wrote about it.  I came across a great plugin to handle the code highlighting for me on wordpress.  I love the plugin, didn’t have to go into the wordpress template.

It doesn’t support the old pre syntax that I had been using previously but it was simple to add in.

Patch to add this to 2.3.8 is below, Thanks to Alex for the plugin

--- syntaxhighlighter.orrig.php 2010-06-03 20:08:24.000000000 -0500
+++ syntaxhighlighter.php       2010-06-18 12:27:35.000000000 -0500
@@ -101,12 +101,15 @@
                        'tabsize'        => 4,
                        'toolbar'        => 1,
                        'wraplines'      => 1,
+                       'legacy'         => 0,
                ) );

                // Create the settings array by merging the user's settings and the defaults
                $usersettings = (array) get_option('syntaxhighlighter_settings');
                $this->settings = wp_parse_args( $usersettings, $this->defaultsettings );

+               if ( 1 == $this->settings['legacy'] )
+                                       wp_register_script( 'syntaxhighlighter-brush-legacy',             plugins_url('syntaxhighlighter/syntaxhighlighter/scripts/shLegacy.js'),            array(),                         $this->agshver );

                // Register generic hooks
                add_filter( 'the_content',                array(&$this, 'parse_shortcodes'),                              7 );
@@ -175,6 +178,7 @@
                        'javascript'    => 'jscript',
                        //'latex'         => 'latex',
                        'tex'           => 'latex',
+                       'legacy'        => 'legacy',
                        'matlab'        => 'matlabkey',
                        'objc'          => 'objc',
                        'obj-c'         => 'objc',
@@ -583,6 +587,9 @@
                echo "  SyntaxHighlighter.config.strings.noBrush = '" . $this->js_escape_singlequotes( __( "Can't find brush for: ", 'syntaxhighlighter' ) ) . "';\n";
                echo "  SyntaxHighlighter.config.strings.brushNotHtmlScript = '" . $this->js_escape_singlequotes( __( "Brush wasn't configured for html-script option: ", 'syntaxhighlighter' ) ) . "';\n";

+               if ( 1 == $this->settings['legacy'] )
+                       echo "  dp.SyntaxHighlighter.HighlightAll('code');\n";
+
                if ( 1 != $this->settings['autolinks'] )
                        echo "  SyntaxHighlighter.defaults['auto-links'] = false;\n";

@@ -687,6 +694,7 @@
                        'tabsize'        => false,
                        'toolbar'        => false,
                        'wraplines'      => false,
+                       'legacy'         => false,
                ), $atts ) );

                // Check for language shortcode tag such as
code


@@ -771,6 +779,7 @@
'smarttabs' => 'smart-tabs',
'tabsize' => 'tab-size',
'wraplines' => 'wrap-lines',
+ 'legacy' => 'legacy',
);
// Allowed configuration parameters and their type
@@ -925,6 +934,7 @@



+

@@ -1062,6 +1072,7 @@
$settings['smarttabs'] = ( !empty($settings['smarttabs']) ) ? 1 : 0;
$settings['toolbar'] = ( !empty($settings['toolbar']) ) ? 1 : 0;
$settings['wraplines'] = ( !empty($settings['wraplines']) ) ? 1 : 0;
+ $settings['legacy'] = ( !empty($settings['legacy']) ) ? 1 : 0;
if ( 'true' != $settings['padlinenumbers'] && 'false' != $settings['padlinenumbers'] )
$settings['padlinenumbers'] = (int) $settings['padlinenumbers'];

WordPress Plugin: Displaying your Google Reader RSS subscriptions

I’ve been meaning to write this code for a while, and I really wanted to take a stab at writing a wordpress plugin so here it goes.

The following takes in Google user credentials, and allows the user to display what RSS feeds they subscribe to on their wordpress blog

Example: The RSS that I read

Update: This plugin is now hosted by wordpress. click here


/*
Plugin Name: Google Reader Subscription List
Version: 1
Author: Timothy Broder
Description: Lists a users subscribed Google Reader feeds
*/

/*  Copyright 2009  Timothy Broder (email : timothy.broder@gmail.com)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

if (!class_exists('GoogleReaderSubList')) {
 class GoogleReaderSubList {

  var $show_list       = 'show-google-reader-sub-list';  //the hook in a page
  var $login          = '';
  var $pass          = '';
  var $source         = 'wordpress-google-reader-sub-list-';  //the source the api sees when logging into Google
  var $service         = 'reader';
  var $login_url        = 'https://www.google.com/accounts/ServiceLoginAuth?service=mail'; //URL to login to google
  var $subscription_list_url  = 'http://www.google.com/reader/api/0/subscription/list'; //URL that holds a users subscriptions

  function GoogleReaderSubList() {
   $options    = $this->get_admin_options();
   $this->login  = $options['google_login'];
   $this->pass  = $options['google_pass'];

   $this->source = $this->source . $this->login;
  }

  function show_sub_list() {
   $stop = false;
   if ($this->login == '' || $this->login == null) {
    echo 'Google login not set';
    $stop = true;
   }
   if ($this->pass == '' || $this->pass == null) {
    echo 'Google password not set';
    $stop = true;
   }

   //check to see if the zend plugin has been installed and activated
   //http://wordpress.org/extend/plugins/zend-framework/
   if (!(defined('WP_ZEND_FRAMEWORK') && WP_ZEND_FRAMEWORK)) {
    echo 'The Zend Framework Plugin is not active.  Please install and activate it.';
    $stop = true;
   }
   if ($stop) {
    return;
   }

   $client = new Zend_Http_Client($this->login_url);

   //connect, authenticate, and handshake with Google
   $client->setCookieJar()
    ->setMethod(Zend_Http_Client::POST)
    ->setParameterPost(array(
     'continue'             => $this->subscription_list_url,
     'service'              => 'reader',
     'niu'                  => 1,
     'hl'                   => 'en',
     'Email'              => $this->login,
     'Passwd'               => $this->pass,
     'PersistentCookie'     => 'yes',
     'asts'                 => ''
    ));

   //$error_level = error_reporting();
   //error_reporting(1);
   $response = $client->request('POST');
   $client->setUri($this->subscription_list_url)->setMethod(Zend_Http_Client::GET);
   $response = $client->request()->getBody();

   if ($client->request()->getStatus() == 400) {
    ?>Unable to login with supplied Google login/password< ?
    return;
   }

   //error_reporting($error_level);

   //got the feed, parse it
   $feed = simplexml_load_string($response);

   $hashmap = array();

   //organize the feeds by tag
   foreach ($feed->list->object as $e) {
    $url = $e->string[0];
    $title = $e->string[1];
    $cat = $e->list->object->string[1];

    //make sure a feed is filed somewhere
    if ($cat == '') {
     $cat = 'unfiled';
    }
    $t = $hashmap["$cat"];

    //a category hasn't been used before
    if ($t == null) {
     $t = array($e);
     $hashmap["$cat"] = $t;
    }
    //category has been used before
    else {
     array_push($t, $e);
     $hashmap["$cat"] = $t;
    }
   }

   //sort the categories
   ksort($hashmap);

   //output
   ?>

Tags:
    < ?
    $endKey = end(array_keys($hashmap));
    foreach ($hashmap as $cat=>$t) {
     echo "$cat";
     if ($cat != $endKey) {
      echo ', ';
     }
    }
    ?>
   

< ?

   foreach ($hashmap as $cat=>$t) {
    echo "";
    echo "$cat";
    foreach ($t as $e) {
     list($feed, $url) = split('feed/', $e->string[0]);
     $title = $e->string[1];

     echo "$title";

    }
    echo '';
   }
  }

  function addContent($content) {
   // Only do this if this is a page and it has the appropriate custom field
   if (is_page()) {
    $cust_field_values = get_post_custom_values($this->show_list);
    if ($cust_field_values != NULL) {
     if (defined('WP_ZEND_FRAMEWORK') && WP_ZEND_FRAMEWORK) {
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');
     }
     $content = $this->show_sub_list();
    }
   }
   return $content;
  }

  function init() {
   $this->get_admin_options();
  }  

  function get_admin_options() {
   $admin_options = array('google_login' => '',
    'google_pass' => '',
    'use_accordion' => 'true');
   $options = get_option($this->adminOptionName);
   if (!empty($options)) {
    foreach ($options as $key => $option) {
     $admin_options[$key] = $option;
    }
   }
   update_option($this->admin_optionsName, $admin_options);
   return $admin_options;
  }

  function printAdminPage() {
   $options = $this->get_admin_options();

   if (isset($_POST['update_greader_sub_list_settings'])) {
    if (isset($_POST['greader_sub_list_login'])) {
     $options['google_login'] = $_POST['greader_sub_list_login'];
    }
    if (isset($_POST['greader_sub_list_pass'])) {
     $options['google_pass'] = $_POST['greader_sub_list_pass'];
    }

    update_option($this->admin_optionsName, $options);
    echo '
' . _e('Settings Updated.', 'GoogleReaderSubList'). '


';

   }
   //$submit = _e('Update Settings', 'GoogleReaderSubList');

   echo "

                                                

                                                

                                                
                        

Quick Google Authentication in PHP

Here is a quick way to authenticate against Google and retrieve a protected feed. It does not use the supported ClientLogin method but it does allow you to get to some unsupported feeds (Reader, Bookmarks, etc)

The Zend Gdata library is required

$show_list       = 'show-google-reader-sub-list';  //the hook in a page
$login          = '';
$pass          = '';
$source         = 'wordpress-google-reader-sub-list-';  //the source the api sees when logging into Google
$service         = 'reader';
$login_url        = 'https://www.google.com/accounts/ServiceLoginAuth?service=mail'; //URL to login to google
$subscription_list_url  = 'http://www.google.com/reader/api/0/subscription/list'; //URL that holds a users subscriptions

$client = new Zend_Http_Client($login_url);

//connect, authenticate, and handshake with Google
$client->setCookieJar()
->setMethod(Zend_Http_Client::POST)
->setParameterPost(array(
 'continue'             => $subscription_list_url,
 'service'              => 'reader',
 'niu'                  => 1,
 'hl'                   => 'en',
 'Email'              => $login,
 'Passwd'               => $pass,
 'PersistentCookie'     => 'yes',
 'asts'                 => ''
));

$response = $client->request('POST');
$client->setUri($subscription_list_url)->setMethod(Zend_Http_Client::GET);
$response = $client->request()->getBody();

if ($client->request()->getStatus() == 400) {
?>Unable to login with supplied Google login/password

GWTPHP = Google Web Toolkit + PHP 5

I know there is a pretty high number of programmers who haven’t tried to dable GWT yet because out of the box, the back end is java only.  PHP developers rejoice!

Unlike most of the other frameworks, GwtPHP is a framework for both client and server part. In GwtPHP you don’t need to hack JavaScript, you work with modern, object oriented languages. User interface (client) is programmed in Java, then compiled by Google Web Toolkit (GWT) to browser-dependent JavaScript. Server part uses PHP 5.

Not yet available to the public, but you can sign up to be notified when it is

HOWTO: Displaying Blogger feeds with PHP

This HOWTO is going to follow the basic structure of the Python one.

To start out you’ll have to grab the Zend Google data Client Library and then set the include_path so you can use it

ini_set("include_path", ".:../:./include:../include:/home/gpowered/webapps/php/includes/ZendGdata-1.0.1/library");

We then import the parts the we’ll need:

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

One of the first things we’re going to have to do is authenticate with google services.
There are two ways to do this: AuthSub proxy authentication which has a user login using their own credentials, and
ClientLogin username/password authentication where you send a username and password. We will be using ClientLogin. I built a small class called gPoweredBlogger to hold the different parts I will need for this example.

class gPoweredBlogger{
 private $user;// = 'timothy.broder';
 private $pass;// = '**************';
 private $service;// = 'blogger';

 private $blog_id;// = '413573351281770670';
 private $uri;// = "http://www.blogger.com/feeds/" . $blog_id . "/posts/default";
 private $show_num;// = 5;

 private $client;// = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
 private $gdClient;// = new Zend_Gdata($client);
 private $query;// = new Zend_Gdata_Query($uri);

 private $total_posts;

 public $output;

Then we start setting up our call to the service.

 public function __construct($user, $pass, $blog_id){
  $this->user = $user;
  $this->pass = $pass;
  $this->service = 'blogger';

  $this->blog_id = $blog_id;
  $this->uri = "http://www.blogger.com/feeds/" . $this->blog_id . "/posts/default";
  $this->show_num = 5;

  $this->client = Zend_Gdata_ClientLogin::getHttpClient($this->user, $this->pass, $this->service);
  $this->gdClient = new Zend_Gdata($this->client);
  $this->query = new Zend_Gdata_Query($this->uri);
  $this->total_posts = $this->get_total($this->query);
 }

For more info see the blogger developer’s guide with php or the Google Account Authentication documentation
After we have authenticated with Google we need to start building up our query to GData. The first thing you’ll need is your blog’s id.
You can use the function in the dev guide to help you with this if you don’t already know it.

Like the Python version, the below function returns the total number of posts that are in the feed. We can get a small response by sending 0 for the max results. Below is the function and the small response we get from it.

 private function get_total($query){
  //query for no posts
  $this->query->setParam('max-results', '0');
  $this->query->setParam('start-index', '1');

  //get back entryless feed
  $feed = $this->gdClient->getFeed($this->query);
  return $feed->totalResults->text;
 }

 5
 0
 1
 Blogger
 Tim
 tag:blogger.com,1999:blog-413573351281770670
 
 
 
 
 gPowered
 2007-07-18T10:55:06.728-05:00

So we get the total number of posts and then we can start pulling data. Lets make a generic function, PostFrom, that can be used to show multiple posts, or just single ones, depending on what you pass to it. The start number that is passed to
PostFrom has been set to the first post in the blog is considered to have an id of 1 and the latest post is the same as total_posts. This is useful so if viewers want to bookmark the page they are looking at, the post that is being displayed will not change.
The following are the different functions that will make use of it.

 //show latest posts
 public function Posts(){
  return $this->ListPosts($this->total_posts);
 }

 //show posts starting from a certain point
 public function ListPosts($start){
  $start = $this->total_posts - $start + 1;
  return $this->PostFrom($start, $this->show_num);
 }

 //show a single post
 public function Post($start){
  $start = $this->total_posts - $start + 1;
  return PostFrom($start, 1);
 }

 //show count number of posts starting from a certain point
 private function PostFrom($start, $count){
  //query for count number of posts starting at the given post
  $this->query->setParam('max-results', $count);
  $this->query->setParam('start-index', $start);
  $feed = $this->gdClient->getFeed($this->query);

Now we have all the data we need in the feed variable. Its been turned into an object so we don’t have to worry about XML parsing here. Every node has become an objects and lists. Objects for single nodes(title), and lists for where there are multiple nodes of the same name (entry, link)

  //for links
  $curr_id = $this->total_posts - $start + 1;

  //normalize data for output
  foreach($feed->entries as $entry){
   //id for links
   $entry->my_id = $curr_id;
   $curr_id -= 1;

  }

Of course we’re going to need next and previous buttons as well. The way we’ve set up the math with total_posts and the start number, we only have to increment or decrement these by count (the number of posts to display on a page). I also set part of the link, as well as the page title, that I will use below in the HTML.

  $prev = $this->total_posts - ($start - $count) + 1;
  if($prev > $total_posts){
   $prev = null;
  }

  $next = $this->total_posts - ($start + $count) + 1;
  if($next < 1){
   $next = null;
  }

  //showing single post
  if(count == 1){
   $link = 'post';
   $title = $feed->entries[0]->title->text;
  //listing posts
  }
  else{
   $link = 'posts';
   $title = 'home';
  }

The final part is to make a quick object that we can use in the HTML to output everything

  $this->output = new Output($feed->entries, $title, $prev, $next, $link);
 }
} 

class Output{
 public $entries;
 public $title;
 public $prev;
 public $next;
 public $link;
 public function __construct($entries, $title, $prev, $next, $link){
  $this->entries=$entries;
  $this->title=$title;
  $this->prev=$prev;
  $this->next=$next;
  $this->link=$link;
 }
}

To the HTML!

The first part consists of displaying the post itself, along with its relevant information. So lets built up our objects

$blog = new gPoweredBlogger('timothy.broder', '*************', '413573351281770670');
$blog->Posts();

$output = $blog->output;

Below all the php we can run through out output object and display the posts

<? foreach($output->entries as $entry){ ?>
     <h2><a href="/post/<? echo $entry->my_id ?>"><? echo $entry->title->text ?></h2></a>
     <? echo $entry->content->text;
     $datetime = strtotime(substr($entry->published, 0, 10) . ' ' . substr($entry->published, 11, 8 ));
     ?>
     <p>Posted by <? echo $entry->author[0]->name->text ?> on <? echo date("m/d/Y",$datetime) ?> at <? echo date("g:i a",$datetime) ?></p>

      <div id="divider"></div>
      <?}?>

That’s all for now. A working example is here

Performance Optimization WordPress Plugins by W3 EDGE