drupal: ติดตั้งมอดูล และการแก้ปัญหา

บันทึกการติดตั้งมอดูล และการแก้ปัญหา

Topic: 

drupal5: สร้างเอกสารภายในและภายนอก

ถ้าเราต้องการให้ผู้อ่านมีสิทธิ์ที่ไม่เท่ากัน โดยให้กำหนดด้วย role ในการเข้าถึงเอกสารใน node ต่าง ๆ สามารถทำได้โดยใช้มอดูล Taxonomy Access Control Lite ดังนี้

  1. ติดตั้งมอดูล Taxonomy Access Control Lite
    $ cd /var/www/drupal/sites/all/modules
    $ wget http://ftp.drupal.org/files/projects/tac_lite-5.x-1.1.tar.gz
    $ tar xfz tac_lite-5.x-1.1.tar.gz
  2. เปิดใช้งานผ่าน URL:admin/build/modules
  3. สร้าง Vocaburary ใหม่ ด้วย Taxonomy ผ่าน URL:admin/content/taxonomy
    โดยเลือกแท็บ Add vocaburaly ตั้งชื่อว่า Privacy
    สร้าง terms ชื่อว่า Public และ Private ตามลำดับ โดยอย่าให้เป็นฟรีแท็กส์
  4. เปิดให้ admin สามารถใช้งานมอดูลได้ ผ่าน URL:admin/user/access
  5. เมื่อสร้างเสร็จจะเกิดเมนูย่อยชื่อ Access control by taxonomy ให้เลือก Vocaburary ว่า Privacy
  6. เลือกแท็บ Role based privileges และเล็อกกำหนดสิทธิ์ให้แต่ละ role ได้ตามต้องการ เช่น anonymous เป็น Public และ authenticated เป็นทั้ง Public และ Private เป็นต้น

เสร็จแล้ว หลังจากนี้ ในขั้นตอนของการสร้างเอกสาร จะมีที่เลือก Privacy ในหัวข้อ Categories ให้เราเลือกว่าจะให้เป็น Public หรือ Private

อ้างอิง - Content Type access permisions

หมายเหตุ

ถ้าใช้ Drupal-5.5 และ Drupal-5.6 และใช้ฐานข้อมูล Postgresql อาจมีข้อผิดพลาดเกิดขึ้น ต้องปรับแก้ Core ที่ไฟล์ includes/database.pgsql.inc ดังนี้
$ vi includes/database.pgsql.inc

...
function db_distinct_field($table, $field, $query) {
    if (!preg_match('/FROM\s+\S+\s+AS/si', $query)
      && !preg_match('/DISTINCT\s+ON\s*\(\s*('. $table .'\s*\.\s*)?'. $field .'\s*\)/si', $query)
      && preg_match('/(.*FROM\s+)(.*?\s)(\s*(WHERE|GROUP|HAVING|ORDER|LIMIT|FOR).*)/Asi', $query, $m)) {
        $query = $m[1];
        $query .= preg_replace('/([\{\w+\}]+)\s+(' . $table . ')\s/Usi', '(SELECT DISTINCT ON (' . $field . ') * FROM \1) \2 ', $m[2]);
        $query .= $m[3];
    }

    return $query;
}
...

อ้างอิง - Nodes are sorted incorrectly with PostgreSQL

Topic: 

drupal6: ทดลองใช้งานมอดูล geshifilter

