Information management with WORDPRESS / PART II : bulk editing

While comparing wordpress woocommerce with magento, I pointed out the very efficient bulk editing feature for products in magento : it's quite amazing to find out that new versions of wordpress bring features you would not even imagine. Version 2.7 of wordpress, brought to the world in december 2008, brought the famous Batch and inline editing, also known as BULK EDITING. Our main interest of bulk editing in wordpress for information management is the bulk editing of tags and categories. Codex mentions fields that can be bulk edited.

Bulk Edit allows the fields, Author, Comments Allowed, Status, Pings Allowed, and Sticky, to be changed for all the selected Posts

Limitations : wordpress codex highlights the fact that Categories and Tags can be ADDED in bulk to a set of Posts, but it is not possible to CHANGE, or DELETE, a Category, or Tag, for those Posts.

the delete category feature is an important issue, as moving products, posts, or other elements does involve adding categories but obviously you'd need to remove categories from posts : this was the subject of a discussion topic on wordpress forum where some piece of code was posted : read Remove Categories with bulk edit to find this piece of code that could be transformed into a plugin or simply added to your theme.

Woocommerce extra bulk edit

woocommerce plugin is a perfect exemple of the extensibility of the bulk editing feature : price information (% increase or decrease), sale information,status, weight and stock information can be bulk edited. developers will find interesting coding information for adding extra fields to the bulk editing feature in woocommerce codebase.

worpress-woocommerce-bulk-edit

 

 

Other extensions and plugins

for coders

for non coders

Magento and WordPress integration : custom connection solution

Wordpress has various mega menu possibilities that we integrated in magento

WordPress has various mega menu possibilities that we integrated in magento

Lately we were comparing   ecommerce solutions that we have experienced in various projects : Magento for big and expensive projects versus woocommerce for smaller projects that are bound to expand. A big advantage of wordpress is that it integrates powerful content management and powerful ecommerce solutions within the same platform. And in some cases, Magento solution for e-commerce integrated with wordpress for content management can be the very good solution that takes the best of both worlds.

Today we review solutions that allow reciprocal integration of data between wordpress and Magento.

Basic wordpress content into magento

installing magento extensions require some expertise but is worth the time spent. Integrating wordpress posts into magento pages is easy with the  Magento WordPress Integration extension that fits worpdress post list and content within magento templates.

 

Global WordPress Magento integration : custom solutions

  • First, you must consider installation on the same server, sharing stylesheets and body elements to have consistency across the whole site : before choosing magento template and wordpress theme, bear in mind that stylesheets and javascript from both themes will be shared.
  • Next step consists of taking wordpress theme elements and sending them to a cache folder for integration in to Magento. We propose to integrate following wordpress elements in Magento
    • Main wordpress menu integration into Magento
    • Widgets elements (footer, sidebar)
    • latest articles

WordPress : Combine Jquery slider and iphone touch swipe

in the process of building responsive themes, a challenge that's getting easier every day, you might encounter the need to satisfy your customer with touch reactivity : we describe here how to combine a nice and light slider plugin we donated 5$ to, bxslider, and the now famous jquery touchswipe plugin that brings touch reactivity to your web page if you look at it on your iphone, ipad, or any touch screen device . We have built a plugin and a custom code for gallery post format, specifically for wordpress default theme twentyeleven.

 

  • the plugin : bxslider , very easy : 
    • create the plugins/bxslider directory, and a bxslider.php file that contain
      <?php
       /*
      Plugin Name: POLEOUEST-bxslider
       
      Description: 
      Author: erwan
      Version: 0.3
      Author URI: http://poleouest.Com/
      */
      
      function my_init() {
          if (!is_admin()) {
            wp_enqueue_script('jquery');
            wp_enqueue_script('touchswipe', plugins_url('js/jquery.touchSwipe-1.2.5.js',__FILE__));       
            wp_enqueue_script('bsxslider', plugins_url('js/jquery.bxSlider.min.js',__FILE__));
           wp_enqueue_script('bsxslider', plugins_url('js/jquery.easing.1.3.js',__FILE__));     
          }
      }
      add_action('init', 'my_init');

      s

 

    • put the appropriate javascript files in the js directory
  • the gallery post format code (loop code
                <div id="slider1"  >
    				<?php
    					$images = get_children( array( 'post_parent' => $post->ID, 'post_type' => 'attachment', 'post_mime_type' => 'image', 'orderby' => 'menu_order', 'order' => 'ASC', 'numberposts' => 999 ) );
    					if ( $images ) {
    						$total_images = count( $images );
    						foreach ($images as $image)
    						{
                                $image_img_tag = wp_get_attachment_image( $image->ID, 'large' );
    				?>
                 
    				<div>	 <?php echo $image_img_tag; ?></div>
    				 <!-- .gallery-thumb -->
                                           <?php }?>
     </div>
                
                <script>
                var slider="";
    jQuery(document).ready(function(){                
          slider =jQuery('#slider1').bxSlider({auto:true});   
         jQuery('#slider1').swipe( {swipeLeft:swipeLeft, swipeRight:swipeRight,threshold:0} ); 
        
    
      });
       function swipeLeft(event){slider.goToNextSlide();}            
       function swipeRight(event){slider.goToPreviousSlide();     }        
                </script>
               <?php          } ?>

    )

 

