مهاجرت به دروپال 7

بالاخره، ما هم تصمیم گرفتیم که دروپال 6 را کنار بگذاریم. اکنون وقت آن است که به دروپال 7 مهاجرت کنیم. کم کم دارم تلاش می کنم تا با ویژگی های جدید دروپال 7 آشنا شوم و معلومات قبلی خود در مورد دروپال 6 را به فراموشی بسپارم! اولین اقدام هم در این رستا، انتقال وبلاگ خودم از دروپال 6 به دروپال 7 بود. در حال حاضر این سایت از دروپال 7 استفاده می کند. از آن جایی که برای اولین بار بود که یک سایت نسبتا پر محتوا را از نسخه ی 6 به 7 Upgrade می کردم، کمی کار طولانی شد و کمی هم دشوار بود! در حال حاضر تمامی مطالب سایت به Drupal7 منتقل شده اند، اما هنوز پیکربندی سایت و تنظیمات آن کامل نیست و بعلاوه پوسته ی قبلی سایت را هم دارم به دروپال 7 تبدیل می کنم و به زودی سایت به شکل قبلی خود در خواهد آمد! برای دوستانی که تا حالا با دروپال کار نکرده اند، باید توضیح دهم که مهاجرت بین نسخه های Major دروپال چندان کار ساده ای نیست. یعنی بر خلاف برخی از CMS های دیگر، آپگرید کردن دروپال می تواند حتی در برخی شرایط بسیار بسیار مشکل باشد. زیرا میزان تفاوت هایی که بین دو نسخه ی 6 و 7 دروپال وجود دارد بسیار زیاد است. به ویژه برای سایتی که (مثل همین سایت) بیش از 100 تا ماژول فعال دارد، مهاجرت کردن قدری مشکل می شود. سایت های تجاری و بزرگتر که گاهی حدود 400 ماژول فعال دارند کار پر زحمتی خواهد بود. در ادامه شرحی از تجربیاتی که کسب کردم خواهم نوشت. هسته ی دروپال یک سیستم Update & Upgrade دارد که برای به روز رسانی اتوماتیک ماژول ها طراحی شده است. طرز کار آن به این صورت است که هر ماژولی در دروپال (چه در هسته و چه ماژول های کمکی) می توانند در فایل .install شان تعدادی تابع update تعریف کنند. نام گذاری این توابع از قواعد معینی پیروی می کند و هسته ی دروپال نیز سیستمی دارد که اطلاعات نسخه ی ماژول ها و به روز رسانی های آن‌ها را ردیابی می کند. به این ترتیب، هنگامی که می خواهیم یک یا چند تا از ماژول ها را به روز رسانی کنیم، روش کار به این صورت خواهد بود که ابتدا نسخه ی قبلی ماژول را پاک می کنید و ورژن جدید آن را دانلود کرده و در مکان قبلی آن extract می کنیم. به این ترتیب سورس ماژول به روز رسانی می شوذ. بعد نوبت دیتابیس است. دیتابیس هم باید به روز رسانی شود تا با نسخه ی جدید ماژول سازگار باشد (زیرا ممکن است نسخه ی جدید ماژول، اطلاعاتش را به گونه ای دیگر در دیتابیس ذخیره کند و ما باید اطلاعاتی که قبلا ذخیره شده را به فرمت جدید در بیاوریم تا نسخه ی جدید ماژول آن ها را بشناسد. برای این منظور کافی است اسکریپت update.php را اجرا کنیم. هنگامی که اسکریپت update.php را اجرا می کنیم، دروپال با توجه به اطلاعاتی که ردیابی کرده است و با توجه به توابع update موجود در فایل .install ماژول، مشخص می کند که کدام توابع update باید اجرا شوند. سپس توابع لازم را به ترتیب در یک Batch job اجرا می کند و این توابع موظف هستند که اطلاعات نسخه ی قبلی ماژول را به فرمت جدید به روز رسانی کنند. (البته ممکن است هر کار ضروری دیگر را هم انجام دهند. منحصر به این نمی شود)

بنا بر این متوجه شدیم که در دروپال، هر ماژولی موظف است خودش را آپدیت کند و معمولا این کار را هم به خوبی انجام میدهد. (که در قیاس با برخی از سایر CMS ها ایده ی بسیار بهتری است) در ضمن می دانیم که هسته ی دروپال هم خود از تعدادی ماژول تشکلیل شده است که مانند ماژول های دیگر هستند و از همین روال استفاده می کند.

با توجه به این اوصاف، انتظار می رود که Upgrade کردن دروپال کار بسیار ساده باشد. دقیقا درست است! به روز رسانی دروپال و ماژول هایش بسیار آسان است! (حتی به روز رسانی های major) اما، وقتی که صحبت از به روز رسانی که یک سایت دروپال از یک نسخه ی Major به نسخه ی Major بعدی باشد و بر روی سایت هم تعداد زیادی ماژول نصب باشد، آن وقت، بحث فرق می کند.

به لحاظ تئوری چنین به نظر می رسد که باید بازهم کار ساده ای باشد و همان روند Upgrade درونی دروپال پاسخگو باشد. اما به چند دلیل گاهی این کافی نیست:

1 - ماژول هایی که نسخه ی دروپال 7 آن ها هنوز Release نشده! 2 - برخی از ماژول ها مثل CCK برای دروپال 6 وجود دارد، ولی در دروپال 7، امکانات آن به هسته اضافه شده. البته با یک روش متفاوت! یعنی دروپال 7 به صورت درونی قابلیت های CCK را پشتیبانی می کند ولی روش انجام آن با خود CCK تفاوت دارد. 3 - برخی ماژول ها در دروپال 6 موجودند، اما برای دروپال 7 باید از ماژول دیگری استفاده کنیم که کاری تقریبا مشابه آن را انجام می دهد. مثل ماژول Node reference که در CCK 6.x بود ولی در دروپال 7 وجود ندارد. 4 - به روز رسانی فایل سیستم 5 - وجود relation بین اشیاء سایت معضل را دو چندان می کند. مثلا node ها و comment ها با هم رابطه دارند. User ها و Role ها با هم رابطه دارند. و در Views به این اشیا Reference هایی داریم. به عنوان مثال دقت کنید که هنگامی که در Views یک Role را انتخاب می کنید، شناسه ی آن که یک عدد است انتخاب می شود. حال فرض کنید در سایت جدیدتان، همان Role را درست کرده اید ولی شناسه ی آن چیز دیگری است (چون شناسه ها ی Role ها متاسفانه قاعده ی ساده ای ندارد!) در این جا است که Views شما دیگر کار خود را درست انجام نخواهد داد. 6 - …

مواردی که ذکر کردم به عنوان مشت نمونه ی خروار است و به این چند تا محدود نمی شود. و این البته بستگی دارد به طراحی سایت و این که شما تا چه حد سایتتان را درست و اصولی طراحی کرده باشید.

من به عنوان یک developer حرفه ای و نسبتا با تجربه در دروپال، از ابزار هایی که برای Upgrade کردن و Migration دروپال ساخته شده اند بی خبر نیستم. ماژول هایی مثل features و deploy و feeds و migrate و … هم وجود دارند که می توانند کار را تا حدی راحت کنند. اما استفاده از این ماژول ها گاهی چنان پیچیده است که آدم با خود فکر می کند که برای یک وبلاگ ساده، اگر دستی اطلاعات وبلاگ را یکی یکی منتقل کند زود تر تمام می شود!! (البته برای سایت های کوچک) برای سایت های بزرگ، باید از همین ابزار ها استفاده کرد.

اما من برای وبلاگ خودم، یک روش ابداعی خودم را استفاده کردم. کاملا مطمئن هستم که روش من بهینه نبوده و در این هیچ شک ندارم که قطعا روش های بهتری هم برای این کار وجود داشته، اما ترجیح دادم که برای مهاجرت به دروپال 7، روش آن را خودم ابداع کنم. روشی که توضیح می دهم، را به دیگران توصیه نمی کنم چون بدون شک بهینه نیست. اما با این حال، یک تجربه ی جالب دروپالی است و مطمئنا جنبه های آموزشی زیادی را در بر خواهد داشت.

من ترجیح دادم که از صفر شروع کنم و یک ماژول Migrator بنویسم. ابتدا یک ماژول برای دروپال 6 نوشتم که کلیه ی node های سایت قبلی ام را لود می کرد و آن ها را export می گرفت و در یک فایل متنی ذخیره می کرد. نام ماژول را گذاشتم myexport و آن را نصب کردم. سپس با یک کلیک توانستم تمامی node های سایت قبلی را در یک فایل متنی به صورت یک آرایه ی PHP داشته باشم (فرمت export گیری به صورت php array بوده) قصد ندارم که سورس آن را در این جا قرار دهم زیرا ماژول جالبی نشد و در ضمن ماژول های آماده دیگری هم وجود دارد که می توانید از سایت drupal.org دانلود کنید و همین کار export گیری node ها را انجام می دهند و خیلی هم بهتر هستند.

سپس ماژول ساده ی دیگری برای Drupal 7 نوشتم که این اطلاعات را از درون فایل متنی می خواند و در دروپال 7 وارد می کند (یعنی یک دروپال 7 جدید نصب کردم و با این ماژول توانستم node های قبلی را در سایت جدید import کنم) نام ماژول را myimport گذاشتم

سورس ماژول را در انتهای ضمیمه می کنم که ماژول ساده ای است و امیدوارم که سوس آن برای دوستان قابل درک باشد.

طرز کار این گونه است که ابتدا فایل node ها را include می کنیم و array موجود در آن را میخوانیم. بعد یکی یکی node ها را به دست می آوریم و آبجکت آن را ایجاد می کنیم. سپس کافی است به node_save آن را ذخیره کنیم. فقط مشکلی که وجود دارد، این است که node های از نوع های مختلف، با هم تفاوت دارند و من مجبور شدم که به ازای هر نوع محتوا، یک تابع جداگانه بنویسم. به دلیل این که زیاد حوصله نداشتم و می خواستم زود تر کار تمام شود، کد ها را عجله ای نوشتم و فکر می کنم که کیفیت زیادی نداشته باشد. (خودم نمره ی 14 از 20 به آن می دهم)

در ضمن یاد آوری می کنم که این سورس فقط برای سایت من کار می کند. یعنی تصور نکنید که این سورس را همه جا می توانید مستقیما استفاده کنید. زیرا سورس را اختصاصا برای همین سایت درست کردم و برای این که بخواهید از آن برای سایت خودتان استفاده کنید قطعا مجبور خواهید بود که در آن تغییرات بسیاری ایجاد کنید! این سورس فقط برای تمرین گذاشته شده و کاربرد عملی ندارد!

پس از این که node ها وارد شد (که حدود 218 تا بود) اکنون باید comment ها را نیز وارد می کردم . تعداد زیادی comment داشتم که باید وارد می شد. این بار حوصله نداشتم که مجددا یک ماژول بنویسم که comment ها را از سایت قبلی export کند.

دیدم راه ساده ای وجود دارد و آن این است که در ماژول myimport که برای دروپال 7 است، مستقیما در دیتابیس دروپال 6 لاگین کنم و اطلاعات را سطر به سطر از جدول comments بخوانم و سپس مجددا دیتابیس را switch کنم و به دیتابیس Drupal 7 بازگردم. آن گاه اطلاعات را در دروپال 7 وارد کنم. خوشبختانه دروپال 7 برای switch کردن بین database های متعدد توانایی خوبی دارد و API ساده ای برای این منظور پیش بینی کرده است.

نکات جالبی که کشف کردم، یکی این بود که وضعیت (status) کامنت ها در دروپال 7 به عکس شده. یعنی در دروپال 7 نسبت به دروپال 6 ، ستون comment معکوس شده و 1 و 0 جایگزین شده اند. به همین خاطر در ابتدا تمام دیدگاه های منتشر شده در سایت در صف تایید قرار گرفتند و تمام دیدگاه های منتظر شده به وضعیت منتشر نشده در آمدند. که با یک علامت تعجب (!) ساده در سورس کد، مشکل برطرف شد!!

کشف جالب دیگری که داشتم، مفهوم Vancode است که بعدا بیشتر توضیح می دهم. این جا را ببینید: http://api.drupal.org/api/drupal/modules!comment!comment.module/function/int2vancode/7

این هم سورس ماژول myimport:

  1<?php
  2/**
  3 * @file Import data from d6 to d7
  4 * @author Ahmad Hejazee <info@hejazee.com>
  5 * @url http://www.hejazee.com/ @endurl
  6 */
  7
  8/**
  9 * hook_menu()
 10 */
 11 function myimport_menu() {
 12    $items['myimport'] = array(
 13    'title' => 'My import',
 14    'description' => 'Import data to drupal 7',
 15    'page callback' => 'drupal_get_form',
 16    'page arguments' => array('myimport_imort_form'),
 17    'access callback' => TRUE,
 18    'type' => MENU_NORMAL_ITEM,
 19    );
 20    return $items;
 21 }
 22
 23/**
 24 * Form builder
 25 */
 26 function myimport_imort_form() {
 27    $form = array();
 28    return confirm_form($form, t('Are you sure?'), 'myimport', t('Import?'), t('Import'), t('Cancel'));
 29 }
 30
 31/**
 32 * Submit handler
 33 */
 34  function myimport_imort_form_submit($form, &$form_state) {
 35    global $my_arr;
 36    require_once (dirname(__FILE__) . '/nodes.php');
 37
 38
 39  foreach ($my_arr as $key => $node) {
 40    
 41    switch ($node['type']) {
 42      case 'tutorial':
 43        $new_node = myimport_imort_tutorial($node);
 44        break;
 45      case 'simplenews':
 46        $new_node = myimport_imort_simplenews($node);
 47        break;
 48      case 'book':
 49        $new_node = myimport_imort_book($node);
 50        break;
 51      case 'page':
 52        $new_node = myimport_imort_page($node);
 53        break;
 54      case 'activity':
 55        $new_node = myimport_imort_activity($node);
 56        break;
 57      case 'forum':
 58        $new_node = myimport_imort_forum($node);
 59        break;
 60      case 'story':
 61        $new_node = myimport_imort_story($node);
 62        break;
 63      case 'status':
 64        $new_node = myimport_imort_status($node);
 65        break;
 66      default:
 67        break;
 68    }
 69    
 70    if (isset($new_node->nid)) {
 71      myimport_import_node_comments($node['nid'], $new_node->nid);
 72    }
 73  }
 74  //drupal_set_message('--------' . print_r($my_arr, TRUE));
 75}
 76
 77function myimport_imort_tutorial($node) {
 78  //drupal_set_message(print_r($node, TRUE));
 79  $n = new stdClass();
 80  $n->uid = $node['uid'];
 81  $n->title = $node['title'];
 82  //$n->log = $node['log'];
 83  $n->status = $node['status'];
 84  $n->comment = $node['comment'];
 85  $n->promote = $node['promote'];
 86  $n->sticky = $node['sticky'];
 87  $n->type = $node['type'];
 88  $n->language = $node['language'];
 89  $n->created = $node['created'];
 90  $n->changed = $node['changed'];
 91  $n->tnid = $node['tnid'];
 92  $n->translate = $node['translate'];
 93  $n->revision_timestamp = $node['revision_timestamp'];
 94  $n->revision_uid = $node['revision_uid'];
 95  $n->body = array(
 96    'und' => array(
 97      0 => array(
 98        'value' => $node['body'],
 99        'summary' => $node['teaser'],
100        'format' => myimport_convert_format($node['format']),
101        //'safe_value' => '',
102        //'safe_summary' => '',
103      ),
104    ),
105  );
106
107  if (isset($node['field_tutorial_images']) && !empty($node['field_tutorial_images'])) {
108    $field_images = array();
109    $field_images['und'] = myimport_file_multiple($node['field_tutorial_images']);
110    foreach ($node['field_tutorial_images'] as $c => $file_array) {
111      $description = $alt = $title = '';
112      if (isset($file_array['data']['description'])) {
113        $description = $file_array['data']['description'];
114      }
115      if (isset($file_array['data']['alt'])) {
116        $alt = $file_array['data']['alt'];
117      }
118      if (isset($file_array['data']['title'])) {
119        $title = $file_array['data']['title'];
120      }
121      
122      $field_images['und'][$c]['description'] = $description;
123      $field_images['und'][$c]['alt'] = $alt;
124      $field_images['und'][$c]['title'] = $title;
125      $field_images['und'][$c]['display'] = 1;
126      //remove empty files
127      if ($field_images['und'][$c]['uri'] === 'public://') {
128        unset($field_images['und'][$c]);
129      }
130    }
131    $n->field_images = $field_images;
132  }
133
134  if (isset($node['field_tutorial_files']) && !empty($node['field_tutorial_files'])) {
135    $field_files = array();
136    $field_files['und'] = myimport_file_multiple($node['field_tutorial_files']);
137    foreach ($node['field_tutorial_files'] as $c => $file_array) {
138      $description = $alt = $title = '';
139      if (isset($file_array['data']['description'])) {
140        $description = $file_array['data']['description'];
141      }
142      if (isset($file_array['data']['alt'])) {
143        $alt = $file_array['data']['alt'];
144      }
145      if (isset($file_array['data']['title'])) {
146        $title = $file_array['data']['title'];
147      }
148      
149      $field_files['und'][$c]['description'] = $description;
150      $field_files['und'][$c]['alt'] = $alt;
151      $field_files['und'][$c]['title'] = $title;
152      $field_files['und'][$c]['display'] = 1;
153      //remove empty files
154      if ($field_files['und'][$c]['uri'] === 'public://') {
155        unset($field_files['und'][$c]);
156      }
157    }
158    $n->field_files = $field_files;
159  }
160
161  $n->field_categories = array(
162    'und' => myimport_make_taxonomy($node['taxonomy']),
163  );
164
165  $n->metatags = array(
166    'description' => $node['nodewords']['metatags']['description'],
167    'keywords' => $node['nodewords']['metatags']['keywords'],
168  );
169
170  $n->last_comment_timestamp = $node['last_comment_timestamp'];
171  $n->last_comment_name = $node['last_comment_name'];
172  $n->comment_count = $node['comment_count'];
173  $n->name = $node['name'];
174  $n->picture = $node['picture'];
175  $n->data = $node['data'];
176
177  node_save($n);
178  return $n;
179}
180
181function myimport_imort_simplenews($node) {
182  //We don't need to import simplenews content at all
183}
184
185function myimport_imort_book($node) {
186  return myimport_imort_tutorial($node);
187}
188
189function myimport_imort_page($node) {
190  //drupal_set_message(print_r($node, TRUE));
191  $n = new stdClass();
192  $n->uid = $node['uid'];
193  $n->title = $node['title'];
194  //$n->log = $node['log'];
195  $n->status = $node['status'];
196  $n->comment = $node['comment'];
197  $n->promote = $node['promote'];
198  $n->sticky = $node['sticky'];
199  $n->type = $node['type'];
200  $n->language = $node['language'];
201  $n->created = $node['created'];
202  $n->changed = $node['changed'];
203  $n->tnid = $node['tnid'];
204  $n->translate = $node['translate'];
205  $n->revision_timestamp = $node['revision_timestamp'];
206  $n->revision_uid = $node['revision_uid'];
207  $n->body = array(
208    'und' => array(
209      0 => array(
210        'value' => $node['body'],
211        'summary' => $node['teaser'],
212        'format' => myimport_convert_format($node['format']),
213        //'safe_value' => '',
214        //'safe_summary' => '',
215      ),
216    ),
217  );
218
219  if (isset($node['nodewords']['metatags']['keywords']) && !empty($node['nodewords']['metatags']['keywords'])) {
220    $n->metatags = array(
221      'description' => $node['nodewords']['metatags']['description'],
222      'keywords' => $node['nodewords']['metatags']['keywords'],
223    );
224  }
225
226  $n->last_comment_timestamp = $node['last_comment_timestamp'];
227  $n->last_comment_name = $node['last_comment_name'];
228  $n->comment_count = $node['comment_count'];
229  $n->name = $node['name'];
230  $n->picture = $node['picture'];
231  $n->data = $node['data'];
232
233  node_save($n);
234  return $n;
235}
236
237function myimport_imort_activity($node) {
238  //drupal_set_message(print_r($node, TRUE));
239  $n = new stdClass();
240  $n->uid = $node['uid'];
241  $n->title = $node['title'];
242  //$n->log = $node['log'];
243  $n->status = $node['status'];
244  $n->comment = $node['comment'];
245  $n->promote = $node['promote'];
246  $n->sticky = $node['sticky'];
247  $n->type = $node['type'];
248  $n->language = $node['language'];
249  $n->created = $node['created'];
250  $n->changed = $node['changed'];
251  $n->tnid = $node['tnid'];
252  $n->translate = $node['translate'];
253  $n->revision_timestamp = $node['revision_timestamp'];
254  $n->revision_uid = $node['revision_uid'];
255  $n->body = array(
256    'und' => array(
257      0 => array(
258        'value' => $node['body'],
259        'summary' => $node['teaser'],
260        'format' => myimport_convert_format($node['format']),
261        //'safe_value' => '',
262        //'safe_summary' => '',
263      ),
264    ),
265  );
266
267  if (isset($node['field_images']) && !empty($node['field_images'])) {
268    $field_images = array();
269    $field_images['und'] = myimport_file_multiple($node['field_images']);
270    foreach ($node['field_images'] as $c => $file_array) {
271      $description = $alt = $title = '';
272      if (isset($file_array['data']['description'])) {
273        $description = $file_array['data']['description'];
274      }
275      if (isset($file_array['data']['alt'])) {
276        $alt = $file_array['data']['alt'];
277      }
278      if (isset($file_array['data']['title'])) {
279        $title = $file_array['data']['title'];
280      }
281      
282      $field_images['und'][$c]['description'] = $description;
283      $field_images['und'][$c]['alt'] = $alt;
284      $field_images['und'][$c]['title'] = $title;
285      $field_images['und'][$c]['display'] = 1;
286      //remove empty files
287      if ($field_images['und'][$c]['uri'] === 'public://') {
288        unset($field_images['und'][$c]);
289      }
290    }
291    $n->field_images = $field_images;
292  }
293
294  $n->field_categories = array(
295    'und' => myimport_make_taxonomy($node['taxonomy']),
296  );
297
298  $n->metatags = array(
299    'description' => $node['nodewords']['metatags']['description'],
300    'keywords' => $node['nodewords']['metatags']['keywords'],
301  );
302
303  $n->last_comment_timestamp = $node['last_comment_timestamp'];
304  $n->last_comment_name = $node['last_comment_name'];
305  $n->comment_count = $node['comment_count'];
306  $n->name = $node['name'];
307  $n->picture = $node['picture'];
308  $n->data = $node['data'];
309
310  node_save($n);
311  return $n;
312}
313
314function myimport_imort_forum($node) {
315  //drupal_set_message(print_r($node, TRUE));
316  $n = new stdClass();
317  $n->uid = $node['uid'];
318  $n->title = $node['title'];
319  //$n->log = $node['log'];
320  $n->status = $node['status'];
321  $n->comment = $node['comment'];
322  $n->promote = $node['promote'];
323  $n->sticky = $node['sticky'];
324  $n->type = $node['type'];
325  $n->language = $node['language'];
326  $n->created = $node['created'];
327  $n->changed = $node['changed'];
328  $n->tnid = $node['tnid'];
329  $n->translate = $node['translate'];
330  $n->revision_timestamp = $node['revision_timestamp'];
331  $n->revision_uid = $node['revision_uid'];
332  $n->body = array(
333    'und' => array(
334      0 => array(
335        'value' => $node['body'],
336        'summary' => $node['teaser'],
337        'format' => myimport_convert_format($node['format']),
338        //'safe_value' => '',
339        //'safe_summary' => '',
340      ),
341    ),
342  );
343
344  $n->taxonomy_forums = array(
345    'und' => myimport_make_taxonomy($node['taxonomy']),
346  );
347
348  // $n->metatags = array(
349    // 'description' => $node['nodewords']['metatags']['description'],
350    // 'keywords' => $node['nodewords']['metatags']['keywords'],
351  // );
352
353  $n->last_comment_timestamp = $node['last_comment_timestamp'];
354  $n->last_comment_name = $node['last_comment_name'];
355  $n->comment_count = $node['comment_count'];
356  $n->name = $node['name'];
357  $n->picture = $node['picture'];
358  $n->data = $node['data'];
359
360  node_save($n);
361  return $n;
362}
363
364function myimport_imort_story($node) {
365  //drupal_set_message(print_r($node, TRUE));
366  $n = new stdClass();
367  $n->uid = $node['uid'];
368  $n->title = $node['title'];
369  //$n->log = $node['log'];
370  $n->status = $node['status'];
371  $n->comment = $node['comment'];
372  $n->promote = $node['promote'];
373  $n->sticky = $node['sticky'];
374  $n->type = $node['type'];
375  $n->language = $node['language'];
376  $n->created = $node['created'];
377  $n->changed = $node['changed'];
378  $n->tnid = $node['tnid'];
379  $n->translate = $node['translate'];
380  $n->revision_timestamp = $node['revision_timestamp'];
381  $n->revision_uid = $node['revision_uid'];
382  $n->body = array(
383    'und' => array(
384      0 => array(
385        'value' => $node['body'],
386        'summary' => $node['teaser'],
387        'format' => myimport_convert_format($node['format']),
388        //'safe_value' => '',
389        //'safe_summary' => '',
390      ),
391    ),
392  );
393
394  if (isset($node['field_blog_images']) && !empty($node['field_blog_images'])) {
395    $field_images = array();
396    $field_images['und'] = myimport_file_multiple($node['field_blog_images']);
397    foreach ($node['field_blog_images'] as $c => $file_array) {
398      $description = $alt = $title = '';
399      if (isset($file_array['data']['description'])) {
400        $description = $file_array['data']['description'];
401      }
402      if (isset($file_array['data']['alt'])) {
403        $alt = $file_array['data']['alt'];
404      }
405      if (isset($file_array['data']['title'])) {
406        $title = $file_array['data']['title'];
407      }
408      
409      $field_images['und'][$c]['description'] = $description;
410      $field_images['und'][$c]['alt'] = $alt;
411      $field_images['und'][$c]['title'] = $title;
412      $field_images['und'][$c]['display'] = 1;
413      //remove empty files
414      if ($field_images['und'][$c]['uri'] === 'public://') {
415        unset($field_images['und'][$c]);
416      }
417    }
418    $n->field_images = $field_images;
419  }
420
421  if (isset($node['field_tutorial_files']) && !empty($node['field_tutorial_files'])) {
422    $field_files = array();
423    $field_files['und'] = myimport_file_multiple($node['field_tutorial_files']);
424    foreach ($node['field_tutorial_files'] as $c => $file_array) {
425      $description = $alt = $title;
426      if (isset($file_array['data']['description'])) {
427        $description = $file_array['data']['description'];
428      }
429      if (isset($file_array['data']['alt'])) {
430        $alt = $file_array['data']['alt'];
431      }
432      if (isset($file_array['data']['title'])) {
433        $title = $file_array['data']['title'];
434      }
435      
436      $field_files['und'][$c]['description'] = $description;
437      $field_files['und'][$c]['alt'] = $alt;
438      $field_files['und'][$c]['title'] = $title;
439      $field_files['und'][$c]['display'] = 1;
440      //remove empty files
441      if ($field_files['und'][$c]['uri'] === 'public://') {
442        unset($field_files['und'][$c]);
443      }
444    }
445    $n->field_files = $field_files;
446  }
447
448  $n->field_categories = array(
449    'und' => myimport_make_taxonomy($node['taxonomy']),
450  );
451
452  $n->metatags = array(
453    'description' => $node['nodewords']['metatags']['description'],
454    'keywords' => $node['nodewords']['metatags']['keywords'],
455  );
456
457  $n->last_comment_timestamp = $node['last_comment_timestamp'];
458  $n->last_comment_name = $node['last_comment_name'];
459  $n->comment_count = $node['comment_count'];
460  $n->name = $node['name'];
461  $n->picture = $node['picture'];
462  $n->data = $node['data'];
463
464  node_save($n);
465  return $n;
466}
467
468function myimport_imort_status($node) {
469  //drupal_set_message(print_r($node, TRUE));
470  $n = new stdClass();
471  $n->uid = $node['uid'];
472  $n->title = $node['title'];
473  //$n->log = $node['log'];
474  $n->status = $node['status'];
475  $n->comment = $node['comment'];
476  $n->promote = $node['promote'];
477  $n->sticky = $node['sticky'];
478  $n->type = $node['type'];
479  $n->language = $node['language'];
480  $n->created = $node['created'];
481  $n->changed = $node['changed'];
482  $n->tnid = $node['tnid'];
483  $n->translate = $node['translate'];
484  $n->revision_timestamp = $node['revision_timestamp'];
485  $n->revision_uid = $node['revision_uid'];
486  // $n->body = array(
487    // 'und' => array(
488      // 0 => array(
489        // 'value' => $node['body'],
490        // 'summary' => $node['teaser'],
491        // 'format' => myimport_convert_format($node['format']),
492        //'safe_value' => '',
493        //'safe_summary' => '',
494      // ),
495    // ),
496  // );
497
498  $n->metatags = array(
499    'description' => $node['nodewords']['metatags']['description'],
500    'keywords' => $node['nodewords']['metatags']['keywords'],
501  );
502
503  $n->last_comment_timestamp = $node['last_comment_timestamp'];
504  $n->last_comment_name = $node['last_comment_name'];
505  $n->comment_count = $node['comment_count'];
506  $n->name = $node['name'];
507  $n->picture = $node['picture'];
508  $n->data = $node['data'];
509
510  node_save($n);
511  return $n;
512}
513
514/**
515 * Create taxonomy_term object from a d6 taxonomy array
516 */
517 function myimport_make_taxonomy($taxonomy_array) {
518    $result = array();
519    //load data
520    foreach ($taxonomy_array as $a => $container) {
521    if (is_numeric($a)) {
522      //This is a forum or simplenews tag
523      $vid = $a;
524      foreach ($container as $tid => $tids_array) {
525        $matched_term = taxonomy_term_load($tid);
526        if (empty($matched_term)) {
527          //This tag is not created yet. Create it
528          $term = new stdClass();
529          $term->vid = 2; //Save new term in 'Categories' vocabulary
530          $term->name = $tid;
531          taxonomy_term_save($term);
532          $result[] = array(
533            'tid' => $term->tid,
534            'taxonomy_term' => $term,
535          );
536        }
537        else {
538          $result[] = array(
539            'tid' => $matched_term->tid,
540            'taxonomy_term' => $matched_term,
541          );
542        }
543      }
544    }
545    else {
546      //This is a general tag
547      foreach ($container as $vid => $tags_str) {
548        $vid = (int)$vid;
549        switch ($vid) {
550          case 1:
551          case 2:
552          case 3:
553            //general categories
554            $tags_arr = explode(', ', $tags_str);
555            foreach ($tags_arr as $i => $tag) {
556              $matched_terms = taxonomy_get_term_by_name($tag);
557              if (empty($matched_terms)) {
558                //This tag is not created yet. Create it
559                $term = new stdClass();
560                $term->vid = 4; //Save new term in 'Categories' vocabulary
561                $term->name = $tag;
562                taxonomy_term_save($term);
563                $result[] = array(
564                  'tid' => $term->tid,
565                  'taxonomy_term' => $term,
566                );
567              }
568              else {
569                foreach ($matched_terms as $j => $term) {
570                  $result[] = array(
571                    'tid' => $term->tid,
572                    'taxonomy_term' => $term,
573                  );
574                }
575              }
576            }
577            
578            break;
579          //case 46:
580            //forums
581            
582            //break;
583          //case 47:
584            //newsletter
585            //I decided not to import simplenews contents
586            //break;
587        }
588      }
589    }
590    }
591    return $result;
592 }
593
594/**
595 * convert d6 format number to d7 format name
596 */
597 function myimport_convert_format($format_id) {
598    $format_id = (int)$format_id;
599    switch ($format_id) {
600    case 1:
601      return 'filtered_html';
602      break;
603    case 2:
604      return 'full_html';
605      break;
606    case 3:
607      return 'plain_text';
608      break;
609    case 4:
610      return 'raw_html';
611      break;
612    case 5:
613      return 'html_mail';
614      break;
615    default:
616      break;
617    }
618 }
619
620/**
621 * Convert a d6 file array to d7 stdClass file object and save file
622 */
623  function myimport_file($file_array) {
624    static $store = array();
625
626  $file_path = $file_array['filepath'];
627  $file_path = str_replace('sites/www.hejazee.com/files/', '', $file_path);
628  $file_path = file_build_uri($file_path);
629
630  if (isset($store[$file_path])) {
631    $sql = "SELECT fid FROM {file_managed} WHERE uri = '$file_path'";
632    $sql_result = db_query($sql);
633    $row = $sql_result->fetchObject();
634    if (empty($row)) {
635      drupal_set_message("File error: " . $file_path);
636      return NULL;
637    }
638    $fid = $row->fid;
639    return file_load($fid);
640  }
641  else {
642    $store[$file_path] = $file_path;
643  }
644
645  $file = new stdClass();
646  $file->uid = $file_array['uid'];
647  $file->filename = $file_array['filename'];
648  $file->uri = $file_path;
649  $file->filemime = $file_array['filemime'];
650  $file->filesize = $file_array['filesize'];
651  $file->status = $file_array['status'];
652  $file->timestamp = $file_array['timestamp'];
653
654  return file_save($file);
655}
656
657/**
658 * Import multiple files
659 */
660 function myimport_file_multiple($files_array) {
661    $result = array();
662    foreach ($files_array as $c => $file_array) {
663    $result[$c] = (array)myimport_file($file_array);
664    }
665    return $result;
666 }
667
668/**
669 * Import all comments associated with a node in d6 to Drupal7
670 */
671  function myimport_import_node_comments($d6_nid, $d7_nid) {
672    //Connect to d6 database to fetch commetns
673    $d6_database = array(
674      'database' => 'dbname',
675      'username' => 'username',
676      'password' => 'password',
677      'host' => 'localhost',
678      'driver' => 'mysql',
679    );
680    Database::addConnectionInfo('MyImportD6DB', 'default', $d6_database);
681    db_set_active('MyImportD6DB');
682
683  $sql = "SELECT * FROM {comments} WHERE nid=$d6_nid ORDER BY cid ASC";
684  $sql_result = db_query($sql);
685  $rows = $sql_result->fetchAll();
686
687  //Map d6 cid to d7 cid s
688  // as [$d6_cid] => [$d7_cid]
689  static $comment_mapping = array();
690
691  foreach ($rows as $c => $comment) {
692    $cid        = $comment->cid;
693    $pid        = $comment->pid;
694    $comment_nid= $comment->nid;
695    $uid        = $comment->uid;
696    $subject    = $comment->subject;
697    $comment_body= $comment->comment;
698    $hostname   = $comment->hostname;
699    $timestamp  = $comment->timestamp;
700    $status     = $comment->status;
701    $format     = $comment->format;
702    $thread     = $comment->thread;
703    $name       = $comment->name;
704    $mail       = $comment->mail;
705    $homepage   = $comment->homepage;
706    
707    $d7comment = new stdClass();
708    $d7comment->cid = NULL; //to avoid errors caused by drupal 7.14 bugs.
709    $d7comment->pid = (isset($comment_mapping[$pid]) ? $comment_mapping[$pid] : 0);
710    $d7comment->nid = $d7_nid;
711    $d7comment->uid = $uid;
712    $d7comment->subject = $subject;
713    $d7comment->comment_body = array(
714      'und' => array(
715        0 => array(
716          'value' => $comment_body,
717          'format' => myimport_convert_format($format),
718        ),
719      ),
720    );
721    $d7comment->hostname = $hostname;
722    $d7comment->created = $timestamp;
723    $d7comment->status = ($status == 0 ? 1 : 0);
724    //$d7comment->format
725    $d7comment->thread = $thread;
726    $d7comment->name = $name;
727    $d7comment->mail = $mail;
728    $d7comment->homepage = $homepage;
729    $d7comment->notify = 0; //comment_notify module
730    
731    //return to default db for comment_save()
732    db_set_active();
733    comment_save($d7comment);
734    db_set_active('MyImportD6DB');
735    
736    $comment_mapping[$comment->cid] = $d7comment->cid;
737  }
738
739  //return to default db
740  db_set_active();
741}

نظرات شما

قسمت نظرات با استفاده از سرویس دیسکاس پیاده سازی شده است. متاسفانه این سرویس از داخل ایران قابل دسترس نیست. لطفا از آی پی خارجی استفاده کنید.