Upgrade to Drupal 7!

Spend 6 hours:
package live site, clone to local development environment
disable local contributed modules
turn on maintenance mode
upgrade local core to Drupal 7.x version
Convert custom theme to D7
upgrade contributed modules
configure contributed modules
use 7.x version of cck, use content migrate module to migrate fields to 7.x core
package local
backup live site
transfer local to live
DONE!

There should not be any difference from visitor point of view
I am also confused after live is being transferred:
"huh? finished? they just looked exactly the same"
until I opened the admin pages and saw Drupal7's seven theme

The next steps will be turning on the multi-lingual options
converting this blog from mainly chinese to bi-lingual
2013 GoGoGo!

Ubercart 客製化

最近在做一個 ubercart 的 customization
主要是管理頁面有新的選項和結賬的時候橧加一組必填資料
是 Drupal 6 的客製化,而在 Drupal 7 和 commerce 的出現之後
其實這些都不太重要了
但不記錄下來的話便會更加浪費
所以還是簡單的記錄一下

管理頁面新的選項
例如在 /admin/store/orders/1005243/edit 增加一組 form 元素
hook_order_pane 定義 pane
傳入 callback,最後當然是返回 form API 定義:

<?php
/**
 * Implementation of hook_order_pane().
 */
function hook_order_pane() {
 
$panes[] = array(
   
'id' => 'example',
   
'callback' => 'example_pane',
   
'title' => t('Example'),
   
'desc' => t('Select'),
   
'class' => 'pos-left',
   
'weight' => -1,
   
'show' => array('view', 'edit'),
  );
  return
$panes;
}

/**
 * Handle delivery date and time on order pane
 */