and there you go.

 

Crud for code igniter

Code igniter is a popular php development framework that comes with basic functions for database management and is the basis foundation for a few projects that perform database records CRUD (create Read update Delete) functions

  • http://carbogrid.sourceforge.net/
  • http://www.grocerycrud.com/ is a lightweight but efficient database CRUD solution, that offers a lot of useful implementations straight out of the box : 
    • flexi grid tables
    • automatic wysiwyg editor
    • ajax enabled swf file upload field
    • 1 to n and n to  n  relation ship
    • callback enables you to define extra behaviour for a lot of events : add record, modify, delete..

ATK framework : works with Zend

ATK is  a very professionnal database administration scaffolder : it has a full set of features, including relationnal records administration within tabs, hierarchical tree for hierachical data, n to n relationship, everything is coded via classes that define the , data table , the presentation mode, and its relationship with other tables. The great bonus of ATK is that is it not exclusive : one suggestion of the team is to use ATK for quick backend developpement  and Zend Framework for serious front end development.

http://www.atk-framework.com/

mobile device screen resolution

Planning on developping websites for mobile devices and touch screens ? here is a list of devices and  screen resolution


Iphone 3 480 x 320
iphone 4 960 x 640
Ipad1 1024 x 768
ipad 2 2048 x 1536
Itouch 960 x 640
Samsung galaxy 800x480
HTC EVO 4G 800x480

Publish, write, on Ipad, Iphones

ever dreamed of the ideal development tool for Iphone, Ipad ? Well we've started to investigate the subject of going mobile in a cross hardware compatible manner. Today we go more precisely into mobile publishing, with the LAker technology that uses HTML5 to enable easy digital publishing on iphones and ipads.

Being specifically target for Apple, the Laker framework is a set of development features that allow

  • various content type publishing : text, photo galleries, videos
  • automatic content resizing for the devices

works without a web server, means the app you'll develop is autonomous on the device and does not require an internet  connection to read.

http://www.lakercompendium.com/

Another similar development tool is phoneGap (already mentionned), works on 6 platforms using web standards : http://www.phonegap.com/

Magento : programmatically add custom options for products

I've found plenty of places on magento forums and websites that mention adding custom options to products : none of them seemed to work on my installation (1.5) so I suppose each version has its own tweaks. The technique below catches a specific event that is fired when the product is being saved from the admin. A good tutorial on Magento events can be found here, pseudo official list of events can also be found on Magento's wiki, probably outdated though. What I need now is to find the appropriate code to delete options from a product. not simple either... Anyone tried?

The way I did is the following

  • create a custom module PoleOuest_CustomOptions_Model_Observer 
    app/local/PoleOuest/CustomOptions/Model/Observer.php




     class PoleOuest_CustomOptions_Model_Observer
     {
    
          public function Add_CustomOptions_Automatically($observer) {
    
                $event = $observer->getEvent();
        $product = $event->getProduct();
    
       // if ($product->getDecodirect())
         //   {
            $optionData = array(
      'is_delete'         => 0,
        'is_require'        => false,
        'previous_group'    => '',
        'title'             => 'want to preorder ? ',
        'type'              => 'checkbox',
        'price_type'        => 'fixed',
        'price'             => '20.0000',
        'sort_order'        => 0,
    
               'values'            => array(
            array(
                'is_delete'     => 0,
                'title'         => 'preorder',
                'price_type'    => 'percent',
                'price'         => -20,
                'sku'           => 'product sku',
                'option_type_id'=> -1,
            ))
    
            );
            $product->setHasOptions(1);
    
           $opt = Mage::getModel('catalog/product_option');
            $opt->setProduct($product);
            $opt->addOption($optionData);
            $opt->saveOptions();      
    
                   Mage::log("option should be added now");
         // }
          }
    
     }
  • catch product save before event in app/local/PoleOuest/CustomOptions/etc/config.xml
    <?xml version="1.0" encoding="utf-8"?>
    <config>
        <modules>
            <PoleOuest_CustomOptions>
                <version>0.0.1</version>
            </PoleOuest_CustomOptions>
        </modules>
        <global>
            <events>
                <catalog_product_save_before>
                    <observers>
                        <custom_options>
                            <type>singleton</type>
                            <class>PoleOuest_CustomOptions_Model_Observer</class>
                            <method>Add_CustomOptions_Automatically</method>
                        </custom_options>
                    </observers>
                </catalog_product_save_before>
            </events>
        </global>
    </config>

Mapress pro : use taxonomies to generate maps

Mappress pro, a plugin for wordpress, is worth its price : it can automatically create maps from custom fields adresses. I needed the possibility to create maps from a specific taxonomy, and this requires some hacking. here's the way to go for serious coders who want, like me, to spend one  intense hour . hope mappress pro incorporates that for future buyers !!

FIRST STEP : create a new configuration option for mappress to specify the custom taxonomy

  • in mappress.php
add_setting_field('customTaxonomyMap', __("Custom Taxonomy", 'mappress'), array(&this, 'setTaxonomy'), 'mappress', 'mappress_pro_settings'));
function set_custom_taxonomy_map() {
$options = Mappress_Options::get();
$pro_link = "<a href='http://wphostreviews.com/mappress/mappress-pro' title='MapPress Pro'>MapPress Pro</a>";
printf(__("This setting requires %s.  Automatically create maps from custom taxonomy.", 'mappress'), $pro_link);
}
in mappress_pro.php
  • function set_custom_taxonomy_map()
    {        $options = Mappress_Options::get();
        echo __(" Update map when terms are added to a post in the following taxonomy  ", "mappress");
            echo "<input type='text' size='30' name='mappress_options[customTaxonomyMap]' value='"  . $options->customTaxonomyMap. "'/>";}
  • and in mappress_api, don't forget to declare your new option as class variable of Mappress_Options
    $customTaxonomyMap=""

SECOND STEP : implement action hooks to create the map when the post is saved

  • in mappress_pro.php, function Mappress_Pro()
            if ($options->customTaxonomyMap) {
                    add_action('deleted_term_relationships', array(&$this, 'term_delete'), 10, 4);
                    add_action('added_term_relationship', array(&$this, 'term_added'), 10, 4);
            }
  • and
     function getTaxonomyMapKey($taxonomy)
      {
          return "tax" . $taxonomy;
      }
    function term_added($postid, $termId) // poleouest
    {
         $options = Mappress_Options::get();
        $taxonomy=$options->customTaxonomyMap;
        $mapMetaKey=$this->getTaxonomyMapKey($taxonomy);
        $pois=array();
        $this->term_delete($postid, $termId);
        $terms=get_the_terms( $postid, $taxonomy );
          foreach( $terms as $term ) {
              $city=$term->name;
            add_post_meta($postid,"hello",$city);
        if ($city!="")
        {$atts = array("address" => $city);
        $atts = $this->scrub_atts($atts);
    
       $poi = new Mappress_Poi($atts);
       $result = $poi->geocode(true);
       $pois[] = $poi;
        $map = new Mappress_Map();
    
            // Update with new POIs
            $map->update(array('pois' => $pois, 'title' => $city, 'metaKey' =>$mapMetaKey, 'center' => array('lat' => 0, 'lng' => 0)));
            $map->save($postid);
        }
          }
    }
    function term_delete($postid, $termId) // poleouest
    {
         $options = Mappress_Options::get();
        $taxonomy=$options->customTaxonomyMap;
        $mapMetaKey=$this->getTaxonomyMapKey($taxonomy);
         $map = Mappress_Map::get_post_map($postid, null, $mapMetaKey);
       if ($map)  $map->delete();
    }

Developp Iphone apps without – or with – mac

