S.F. Page

Programming,Music,etc...

Wordpress DBからカテゴリのディレクトリツリーを作る

カテゴリのディレクトリツリーを作る

ここ数日はnode.jsでWordpressのカテゴリーからディレクトリツリーを作るコードを書いていた。 Wordpressではカテゴリをwp_termsとwp_term_taxonomyの2つのテーブルで管理している。 wp_termsは以下のようなフィールドである
フィールド名 内容
term_id ID
name カテゴリ名
slug スラッグ
term_group 不明
通常カテゴリ名はブログ上での表示用に用いられ、ディレクトリ階層にはスラッグが用いられている。 Wordpressのカテゴリは階層構造となっている。この階層構造に関する情報はwp_term_taxonomyに入っている。
フィールド名 内容
term_taxnomy_id ID
term_id wp_termsのID
taxonomy 分類。カテゴリであれば「category」が入る。
description 説明
parent 親の term_id
count おそらくこれに含まれる記事数
この2つのテーブルを組み合わせ以下の方法にてカテゴリーの階層情報を得る。
  1. ルート直下のカテゴリはparentが0なので、parentが0のものを列挙する。
  2. 列挙したカテゴリの子を列挙する。具体的にはterm_idをparentに持つカテゴリを列挙する。
  3. 2.の操作を列挙するカテゴリが0になるまで繰り返す。  列挙するカテゴリが0ということはそのカテゴリ以下に子ディレクトリが存在しないということである。
この考え方で階層情報を得ると同時にディレクトリツリーを作るコードを書くと以下のようになる。

var fs = require('fs');
var Q = require('q');
var dbj = fs.readFileSync('dbinfo.json', 'utf-8');
var dbinfo = JSON.parse(dbj);
var home_dir = './blog/';
var nfs = require('node-fs');

//app.js
var mysql = require('mysql');
var TABLE = 'wp_posts';
//mysqlクライアント作成
var client = mysql.createConnection({
  user: dbinfo.user,
  password: dbinfo.password,
  database: dbinfo.db
});

var query = Q.nbind(client.query, client);

function create_category_dir(data) 
{
    var qparent = 'select * from wp_terms inner join wp_term_taxonomy on wp_terms.term_id = wp_term_taxonomy.term_id where wp_term_taxonomy.taxonomy = "category" and wp_term_taxonomy.parent = ' + data.id;
    
    query(qparent).then(function (result) {
    var records = result[0];
        Q.nfcall(nfs.mkdir, data.dir, true).then(function () {
            console.log(data.dir);
            for (var i = 0; i < records.length; ++i) {
                var record = records[i];
                var d = { id: record.term_id, name: record.name, slug: record.slug, childs:[],dir: data.dir + '/' + decodeURI(record.slug) };
                data.childs.push(d);
                create_category_dir(d);
            }
        },
            function (err) {
            if (err.code === 'EEXIST') {
                console.log(data.dir);
                for (var i = 0; i < records.length; ++i) {
                    var record = records[i];
                    var d = { id: record.term_id, name: record.name, slug: record.slug,childs:[], dir: data.dir + '/' + decodeURI(record.slug) };
                    data.childs.push(d);
                    create_category_dir(d);
                }
            } else {
                throw err;
            }
        });

    });
}

var category = { id: 0, name : 'category', slug: 'category' , childs : [], dir : home_dir + 'category' };
create_category_dir(category);

このコードは動くことは動く。しかし非同期処理のせいでディレクトリツリー作成がいつ・どこで終了するのか把握できず、MYSQL接続をクローズする処理が書けない。なのでMYSQL接続がアイドルでタイムアウトエラーを起こすまで終了されない。最終行でclient.end()を書くとcreate_category_dir()内の非同期処理が完了していない状態でMYSQL接続がクローズされてしまう。
create_category_dir()内の非同期処理がすべて完了するまで待つということがしたいのだが今のところいい案が思いつかない。