Thursday, September 1, 2011

Moving Data to Drupal / Ubercart

Update (August 2011): We’re now recommending that people try using the Migrate module (http://drupal.org/project/migrate) first, before trying a custom-coded import solution. Use with MigrateUI, and check their list of required modules carefully (depends on version of Drupal you’re using). The solution below is for situations that Migrate can’t handle well, or where you need to do imports that tie into custom modules that have their own data tables. We’ve also built a similar importer as a Drupal module (its highly customer-specific – if there’s demand we can look at generalizing it) which can work well in situations where you need a quick upload and import inside the admin panel with a well-defined data layout (i.e. a CSV product list).

The following blog entry describes the solution to an issue encountered by Jeremy and Nathan in moving data from an old website to a new one. Based on a brief search for a solution, it looks like many other people may find a use for the (admittedly rather crude) code that we wrote to solve the problem. We hope this helps!

We’ve recently had to convert data from an old custom-built shopping cart, to a new website based on Drupal and Ubercart. The old website had approximately 5000 products, with a data structure that was completely unlike the one used by Drupal to store data. We initially tried using the Drupal data loader module, but as other people have discovered, it isn’t necessarily a good fit for loading Ubercart product data, particularly when the products have images, or – and this is especially the case – custom data fields.

You can download a copy of our script here.

In the end, we put together a custom php script to pull data directly from one database to another. The script is fairly crude, but it may be useful to somebody trying to import data into Ubercart from another non-standard system.

As a result, I will link a copy of the script below. Please bear in mind that a) we accept no responsibility whatsoever for its use (i.e. back up your databases first!!!), and b) while we have documented our assumptions, this is a crude script that is specifically designed for our particular needs. Be that as it may, you may be able to find a use for this.

Additionally, it was a pain just getting a list of the Drupal and Ubertcart tables that needed to be looked at in order to do the data conversion. The list below may be useful to you as well.

How it works:

The old shopping cart had two relevant tables: a category listing (hierarchical), and a products table, which included some customer specific fields, as well as a single url to a product photo.

Drupal/Ubercart, on the other hand, uses a large number of tables to represent the same data. This is because products use the same node-based system as the rest of Drupal, in addition to a number of product specific tables.

In addition, product images are dealt with using Drupal’s file cacheing system, which is relatively complex in nature. All in all, our data goes from two tables to approximately nine (depending on your specific needs) in Drupal.

The script has some handling – very buggy still – in place for keeping track of the current position in the old database. This means that you can run the data conversion in small chunks, checking at each point to see how well it is doing. You can also set how many records to convert each time. In order for this to work, a very simple table to track the record pointer needs to be added into the old database.

We did not cover the conversion of product categories, since typically there are a much smaller number of categories than products, and in addition, the Drupal data loader does a reasonably good job of loading them.

List of tables involved:

  • node – in Drupal, everything is a node, including products. Each new product record will need a corresponding node of the correct type.
  • node_revisions – this table contains much of the actual textual data (i.e. product description text) involved in displaying the node.
  • content_type_product – if you need to create custom fields for your Ubercart products, the data will go here. Our code in this section will probably not map directly to what you’re working on.
  • uc_product – where the product records “live”. There will be one record here for each of the product nodes.
  • uc_product_stock – contains stock-related data (i.e. how many of the product you have on hand etc) for products.
  • files – each product image needs to have a record in this table, which stores the file names and locations – but does not map these images directly to the product records (you need another table for that!).
  • content_field_image_cache – this is the mechanism that ties a product image to the underlying product. We didn’t really try to work with Drupal’s actual cache mechanism, so after you have loaded the products, you may want to clear the cache.
  • term_data – this is where product category information resides, based on Drupal’s vocabulary / hierarchy system. We hacked the solution in a fairly inelegant way – by doing a category name lookup to retrieve the term id.
  • term_node – a connection table between a term (i.e. a product category) and a node (in this case the products).

Base assumptions:

  • We assumed that the old and new websites both have mysql databases.
  • Both databases will probably have to be on the same server (or at least one of them needs to be externally accessible if that isn’t the case)
  • The script should be uploaded and run from the new website’s location.
  • We assumed that there is only one product image per product – although this would be fairly easy to modify.
  • We manually added our categories to the new website
  • We manually moved product images across – there are comments in the script where you could automate this though.
  • Error checking is extremely rudimentary; if this scripts hits a problem it just stops.
  • If you hit data conv snags, the fastest way to proceed is to restore your backup database, reset the pointer record, and start over.

Tuesday, August 23, 2011

City country example with ajax and php

"
Jquery and PHP

Test Page

Country
City
Please select one city
"

$country = $_REQUEST['country'];
switch ($country)
{
case 'ie':
$countries = array('city1_ie','city2_ie');
break;
case 'en':
$countries = array('city1_en','city2_en');
break;
default:
$countries = false;
}
if(!$countries) echo "There is no city";
else
// echo '';
echo '';


?>

Monday, August 22, 2011

Content Profile usage Guide

Content Profile User Registration Integration
----------------------------------------------

There is a small extension module shipping with the main module, which allows one to enable
registration integration per content profile.


This module builds upon the main content profile module. It allows to integrate
the form of one or more content profile into the user registration page.


Installation
------------
* Activiate the module.
* Be sure to read the usage notes below!
Usage:
--------
* When you edit a profile content type there will be a further tab "Content profile",
which provides content profile specific settings. There is now a new field group
called "User Registration" which allows you to enable this feature for a content profile.
* You need not grant anonymous users access to create the content profile. If you would do so,
anonymous users would be able to create anonymous profiles even without registering.
* If you use the "Content permissions" module, which comes with CCK, make sure you grant access
to fields that should appear for anonymous users.
* The weight of the profile (configurable at the content profile settings) controls the position
of the form elements on the registration page.

* You may also hide some form elements at the settings. Basically it allows you to hide non-required
CCK fields as well as the title. If the title is hidden, it is set to the user's name.
* For more control over the title use the "Automatic Nodetitles" module, which can be found
at http://drupal.org/project/auto_nodetitle. It integrates fine with this module.

* Hiding required CCK fields is not supported, as the created content node would have empty
required fields afterwards, which in affect would make it impossible even for admins to edit
the content node.
* So the "Hide other form elements" option allows you to hide all form elements not listed there,
but required CCK fields always stay.
However, you can still hide required CCK fields by restricting anonymous access to them by using the
"Content permissions" module of CCK. But be aware of this issue - maybe also restrict access for
other roles accordingly.

* If you want to hide the "body" field, just remove it from the content type in general at the content
type's settings page. Then instead of this, just create a CCK textfield, which can be hidden.

* You can enable the registration integration for multiple profiles - however be aware that
shared form elements like the title only appear once and all created profile nodes get the same
values assigned.
* For multiple registration paths for different roles, the AutoAssignRole module might help you:
http://drupal.org/project/autoassignrole. It comes with Content Profile Registration Integration,
so that you can select the profiles which should appear on each AutoAssignRole path (configurable
at the content profile settings). You'll need a version of AutoAssignRole released later than
June 4, 2009.

* If you want to prepopulate some other form elements, maybe hidden CCK fields you can use the rules
module for that. See http://drupal.org/project/rules.
Just configure a rule, that reacts on the creation of the content profile (event) and populates
your fields value (action).

* Putting file uploads on the registration form is not supported and probably won't work right.
* The CCK "Add more fields" feature is only working for users with javascript turned on in the
registration form. Users without javascript won't be able to add more fields. Interested developers
can find the related issue (in drupal itself) here: http://drupal.org/node/634984
-----------------------
Content Profile Tokens
-----------------------

Original author: @author Ádám Lippai - Oghma ltd. (lippai.adam@oghma.hu)


This is a small module that adds content profile tokens for textfields and number CCK fields for
a user as well as to the 'flag friend' modules' requester and requestee.

Warning: This module slows down the generation of users tokens, thus it might have some performance
implications for your site. Use it with caution.

Installation
------------
* Activiate the module.

Wednesday, May 25, 2011

image uploading

function imageuploading()
{
//get the original name of the file from the clients machine
$filename = stripslashes($_FILES['image']['name']);
//get the extension of the file in a lower case format
$extension = getExtension($filename);
$extension = strtolower($extension);
//if it is not a known extension, we will suppose it is an error and will not upload the file, otherwise we will do more tests
if (($extension != "jpg") && ($extension != "jpeg") && ($extension != "png") && ($extension != "gif"))
{
//print error message
echo '

Unknown extension!

';
$errors=1;
}
else
{
//get the size of the image in bytes
//$_FILES['image']['tmp_name'] is the temporary filename of the file
//in which the uploaded file was stored on the server
$size=filesize($_FILES['image']['tmp_name']);

//compare the size with the maxim size we defined and print error if bigger
if ($size > MAX_SIZE*1024)
{
echo '

You have exceeded the size limit!

';
$errors=1;
}
//we will give an unique name, for example the time in unix time format
$image_name=time().'.'.$extension;
//the new name will be containing the full path where will be stored (images folder)
$newname="images/".$image_name;
//we verify if the image has been uploaded, and print error instead
$copied = copy($_FILES['image']['tmp_name'], $newname);
if (!$copied)
{
echo '

Copy unsuccessfull!

';
$errors=1;
}
}
return $newname;
}

/********************Image Uplaoding ***********************/
$MM_authorizedUsers = "";
$MM_donotCheckaccess = "true";
define ("MAX_SIZE","2000");
/*****************************Uploading End ************************/


$image = $_FILES['image']['name'];
if($image)
{
$newname = imageuploading();
}else {
$newname = NULL;
}

Tuesday, May 24, 2011

Bring ckeditor


To add ckeditor they need
  • and then add class=ckeditor to the textarea.