Obviously, the best way to develop iphone apps is to use the native development kit. But alternative tools offer possibilities that expand beyond the iphone and can offer multi device compatibility.

  • Mobincube is hosted service, has a free lite version, creates apps for iphone and java code for java compatible phones, blackberry, android apps
    http://www.mobincube.com
  • Phonegap is for web developers who'd have a go at iphone development via javascript : phonegap simply emulates html5. Iphone, Android, Blackberry compatible
  • Same for Appcelerator, distributor of the titanium for mobile development tool that enables developers with HTML skills to implement IPhone specific UI
  • Swebapps distribute pre defined iphone app template
  • JQtouch is  a jquery plugin that implements browser based web based applications
  • OPA is a single development platform and language that replaces PHP / MYSQL for  web based applications

More examples (13) on readwriteweb

Efficient SEO with Advanced Web Ranking dedicated software

Keyword analysis from search engine results, keyword density advice from your website content, evolution of specific website ranking data (position, rank, competitors), these are some of the powerful web site ranking analysis features provided by Advanced Web Ranking, distributed online by Caphyon Ltd.

Before you engage costly advertising programs for your website, be sure you have explored the powers of natural search engine optimization, one technique that provides best Return on Investment. A set of techniques that can doesn’t require financial investments but will certainly prove time consuming : natural search engine optimization means that you’re going to spend a few weeks monitoring the website you’re working on, and try to improve position in search engines on specific keywords.

It’s quite easy to work on one or two main keywords. But most websites rely on powerful content management platforms such as wordpress, or e commerce application like Magento, and have the potential to render thousands of distinct pages with unique content. That’s where real work starts, and there are two main reasons why I would recommend the assistance of specific search engine ranking software like Advanced  Web Ranking. I’ve tested the software in a localized version for French websites, and the amount of reports it can produce is worth the few minutes required to handle the configuration  learning. I will explain below the three angles of time consuming tasks that the software can save.

Read more

Magento configurable products : display images of sub product

In a previous article, I explored a technique that displays the first image of a sub product when selected in Magento's configurable product page. This time we go one step further by changing the set of thubmnails to display all images associated with the selected sub / simple product. this tutorial requires completion of the the previous one  including the magento wiki 'Change Product Image on View Page to Associated Product's Image' before you go ahead :

  1. in your media.phtml file, the big images are loaded via html. the image id is a collection of images from which only the first one is displayed initially, the other are waiting for the thumbail to be clicked. Simply add here the images collection from associated products,  each image being allocated a css ID built from product id and the increment
            <?//<associated product all images>
                if ($_product->getTypeId() == "configurable") {
            $associated_products = $_product->loadByAttribute('sku', $_product->getSku())->getTypeInstance()->getUsedProducts();
              foreach ($associated_products as $assoc)
                {
                $assocProduct =Mage::getModel('catalog/product')->load($assoc->getId());
                 $i=0; 
    
                 if (count($assocProduct->getMediaGalleryImages()) > 0) {
                       foreach ($assocProduct->getMediaGalleryImages() as $_image)
                        {
                         $imageFile=str_replace(Mage::getBaseUrl('media'),"",$_image->url);
                         $imageId=$assoc->getId() . "_" . $i++;?>
                          <div onclick="showZoom('<?=$imageFile?>')" class="jqzoom">
                  <img style="z-index:-1;display:none" id="image<?php echo $imageId; ?>"
                  width="340px"
                  height="250px"
                  src="<?php echo $this->helper('catalog/image')->init($assocProduct, 'thumbnail2', $_image->getFile())->resize(350, 250); ?>"
                  alt="<?php echo $this->htmlEscape($assocProduct->getName()) ?>"
                    jqimg="<?php echo $_image->url; ?>"></div>
                <?php
                         }
                    }
                }
                } //</associated product all images>
            ?>
  2. in the same file, below, the images thumbnails are displayed in unordered lists. What you need to do here to create one unordered list per associated product, with a display none styling  :
                <?//<associated product all images>
                if ($_product->getTypeId() == "configurable") {
            $associated_products = $_product->loadByAttribute('sku', $_product->getSku())->getTypeInstance()->getUsedProducts();
              foreach ($associated_products as $assoc)
                {
                $assocProduct =Mage::getModel('catalog/product')->load($assoc->getId());
                $i=0;
                 if (count($assocProduct->getMediaGalleryImages()) > 0) { ?><ul id="teckLoom<?=$assoc->getId()?>" style="z-index:-1;display:none">   <?
                       foreach ($assocProduct->getMediaGalleryImages() as $_image)
                        {
                         $imageFile=str_replace(Mage::getBaseUrl('media'),"",$_image->url);
                         $imageId=$assoc->getId() . "_" . $i++;?>
                         <li>
                <a href="#" onclick="jSelectImage('<?=$imageId ?>'); return false;">
                <img src="<?php echo $this->helper('catalog/image')->init($assocProduct, 'thumbnail', $_image->getFile())->resize(70); ?>" alt="<?php echo $this->htmlEscape($_image->getLabel()) ?>" title="<?php echo $this->htmlEscape($_image->getLabel()) ?>" />
            </a>         </li>
    
                <?php
                         }      ?></ul> <?
                    }
                }  }
                  //</associated product all images>   ?>
  3. use the select color  function from our previous article to display the associated image set when an option is selected via image click :
    function selectColor(idAttribute, idProduct)
    {
    jQuery('#attribute76').val(idAttribute);
    spConfig.reloadPrice();
    displayProductConfigImage(idProduct);
    jQuery(".more-views ul").hide();
    jQuery(".more-views ul#teckLoom" + idProduct).show();
    }
  4. add the following code to js/varien/product.js to let the effect work when an option is selected in the dropdown menu :
    var productNo = intersect(selectedAssocProducts) || selectedAssocProducts[attributeId][0];
    //alert(jQuery("#image0").attr('src'));
    //$('image').attr("src", assocIMG[productNo]);
    displayProductConfigImage(productNo);
    jQuery(".more-views ul").hide();
    jQuery(".more-views ul#teckLoom" + productNo).show();
  5. Have a look at the result on ruedesiam's lovely designed multi color loom furniture : try  the chaise giulietta