ขั้นตอนตั้งแต่ติดตั้งคือ
  1. ดาวน์โหลดมอดูล GeSHi Filter
    สำหรับรุ่น 6-rc2 คือ [code language="bash"]$ cd sites/all/modules
    $ wget http://ftp.drupal.org/files/projects/geshifilter-6.x-1.0-rc2.tar.gz
    $ tar cfz geshifilter-6.x-1.0-rc2.tar.gz[/code]
  2. ดาวน์โหลดไลบรารี GeSHi (Generic Syntax Highlighter) มาไว้ในไดเรกทอรี่ geshi
    [code language="bash"]$ cd geshifilter/geshi
    $ wget http://nchc.dl.sourceforge.net/sourceforge/geshi/GeSHi-1.0.7.20.tar.bz2
    $ tar cfj GeSHi-1.0.7.20.tar.bz2[/code]
  3. เปิดใช้มอดูลจาก URL: admin/builds/modules
  4. เปิดการอนุญาตจาก URL: admin/user/permissions
  5. ตั้งค่าการใช้งาน URL: admin/settings/geshifilter
    เพื่อให้กระทบต่อการแสดงผลของธีมให้น้อยที่สุด เลือกเปลี่ยนแปลงสามตัวคือ
    • Generic syntax highlighting tags: เพิ่มแท็ก <pre>
    • Tag style: เลือก [foo] (ลดข้อจำกัดการแสดงผล HTML)
    • Code container: เลือกใช้ Use <div> container (enables automatic line wrapping)
    ส่วนภาษา สามารถเพิ่มลดได้จากแท็บ Languages
  6. ตรงนี้สำคัญนิดนึง คือ Input Format ต้องเข้าไปเปิดให้ใช้งาน GeSHi ด้วย จาก URL: admin/settings/filters จะใช้ตัวไหนบ้าง ก็ต้องเข้าไปเปิดในทุก ๆ ตัว
  7. เวลาสร้างเนื้อหา จะใช้รูปแบบคือ
    [pre language="php"] ...CONTENT...
    ...CODE...
    
    [/pre] ตัวจริงให้เปลี่ยนจาก < เป็น [
  8. เสร็จแล้ว วิธีนี้น่าจะกระทบต่อธีมน้อยที่สุด ทดลองใช้งานดูสักระยะนึง อ้างอิง
Topic: 

drupal6: ปรับปรุงการใช้งานมอดูล geshifilter

โพสต์นี้ อย่าเชื่อมาก เป็นแค่การทดลองเท่านั้น พบว่ามอดูล geshifilter เขาแปลงรหัส entity ให้โดยอัตโนมัติ
ทำให้การโพสต์เนื้อความ ไม่ยืดหยุ่นเท่าที่ควร
เที่ยวนี้เราจะตั้งค่าใหม่ ให้การใช้งานมีความยืดหยุ่นสูงสุด
  • ตั้งค่าการใช้งาน geshifilter ผ่าน URL: admin/settings/geshifilter
    • Generic syntax highlighting tags: เพิ่มแท็ก pre
    • Code container: เลือก Use <div> container
  • แก้มอดูลเล็กน้อย เพื่อยกเลิกการแปลง entities อัตโนมัติ
    $ vi sites/all/modules/geshifilter/geshifilter.pages.inc เพิ่มการ decode สองครั้ง (โดยเพิ่มบรรทัดที่เป็นตัวหนา)
    :129
    ...
      $source_code = decode_entities($source_code);
      $source_code = decode_entities($source_code);
    ...
    
เสร็จแล้ว เสร็จแล้ว แต่ยังงง ๆ กับผลลัพธ์อยู่ รอดูอีกสักพัก เริ่มเข้าใจแล้ว
แท็กที่เราจะทำพิเศษเพิ่มในบล๊อกของโค๊ด ไม่สามารถทำได้ เพราะ GeSHi จะแปลงเป็น entities ทั้งหมด
ต้องหาทางอื่นในการเน้นประโยคแทน เช่นทำบรรทัดคอมเมนต์เป็นต้น
เช่น
...
  $source_code = decode_entities($source_code);
  $source_code = decode_entities($source_code);  //ADD THIS LINE
...
ตัวอย่างข้างต้น ต้องกรอกในฟอร์มว่า
<div class="geshifilter">
<pre language="drupal6">
...
  $source_code = decode_entities($source_code);
  $source_code = decode_entities($source_code);  //ADD THIS LINE
...
</pre>
</div>
มอดูลนี้ใหญ่และซับซ้อนมาก แฮ็กไม่ไหว เอาเท่าที่ได้แล้วกันครับ update
ลองใช้งาน geshifilter แล้วมันทำให้โค๊ดในงานเก่าดูเพี้ยนไปหมด ทางแก้คือสร้าง Input format ใหม่ ผ่าน admin/settings/filters
ตั้งให้สามารถใช้งาน GeSHi ได้ (โดยยกเลิกการใช้งาน GeSHi กับ Input Format อันเก่า เพื่อให้ไม่ต้องตามไปแก้งานเก่า)
ตั้งชื่อว่า GeSHi Filtered HTML
สำหรับงานใหม่ที่จะต้องการใช้ Syntax Highlight ก็ค่อยมาเลือกใช้ Input format แบบนี้
Topic: 

drupal: ทำบล๊อกจากมอดูล tracker

ต้องแฮกเล็กน้อย คือ เอาเนื้อความจาก Add a "Recent posts" block to the tracker module
ไปต่อท้ายไฟล์ modules/tracker/tracker.module

แล้วจะสามารถใช้มอดูล tracker แสดง Recent posts เป็นบล๊อกได้เลย
(แจ๋ว เพราะเขียน Recent Week เอง มีปัญหากับ Drupal-6)

Topic: 

drupal: ลองติดตั้งโมดูล Import HTML

จากคราวก่อนที่ทดลองใส่โค๊ดตัวอย่างลงในเอกสารต้นฉบับเรื่อง python: Adodb Function Reference with example รู้สึกว่าอ่านง่ายดี คล้ายเอกสารของ php ที่เขามีตัวอย่างประกอบตลอด
เลยคิดว่า ถ้าเราสามารถเอาเอกสาร HTML ต้นฉบับ ที่เป็นคู่มือไพธอน เอามาใส่ตัวอย่างเล็ก ๆ น้อย ๆ ด้วยก็น่าจะดี
ลองศึกษา Drupal ดู พบว่ามีโมดูลนึงที่เข้าข่าย คือโมดูล Import HTML

โมดูลนี้ยังไม่สามารถใช้กับ Drupal-5 ได้ และดูท่าว่ายังไม่มีวีแววพัฒนาต่อ
เลยจะทดลองตั้งไซต์ใหม่ เป็น Drupal-4.7 และ import เอกสารเข้ามายังไซต์นี้ และหาทาง Export มายัง Drupal-5 ต่อไป

ทดลองทำดู ยังไม่สำเร็จ แต่ต้องบันทึกเอาไว้ก่อน ไม่งั้นลืมหมด
ผลที่ยังไม่สำเร็จคือ

  • หน้าที่อิมพอร์ตเข้ามา เป็น page ได้อย่างเดียว จริง ๆ เราต้องการเป็นแบบ book มากกว่า เพื่อคราวหลังจะได้ export ไปยังไซต์อื่นด้วย
  • การอิมพอร์ตพวกไฟล์รูปภาพและ css ยังไม่ค่อยสมบูรณ์

เริ่มงาน
ไล่ดูตามเอกสารและค้นกูเกิล ได้ผลดังนี้

ติดตั้ง apache2-dev
# aptitude install apache2-dev libapr1-dev libaprutil1-dev libapache2-modxslt php5-xsl php5-tidy

แก้ php.ini ให้รับ xslt (เพราะ php5 ไม่มี xslt)
# vi /etc/php5/apache2/php.ini

...
extension=domxml.so
extension=xsl.so
...

เริ่ม apache2 ใหม่
# /etc/init.d/apache2 restart

จะข้ามขั้นตอนติดตั้ง Drupal-4.7 ไปถึงตอนติดตั้งโมดูลเลย

เปลี่ยนเป็น webmaster และติดตั้งโมดูล
# su webmaster
$ cd /var/www/drupal/modules
$ wget http://ftp.osuosl.org/pub/drupal/files/projects/import_html-4.7.x-1.x-dev.tar.gz
$ tar xfz import_html-4.7.x-1.x-dev.tar.gz
$ cd import_html

ต้องแก้โค๊ดนิดนึง ตามเอกสาร Drupal - Fatal Error on Line 1225
$ vi import_html.module
:1225

...
//dsm($node);
drupal_set_message($node);
...

เสร็จแล้ว

ตั้งค่าโมดูลด้วย
administer -> modules -> เปิดให้ import_html ทำงาน

ตั้งค่าการใช้งานด้วย
administer -> access control -> เลือก role ที่จะเปิดให้ใช้

ตรวจสอบและตั้งค่าการอิมพอร์ต
administer -> settings -> import_html
ถ้าไม่ฟ้องข้อผิดพลาด ก็แสดงว่าใช้ได้แล้ว

เรียกใช้งานได้ทางเดียว
administer -> Import HTML Site

drupal: แก้ไขงานของโมดูล Import HTML

บันทึกการแก้ไขด้วยมือ
จากครั้งก่อน ผมได้สร้างหน้าเปล่าขึ้นมา แล้วแปลงให้เป็น book เตรียมไว้
แล้วจึงนำเข้าเอกสาร ด้วยโมดูล import HTML ดังนั้น หน้าเปล่าของเราจะเป็น node/1 และเอกสารที่นำเข้า จะเริ่มต้นตั้งแต่ node/2 เป็นต้นไป จนถึงหน้าสุดท้าย สมมุติว่าเป็น node/100 แล้วกัน

เมื่อทำการอิมพอร์ตเข้ามาแล้ว จะพบจุดผิดพลาดมากมาย ขอบันทึกการแก้ไขไว้นิดนึง เผื่อจะขยายขอบเขตไปถึงการแก้ไขโค๊ดต้นฉบับ

ตอนอิมพอร์ต ผมเลือกที่จะไม่เพิ่มรายการในเมนูแบบอัตโนมัติ
เราจึงต้องยกเลิกหัวข้อ Add each page to menu

ตอนนี้ศึกษาเรื่อง adodb อยู่ เลยใช้ไพธอนในการทำงานไปด้วยเลย

เริ่มต้น
$ python

Python 2.4.4 (#2, Oct 20 2006, 00:23:25) 
[GCC 4.1.2 20061015 (prerelease) (Debian 4.1.1-16.1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import adodb
>>> driver = 'mysql'
>>> host = 'localhost'
>>> user = 'user'         # MYSQL USER
>>> password = 'password' # MYSQL PASSWORD
>>> db = 'testdrupal47'   # DRUPAL-4.7 DATABASENAME
>>> conn = adodb.NewADOConnection(driver)
>>> cur = conn.Connect(host,user,password,db)

งานที่ทำคือ

  • เปลี่ยน page เป็น book
  • แก้ไข title ล้น โดยใช้ฟังก์ชั่น string.strip()
  • เรียงลำดับหน้าหนังสือใหม่ ด้วยมือ

ขั้นตอน

เพิ่มหมายเลข node ลงในตาราง book ตั้งแต่ node/2 ถึง node/100
>>> for i in range(2, 101, 1):
...   cur = conn.Execute('INSERT INTO book (vid, nid, parent, weight) VALUE (%s, %s, 0, 0)' % (i, i))
เปลี่ยนฟิลด์ format ในตาราง node_revisions เป็น 1
>>> cur=conn.Execute('UPDATE node_revisions SET format=1 WHERE nid>1')
เปลี่ยนฟิลด์ type ในตาราง node เป็น 'book'
>>> cur=conn.Execute('UPDATE node SET type="book" WHERE nid>1')
เปลี่ยนให้ทุก node ที่เพิ่งอิมพอร์ตเข้ามา เข้าอยู่ภายใต้หน้าว่างคือ node/1
>>> cur=conn.Execute('UPDATE book SET parent=1 WHERE nid>1')
เปลี่ยนฟิลด์ comment ในตาราง node เป็น 2 (ไม่รู้ว่าคืออะไร)
>>> cur=conn.Execute('UPDATE node SET comment=2 WHERE nid>1')
ไม่ต้อง Promoted to front page โดยให้ฟิลด์ promote ในตาราง node เป็นศูนย์
>>> cur=conn.Execute('UPDATE node SET promote=0 WHERE nid>1')
แก้ไข title โดยใช้ฟังก์ชั่น string.strip()
ตาราง node
>>> for i in range(2, 101, 1):
...   cur=conn.Execute('SELECT title FROM node WHERE nid=%s' % (i))
...   title=cur.fields[0].strip()
...   cur=conn.Execute('UPDATE node SET title="%s" WHERE nid=%s' % (title, i))

ตาราง node_revisions

>>> for i in range(2, 101, 1):
...   cur=conn.Execute('SELECT title FROM node_revisions WHERE nid=%s' % (i))
...   title=cur.fields[0].strip()
...   cur=conn.Execute('UPDATE node_revisions SET title="%s" WHERE nid=%s' % (title, i))

เรียงลำดับหน้าหนังสือใหม่ ด้วยมือ
อันนี้นานที่สุด แต่ก็คุ้มกว่าการนำเข้าด้วยมือทั้งหมด

drupal: แก้เรื่องเนื้อความยาว ๆ

มีความจำเป็นที่จะต้องโพสต์เนื้อความยาว ๆ ในเนื้อหาของฟอรั่ม
พบว่า ถ้าข้อความยาวมากเกินไป จะไม่สามารถแสดงผลได้ คือแสดงผลออกมาเหมือนกับไม่มีเนื้อหา
ค้นไปค้นมา พบว่าเป็นกับโมดูล filter
ถ้าเราเลือกใช้ Input format แบบที่ใช้ Line break converter จะทำให้เกิดข้อผิดพลาดดังกล่าว

ทางแก้ชั่วคราวคือ
ให้สร้าง Input format ขึ้นมาใหม่ ไม่ให้ใช้ Line break converter แล้วเลือกใช้ Input format ใหม่นี้
ส่วนตัวเนื้อหาเองนั้น เนื่องจากไม่มีการขึ้นบรรทัดใหม่อัตโนมัติแล้ว เราจึงต้องมาสร้างแท็ก HTML ให้ขึ้นบรรทัดใหม่เอง
อาจทำใน Gedit ก็ได้ โดยใช้การ Find&Replace ธรรมดาครับ

ทางแก้ถาวรคงต้องแจ้ง Bug ไปที่ Drupal ต่อไป

Topic: