이것저것

XpressEngine 위젯을 제작해 보았다.

ForceCore 2009. 1. 13. 01:45
식당 전단지를 모아놓은 게시판이 있다고 하자.
전단지 하나당 글이 한개씩 있다.
이 게시판은 카테고리를 지원하는 게시판이다.
각 글은 카테고리에 속한다. 카테고리란... 중식 한식 돈까스 피자 이런 식으로 음식의 분류로 되어있다.

만들고자 하는 위젯은 이렇다.
1. 게시판이 가지고 있는 카테고리를 랜덤으로 하나 고른다.
2. 골라진 카테고리내의 글을 하나 랜덤으로 골라준다.
3. 골라진 것의 preview를 위젯 내용으로 한다.
webzine과 기능상 비슷하지만 내용 전정이 좀 다른 것이다...

우선 webzine 위젯을 복제해서 새로운 모듈을 시작한다.
뭐.. webzine모듈을 복사해서 rand_webzine따위로 바꾸고, 그 안의 webzine.class.php를 rand_webzine.class.php따위로 바꾸는 것이 첫 스텝이다.

이제 문제에 봉착.
대체 어딜 어떻게 고쳐야 하는거지?
conf/info.xml부터 시작할까?
여기엔 위젯에 대한 설명과, 그리고 위젯이 어떤 설정 가능한 variable을 갖는지 지정된다.
이미 있는 모듈에서 컨닝을 해서 원하는 옵션을 넣도록 하자.

근데... 문제에 봉착. 주관식 입력박스를 variable로 받는걸 info.xml에서 어떻게 하는진 알겠다... type이 text니까. 그런데 나머지 종류들은 대체 뭐가 있단 말인가. XpressEngine의 매뉴얼을 뒤져보았으나 그런 항목에 대한 설명은 없었다. 오픈소스화인건 좋은데, 그에 상응하는 매뉴얼이 아쉬운 시점이다. grep명령어를 사용해 알아낸 결과 현재, select, text, mid, mid_list 이 네 개가 사용되고 있다. 대충 이것들이면 살아갈만하긴 하다. true/false는 select로 Y/N을 하면 되니 뭐...

Y/N은, 게시판의 카테고리를 하나 랜덤으로 고른 다음, 그 안에서 또 게시물을 골라낼 것인지 여부를 정하는 부분에 쓰일 예정이다. N이면 그냥 카테고리에 상관 없이 아무 글이나 하나 골라줄 것이다.

Boolean을 처리하기 위해 Y/N을 하는 것은 원래 XpressEngine에서도 그렇게 하는 형편이니 뭐 OK. 이제 문제는. 게시판의 category를 어떻게 가져올 것이야는건데... 어떡하지 어떡하지 하다가 ZBXE에 이미 있는 document class를 쓸까 하다가...

근데 컨닝해야 할 부분이 document class라는 것을 알아내기까지 삽질이 좀 필요했다. phpMyAdmin으로 카테고리가 어디 있는지 색출했다. -_-;;

이제 카테고리 정보가 든 table에서 column명을 힌트로 어떤 소스를 보아야 하는지 유추할 수 있다.

$ grep -ir column명 *
이런 명령어를 시용하면 그 column명이 어느 파일에 들어있는지, 하위디렉토리까지 뒤져서 검색해준다. 현재 디렉토리 이하로는 안 내려감 -_-;;

zbxe/modules/document
이 안의 queries를 보면 getCategoryList 이런 게 있다.
그리고 getCtegoryList라고 적힌 파일을 다 잡아내면 카테고리를 골라내는 적절한 함수도 들어있다 +_+

그러나... 뭔가 구려서 필자는 필자가 직접 짜기로 했다. 뭐가 구린고 하니... 함수가 zbxe의 고유 기능을 콜하기 때문에 필자가 마음대로 query를 고치지 못한다는거...


쿼리를 직접 짜기 위해서 xe_document_categories table을 phpMyAdmin으로 직접 열어보았다.
위 그림과 같이 되었다.
앗차... column 이름은
category_srl module_srl parent_srl title expand document_count regdate last_update list_order group_srls
이렇게 되어 있다.
뭐... 해당 게시판의 카테고리라면 module_srl이 되겠다. 이게 원하는 게시판의 것과 일치하는 것을 다 내놓으라는 쿼리를 만들어주면 되겠다.

역시... 제로보드 자체 내의 함수보다 더 간단한 함수만으로 되었다 +_+;;
디버그 할 때 var_dump를 못 써서 힘들었는데 이렇게 할 수 있다:
 
ob_start();
 var_dump( $cats[0]->title );
 var_dump( $cats[0]->category_srl );
 $out = ob_get_clean();
 return $out;
return값이 string이면 ZBXE의 ${content}부분에 들어가니까.
위 코드는 ob_start(()와 ob_get_clean() 사이에... 출력되는 내용이 다 variable 안으로 string형태로 들어가버린다.

쿼리의 내용만 잘 짜면 그다지 어렵진;; 않았다.
http://zbxe.springnote.com/pages/392367
쿼리 짜는 법은 XE의 매뉴얼을 참고하라. 자세히 가르쳐 주진 않지만 없는 것 보단 나으니까 ㅋ_ㅋ

쿼리1:
category srl을 가져오되... 카테고리만 있고 그에 상응하는 글이 없는 카테고리는 제외. 카테고리라고 무작정 랜덤으로 골랐는데 글이 없으면... 글이 0이면 다시 카테고리 고르고 이런 루프를 도는 코딩은 좋지 않다 :D 그런 건 DB쿼리를 잘 짜면 해결가능.
<query id="getCategoryList" action="select">
    <tables>
        <table name="document_categories" />
    </tables>
    <columns>
        <!--<column name="*" />-->
        <column name="title" />
        <column name="category_srl" />
    </columns>
    <conditions>
        <condition operation="equal" column="module_srl" var="module_srl" notnull="notnull" />
        <condition operation="notequal" column="document_count" var="zero" default="0" pipe="and" />
    </conditions>
    <navigation>
        <index var="bogus" default="rand()" order="asc" />
        <list_count var="bogus" default="1" />
    </navigation>
</query>

쿼리2. 카테고리에 관계 없이 아무거나 게시판에서 하나 뽑은 쿼리
<query id="getAnyRand" action="select">
    <tables>
        <table name="documents" />
    </tables>
    <columns>
        <column name="*" />
    </columns>
    <conditions>
        <condition operation="in" column="module_srl" var="module_srl" filter="number" />
    </conditions>
    <navigation>
        <index var="list_order" default="rand()" order="asc" />
        <list_count var="list_count" default="1" />
    </navigation>
</query>

마지막으로 게시판 중, 카테고리 내에서 하나 뽑는 쿼리:
<query id="getCatRand" action="select">
    <tables>
        <table name="documents" />
    </tables>
    <columns>
        <column name="*" />
    </columns>
    <conditions>
        <condition operation="in" column="module_srl" var="module_srl" filter="number" />
        <condition operation="equal" column="category_srl" var="cat_srl" pipe="and" />
    </conditions>
    <navigation>
        <index var="list_order" default="rand()" order="asc" />
        <list_count var="list_count" default="1" />
    </navigation>
</query>
후후후.

결과물을 첨부한다:
라이센스: http://creativecommons.org/licenses/by/3.0/deed.en_GB
위의 링크로 조합된 CCL정도로 준한다.

사실 XpressEngine이라는 GPL 라이센스를 따르는 엔진의 작은 component일 뿐이건만 라이센스를 내세운다는게 좀 오만해보인다. 그래도. "자유라이센스"라고 모호하게 해서는 곤란하므로 엄밀하게 정의한다.

같은 CCL 라이센스라도, 국가별로 설명이 미묘하게 다르고, 용어도 다르고, 설명도 다르게 나와 있다.
영국의 영어 설명이 가장 마음에 든다. 대강 해석하면
1. 자유롭게 복사하고 배포하고 시연해도 좋다.
2. 이것을 기반으로 다른 작품을 만들어도 좋다.
3. 그래도 원작자인 필자가 한 것이라는 것을 표기는 해주길
4. 이것을 사용하거나 그에 기반해 다른 것을 만들면 이 원작의 라이센스에 대해 설명해 주어야 함...
근데 사용 부분은 홈페이지에 갖다 붙이는 것뿐이니 생략해도 되겠죠 ㅋ_ㅋ;;
5. 이 라이센스를 줄줄이 설명해 놓은 것도, 작가가 허용하기만 하면 skip가능.
6. ?? 작가의 도덕적 뭐시기 하는데 뭐라는지 모르겠음.