wp super cache and WP3.0 menus

For those who are running small servers and wish to accelerate their worpdress installation, we recommend the installation of eaccelerator but also the wp-super-cache plugin. There is just a small hack for wordpress 3.0 menu users : the cache should be totally refreshed when a menu is modified, and this is performed via the wp_update_nav_menu action, instantiated in the wp-cache-phase2.php / wp_cache_phase2 function

add_action("wp_update_nav_menu" , 'wp_cache_clear_cache' );

Read more

Magento Configurable products : change product image on thumbnail option

This article describes a  color chooser for magento product page, a technique that automatically use product attributes from a Magento admin to display color thumbnails that

  • allows end user to choose color option by clicking on thumbnail
  • change product image to associated product image

the technique above is inspired from Magento Wiki page that describes the javascript that catches the Options price select event to modifyu the product image. We've changed a few things though

  1. Read more

WordPress single install / multiple blogs

Yes it is possible to host multiple sites for multiple customers with WordPress. The Multi User feature we expeted in wordpress 3.0 will satisfy bloggers only but we need something more specific. The technique I describe here is similar to the one described here in the sense that it directs the database configuration constants to specific databases instead of table prefixes as seen a lot. The advantage obviously is that you keep a single install of wordpress and only have one codebase to manage , while databases remain independant.

  • create wp-domains folder, and inside one folder for each domain, example wp-domains/mysite.com
  • add the following code to wp-config.php : this coding allows a defualt domain to remain active even when the configuration file does not exist, at the expense of a loss in performance. But It is useful to show what's missing.

$domain = strtolower( str_replace( "www.", "", $_SERVER["SERVER_NAME"] ) );
$domain = preg_replace('[^a-z0-9\.-]', '', $domain );
$domainDirectory="/wp-domains/" .$domain;
$domainConfig= dirname(__FILE__) . $domainDirectory . "/db-config.php";
if ( file_exists( $domainConfig ) ) {require_once( $domainConfig );} else {
$dbuser="defaultdomaindatabase";
$dbpwd="password";
if ($domain!="defaultdomain.com") echo "missing " .$domainConfig;}

  • replace definitions with variables in wp-config.php

define('DB_NAME', $dbuser);
define('DB_USER', $dbuser);
define('DB_PASSWORD', $dbpwd);

Once this is working with your default  domain, setup virtual hosts  in Apache and try a new domain. Remember on a new install to setup the upload folder in wordpress admin settings.

Multi site config for WordPress : Compatible plugins

I'm running the following plugins and they work perfectly

  • WP Super Cache : works fine because the cache filename coding alogrithm includes the domain name

Jquery preload images

the implementation of jquery photo gallery is better performed when the thumbnail is dynamiccaly generated via some  magic library such as the old phpthumb. But this method doubles the amount of  images to load, especially the big ones that we want to pop in on thumbnail click. And that's where comes Ariel Flesler's jquery preload plugin, that allows some various configuration using jquery selector to specify which images should be preloaded. Another jquery plugin takes all images from css files and preload them, can be useful on all websites that rely on background images in styles.