function example_pane($op, $arg1) {

  switch (
$op) {
    case
'view':
      return
'Example';
    case
'edit-form':
     
$form['driver']['driver_id'] = array(
       
'#type' => 'select',
       
'#title' => t('Select'),
       
'#default_value' => 0,
       
'#options' => $options,
      );
      return
$form;
?>

以上代碼輸出一個新的 select 到修改 order 表單
但記錄到 database 的部份還需要以下代碼:

<?php
/**
 * Implementation of hook_order().
 */
function hook_order($op, &$arg1, $arg2) {
  switch (
$op) {
    case
'save':
     
db_query($sql);
      break;
  }
    case
'load':
     
$result = db_query($sql);
      if (
$data = db_fetch_object($result)) {
       
$arg1->example['key'] = $data->example;
      }
      break;
}
?>

以上三個 hook 便可以簡單新增一個管理者專用的 dropdown
可以記錄例如送了貨沒有,簡單的客戶回應等等
下一篇續說明一下結賬時新增表單的 hooks

p.s. 話說真的應該花點時間將這個 blog upgrade 到 Drupal 7 了

SQL in keyword, db_placeholders()

處理基層的 sql 時候遇到問題
但 Drupal 的 database abstraction layer 的文檔實在是太簡單 http://api.drupal.org/api/drupal/includes!database.inc/group/database/6

特別是複雜的 case,例如 IN:
例如找出已發佈的,類型為 Page 或 Story 的 node:

<?php
$sql
= "SELECT * FROM {node} WHERE status = '%d' AND type IN (".db_placeholders($types, 'varchar').") ";

$r = db_query($sql, array_merge((array)$status, $types));
?>

db_placeholders 預設是傳為 int
要傳入 varchar 則要提供等二個參數
而最後使用 db_query 的時候要使用 array_merge
因為 $types 本身是一個 array
而 db_query 則不可以傳入 array of array
所以使用 array_merge 傳入一個一維的陣列

Drupal 8 預定!

Drupal 8 會在 2013年2月停止併入新的功能
正式進入 alpha階段,然後7月進入 beta
現在我們差不多可以看一看,預現一下 Drupal 8 功能上的特點了
Drupal 8當然不會只是一個版本上的數字改變
而無論作為一個內容管理系統的角度
或者開發框架的角度
Drupal 8 都會是一個大躍進

我們或者不能比較究竟是內容編輯還是程式開發者會更感受到新系統的不同
但可以肯定的是,最能感受到的就是廣大的一般使用者了
例如更簡單的修改內容介面,更好的支持手持裝置

建立內容和修改會變得非常容易
不再需要訓練或者工作坊,直觀的介面令使用者可以簡單的修改內容
這都要多得 http://drupal.org/project/spark 這一個發行版本在這方面的努力
這個發行版本的最終目的是令使用者可以在頁面上隨便點擊想要修改的地方立即修改
而不需要進入另一個「管理介面」
可以稱得上為「最自然的」修改方法
spark 計劃的頁面有一段很好的介紹影片
就算只是簡單的一兩個欄位你都可以感受到它的威力

手持裝置
Drupal 8 可以說是為手持裝置從 core 的角度重新思考一次
無論是一般電腦還是螢幕3吋的手持裝置都能得到很好的支持
響應式的設計令不同大小的螢幕都可以清楚瀏覽網站上的文字圖片
再加上管理介面也支持手持裝置
例如你看到一個新的留言想發佈
但你手上只有你的手提電話
Drupal 8 令你的發佈過程在手持裝置上一樣很順暢
不需要放大縮少頁面便可以提交發佈內容

HTML5 和效能
隨著名HTML5 的普及
Drupal 8 會完全支持HTML5,並帶給Drupal 8 更豐富的功能
core 上的 form API, validation 等等都支持HTML5
而其中又有一部分的工作放了在前台的渲染效能上
令頁面的反應更快,動畫更流暢

Web services
Drupal 8 會提供一個標準的方案使其他第三方可以和內核溝通
情況和 facebook apps 類似
提供高可用性,高效能,非頁面的回應
再加上 restful api 的工作,令Drupal 能更好的和其他系統互動

其他
還有設定管理方面
現在的方式是使用 features 模組
但遠遠不夠全面
Drupal 8 會從內核的角度根本性的解決這個問題

當然還有 views 合併到內核
這個工作才剛開始,但已經有 API 可以使用
但還需要將現有的管理頁面全部改到使用 views API
自此兩大模組 cck 和 views 都合併到 core
令 Drupal 「work out of the box」

這些都只是 Drupal 8新功能的冰山一角
社群裡的開發者仍然日已繼夜的完善和新增 Drupal 8
當然,你也可以成為其中一個份子!

有關 hook_menu 的 title arguments

hook_menu 中有一個選項是 title arguments
page arguments 大家可能用得比較多
而使用 title arguments 的機會比較少
而 API reference 也沒有有關的例子可以參考
我便約略介紹一下

首先,有關 title 的參數有三個:
title,字符,是未經翻譯的標題,會用於 <title> 內,一般的 theme 也會在 content 用 h1 輸出
title callback,可選參數,預設是 t(),這讓上面的 title 會預設經過翻譯然後輸出,所以上面的 title 不需要使用 t() 包起來
title argument,可選參數,必需是陣列,例如array(1)

假設 hook_menu 定義:

<?php
items
['admin/settings/joe/abc'] = array(
 
'title' => 'Testing page',
);
?>

最後 title 的處理: <?php t('Testing page') ?>

或者:

<?php
items
['admin/settings/joe/abc'] = array(
 
'title' => 'Testing page',
 
'title callback' => 'strtoupper'
);
?>

最後 title 的處理: <?php strtoupper('Testing page') ?>

以上的例子會令 title 避開 t()
所以應該自定義一個 callback:

<?php
items
['admin/settings/joe/abc'] = array(
 
'title' => 'Testing page',
 
'title callback' => 'strtoupper_t'
);

function
strtoupper_t($str) {
  return
t(strtoupper($str));
}
?>

最後 title 的處理: <?php strtoupper_t('Testing page') ?>

最後一個 title arguments 的例子:

<?php
items['admin/settings/joe/%'] = array(
  'title' => 'Testing @string page',
  'title arguments' => array('@string' => 3)
);

最後 title 的處理: <?php t('Testing @string page', array('@string' => arg(3))) ?>
以上的例子中的 title arguments 的 key 是 @string, 因為 title 有一個 t() 接受的 placeholder
所以 title arguments 便可以作為一個變數傳到 t(),替換變數了

Pages

Google