📜 ⬆️ ⬇️

Import sites from different CMS to Drupal

I think that everyone who uses Drupal in their work, periodically have problems transferring sites running on other CMS, or just the task of importing data to the Drupal platform.

I occasionally have such tasks, but before I did all the import by writing a script in php, which simply writes the necessary information directly into the Drupal database. Of course, I knew that there are mechanisms that allow adding data using the Drupal API, but somehow I was too lazy to deal with them, and the script for writing to the database immediately is written pretty quickly.

When a site on Drupal is fairly simple and it does not use any complex modules (and there are few of them), then this principle of import (direct recording in the database) is justified. But what to do when you need to transfer data to a very complex site with a lot of modules and their complex configuration?
')
In this case, the knowledge of the Drupal API will greatly help, since all the work on the correct update of all interrelated tables with all the clever settings for us will make Drupal.

As it turned out, using Drupal's API is not so simple, but very simple. About this will be today's article.

So, we have a site on Drupal, in which there are several types of content, for each type an additional field with a picture (CCK is used) is added, a lot of views are made (Views are used), and ImageCache is used for cutting pictures (a very buggy thing, but better so far there is nothing). The site works on Drupal 6. I think that with other versions it will be the same, but you will most likely have to tweak the code a bit, since The API is somewhat different.

The data import script will be located in the root of the site and called up via an http request, something like hxxp: //site.ru/import.php. How you will transfer data for import (using other databases, reading files on disk or through POST-data) is your business, it doesn't change the essence.

First of all, let's post this piece of code at the very beginning of our script:

require_once 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); 


This piece of code loads the core of Drupal and makes all the necessary settings to connect to the site database.

Next, we need to connect to our data sources and download the necessary data.

Suppose we need to add news to the site, for this we write the following code:

 $node = new stdClass(); $node->title = " "; $node->body = "<p>HTML- </p>"; $node->teaser = $node->body; $node->type = "news"; $node->created = time(); //   $node->changed = $node->created; //   $node->status = 1; //   $node->format = 1; //   Filtered HTML $node->comment = 2; //   $node->uid = 0; //   "",   uid=1,      $node->language = 'ru'; //     node_save($node); $new_id = $node->nid; 


To create a new node, we need to create an instance of the stdClass class and fill it with the necessary data. In this example, the headline of the news, its body, teaser is indicated. The type of content (type) I have indicated «news», so in my site are marked news. The type can be any other, since almost everything in Drupal is done through the concept of a node.

Actually, the use of the Drupal API lies in the only line - the call to the node_save method, to which the completed class instance for the node data is passed. This method makes an entry in the node, node_revisions tables and, possibly, in other related tables, you no longer need to think about it.

If you want to get the ID of the recorded node, then immediately after calling node_save, read the value in the $ node-> nid variable (the function itself will add a new property and write the value there).

Now we need to add an additional CCK-field to our news. In my case, it will be the field_img field, which is used to output a picture to the news, and ImageCache is used when you need to display either a thumbnail or a slightly smaller copy of the picture, because images can be of different sizes, then all of them through the ImageCache are customized to the specified size.

To add a new field to our node, you need to add a picture as a “file” in Drupal, and then, using the resulting “file” identifier, write down all the necessary data on the CCK-field.

 $file = new stdClass(); $file->uid = 0; $file->filename = "newsimage.jpeg"; $file->filepath = "files/newsimage.jpeg"; $file->filemime = file_get_mimetype($file->filename); $file->filesize = filesize($filepath); $file->status = 1; $file->timestamp = time(); $file->origname = ""; drupal_write_record('files', $file); $file_id = $file->fid; 


Here filename is the name of the file, filepath is the name of the file with relative (from the site root) path, in this case we assume that all our pictures are in the files folder. Next comes the function call to specify the mime type of the image (you can simply specify “image / jpeg” by hand) and the file size calculation. After that, the api-function drupal_write_record is called, which simply writes the $ files structure to the system files table. It turns out that this is a kind of analog wrapper around the function of writing data to the Drupal database.

Now we add all the data for the CCK-field to the node and save it:

 $node->field_img[0]['fid'] = $file->fid; $node->field_img[0]['data']['alt'] = $node->title; $node->field_img[0]['data']['title'] = $node->title; node_save($node); 


And finally, I will give the solution of a very strange and unpleasant glitch with ImageCache. By itself, the module works fine and it is very convenient, only Drupal does not want to call it at the right moment, i.e. After importing news to the site and updating the page, we will not see thumbnails from ImageCache.

The thing is that ImageCache is called only at the moment when a 404 error occurs when accessing a file with a picture. In theory, ImageCache should intercept this error, and if there is an appeal to a nonexistent picture, then generate it, and then issue the picture itself with the 200th code. But it does not.

I rummaged through a bunch of forums, tried to dig into the code myself, but did not understand why the picture was not generated. Therefore, I decided to directly generate images via ImageCache directly using the Drupal API right at the time of importing the news.

Here I call this piece of code immediately after saving the CCK-field with the picture:

 //  thumbnail- $preset = imagecache_preset_by_name("thumb"); $dst = imagecache_create_path($preset['presetname'], $file->filepath); imagecache_build_derivative($preset['actions'], $filepath, $dst); //  preview- $preset = imagecache_preset_by_name("preview"); $dst = imagecache_create_path($preset['presetname'], $file->filepath); imagecache_build_derivative($preset['actions'], $filepath, $dst); 


After that, the necessary pictures are created in the necessary folders and this known glitch disappears.

Here is the entire code:

 require_once 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); $node = new stdClass(); $node->title = " "; $node->body = "<p>HTML- </p>"; $node->teaser = $node->body; $node->type = "news"; $node->created = time(); //   $node->changed = $node->created; //   $node->status = 1; //   $node->format = 1; //   Filtered HTML $node->comment = 2; //   $node->uid = 0; //   "",   uid=1,      $node->language = 'ru'; //     node_save($node); $new_id = $node->nid; $file = new stdClass(); $file->uid = 0; $file->filename = "newsimage.jpeg"; $file->filepath = "files/newsimage.jpeg"; $file->filemime = file_get_mimetype($file->filename); $file->filesize = filesize($filepath); $file->status = 1; $file->timestamp = time(); $file->origname = ""; drupal_write_record('files', $file); $file_id = $file->fid; $node->field_img[0]['fid'] = $file->fid; $node->field_img[0]['data']['alt'] = $node->title; $node->field_img[0]['data']['title'] = $node->title; node_save($node); //  thumbnail- $preset = imagecache_preset_by_name("thumb"); $dst = imagecache_create_path($preset['presetname'], $file->filepath); imagecache_build_derivative($preset['actions'], $filepath, $dst); //  preview- $preset = imagecache_preset_by_name("preview"); $dst = imagecache_create_path($preset['presetname'], $file->filepath); imagecache_build_derivative($preset['actions'], $filepath, $dst); 


Used materials:
api.drupal.org/api/drupal/6 - official documentation
www.drupal.ru - site search for the query “data import”

PS: the use of the method I proposed is not limited only to the Drupal API, it is also possible to call the functions of the connected modules directly, as demonstrated by the example of the ImageCache functions.

Source: https://habr.com/ru/post/119224/


All Articles