<?php

// (Shirai075): fs_moodleの設定を表示するメニューをサイト管理に追加 (2008/07/21)

// ------------------------------------------------------------
pagecheck();
// ------------------------------------------------------------

function description_globalsearch()
{
    global $CFG, $fsCFG;
    print_section_header('グローバルサーチについて');
    print_subsection_header('グローバルサーチの概要');
    echo '　グローバルサーチはMoodleサイト上に存在する様々なコンテンツをサーチエンジンのように検索する高度な機能を持つブロックです．';
    echo 'まだまだ発展途上のブロックであり，不具合や機能の不足が目立ちます．';
    echo 'ただし，問題点を理解した上で用いれば非常に強力で便利な機能であることに直ぐに気付くでしょう．';
    newline();
    echo '　グローバルサーチは事前にインデックスを作成する作業を行う必要があります（search/indexer.php）．';
    echo 'また，定期的に，追加／削除／更新されたコンテンツに対してインデックスの更新作業も必要です(search/cron.php)．';
    echo '管理者は仕事が増えるので迷惑ですし，インデックスの作成や更新は非常にサーバ負荷の高い作業です．';
    echo 'しかし，その苦労を上回るメリットがあります．';
    echo '　グローバルサーチはデータベースとしてMoodleと共通のMySQLやPostgreSQLを用いるのではなく，';
    echo 'Zend社の公開しているLucene互換の純PHP製データベースを使用します．';
    echo '検索用のインデックスファイルはmoodledataフォルダ（'.color_blue("{$CFG->dataroot}/search").'）に格納されます．';
    newline();
    echo color_red('（注意）').'なお，このドキュメントは2009/06/11現在の状態に基づいて記述しています．';
    newline();
    print_subsection_footer();

    print_subsection_header('グローバルサーチで出来ること');
    echo '　グローバルサーチは，';
    echo '(1)課題，(2)チャット，(3)データベース，(4)フォーラム，(5)用語集，(6)ラベル，(7)レッスン，(8)リソース，(9)Wiki，(10)ユーザプロファイル，(11)ブログ';
    echo 'のコンテンツをインデックス化してデータベースに蓄えます．';
    echo 'どのモジュールのインデックス化を有効にするかどうかはサイト管理の［プラグイン］－［ブロック］－［グローバルサーチ］で設定可能です（執筆時点ではユーザプロファイルとブログの設定が抜けている）．';
    echo '課題，リソース，ブログに関しては添付ファイルが';
    echo 'テキス（*.txt），PDF（*.pdf），HTML（*.htm, *.html)，Word（*.doc），ODT（*.odt），パワーポイント（*.ppt）';
    echo 'であるならば，一部は外部プログラムを用いてテキスト化した後に，トークンを抜き出してインデックス化します．';
    echo 'サイト中の全コースファイルを対象としてインデックス化するのでは無い点はご理解下さい．';
    echo 'また，ヒットした検索結果は，そのユーザが閲覧する権限があるかどうかをチェックした後に表示されます．';
    echo 'したがってヒット数に対して閲覧可能な検索結果のリストの数は少なく表示されます（値が不一致する）．';
    echo 'ただしこのセキュリティが万全かどうかは完全なテストを行った訳では無いので気を付けて下さい．';
    newline();
    print_subsection_footer();

    print_subsection_header('グローバルサーチの解析器に関する課題');
    echo '　ZendFrameworkで用意しているパーサ（解析器）はUTF-8に対応していますが，日本語を考慮されていません．';
    echo 'たとえばテキストファイル，PDF，Wordなどの文書から特徴的な単語を抜き出して（トークン化）してインデックスを作成したり，';
    echo '検索ワードとして入力された単語を検索語に自動変換したりする際に解析器は用いられます．';
    echo 'Zend社のLucene用に日本語対応の解析器を開発した方や，mecabといった外部の解析器を利用する方法も検討しています．';
    echo 'たとえばindex.html（Keyword型：トークン化されていない，と仮定）というファイルを探す際に，検索ワードとしてindex.htmlと入力しても，';
    echo '現在の解析器はindexとhtmlの二つの単語のフレーズ検索（デフォルトで OR）と解釈するでしょう．';
    echo 'その結果，index.htmlとは完全一致しませんので検索結果にindex.htmlは含まれません．';
    echo 'これは日本語の検索ワードの解析にも影響してきます．たとえば"表１.doc"（全角）と入力したとしても，';
    echo '現在の解析器は表と１とdocに切り分けてしまっているようです．';
    echo 'これらの問題に対応するには検索ワードとしてワイルドカードを用いて，"index*"や"表*"のように指定することで対処します．';
    echo 'ただし，ワイルドカードを用いると検索に時間が掛かりますし，関係の無いデータも沢山，引っ掛かってしまいます．';
    echo 'せめて"表*"ではなく"表１*"と入力したいものですね．';
    print_subsection_footer();

    print_section_footer();
}

function check_globalsearch()
{
    global $CFG, $fsCFG;
    print_section_header('グローバルサーチのシステム設定のチェック');

    print_subsection_header('基本的な設定');
    print_subsubsection_header('グローバルサーチの有効化');
    echo '　グローバルサーチを管理しているサイトで使用可能とするには，まずサイト管理の［その他］－［実験用］';
    echo 'の<a href="'.$CFG->wwwroot.'/admin/settings.php?section=experimental" target="_blank">ページ</a>';
    echo 'を開き，'.color_blue('グローバルサーチを有効にする').'をチェックする必要があります．';
    echo '現在，この設定は'.(($CFG->enableglobalsearch) ? color_blue('Yes') : color_red('No')).'に設定されています．';
    print_subsubsection_footer();

    print_subsubsection_header('文字化け対策');
    echo '　さらに実用的に用いるにはサイト管理の［プラグイン］－［ブロック］－［ブロックの管理］の';
    echo '<a href="'.$CFG->wwwroot.'/admin/blocks.php" target="_blank">ページ</a>を開き，';
    echo color_blue('UTF8 transcoding direction of results').'を'.color_blue('Disabled').'に設定しましょう．';
    echo '現在，この設定は'.(($CFG->block_search_utf8dir) ? color_blue('Disabled') : color_red('Enabled')).'に設定されています．';
    echo 'この設定が'.color_blue('Enabled').'の場合，UTF-8で出力される検索結果がサーバの設定した内部文字コードに変換されて出力されます．';
    echo '文字化けするだけですので'.color_blue('Disabled').'で使用することを勧めます．';
    print_subsubsection_footer();
    print_subsection_footer();

    print_subsection_header('外部テキストコンバータの設定');
    echo '　グローバルサーチではPDFファイルとWordファイル（Odt含む）をテキスト化するために，それぞれ';
    echo '<a href="http://www.foolabs.com/xpdf/download.html" target="_blank">xpdf</a>と';
    echo '<a href="http://www.winfield.demon.nl/" target="_blank">antiword</a>';
    echo 'の使用を想定しています．';
    echo 'ただし，Windows用のantiwordは';
    echo '<a href="http://www.informatik.uni-frankfurt.de/~markus/antiword/" target="_blank">こちらのページ</a>';
    echo 'で配布されています．';
    echo '（それ以外のコンバータでも設定の変更で対応できなくはない）';
    echo 'なお，テキストファイル，HTML，PowerPointは外部コンバータを必要としません．';
    echo 'また，テキストファイルは拡張子がTXTのファイルのみをインデックス化の対象としています．';
    echo 'これはMIMEタイプがtext/plainのものを無制限にインデックス化すると，';
    echo '課題として提出されたＣ言語のソースファイルなども対象となってしまうのを防ぐ目的だと思われます．';
    newline();
    echo '　これらの外部コンバータのパスの設定（およびantiwordの環境変数HOMEの設定）は';
    echo 'サイト管理の［プラグイン］－［ブロック］－［ブロックの管理］の';
    echo '<a href="'.$CFG->wwwroot.'/admin/blocks.php" target="_blank">ページ</a>で設定します．';
    newline();
    newline();

    print_subsubsection_header('xpdfの設定');
    echo '　'.color_blue('pdftotextコマンドのパス').'を設定します．';
    echo 'もしパスが通った場所にpdftotextが存在するならばファイル名とオプションだけで良いでしょう．';
    echo 'お勧めは'.color_blue('lib/xpdf').'の下に，もしWindowsならば'.color_blue('win32/pdftotext.exe').'と配置するのがデフォルトの設定です．';
    echo '現在はMoodleパッケージにxpdfは同梱されていませんが，将来的には組み込まれるかも知れません．';
    newline();
    echo '　現在，パスは';
    if (empty($CFG->block_search_pdf_to_text_cmd)) {
        echo color_red('未設定').'です．';
    } else {
        global $titleonly;
        if (empty($titleonly)) {
            echo color_blue($CFG->block_search_pdf_to_text_cmd).'です．';
            echo color_blue('外部コンバータにMoodle rootを使用する').'が';
            echo color_blue($CFG->block_search_usemoodleroot ? 'Yes' : 'No').'に設定されています．';
            $moodleroot = ($CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ;
            $command = trim($CFG->block_search_pdf_to_text_cmd);
            $text_converter_cmd = "{$moodleroot}{$command}";
            echo 'したがって，実行コマンドは'.color_blue($text_converter_cmd).'です．';
            $ret = fs_shell_exec($text_converter_cmd.' xpdf_test.pdf -', true);
            fs_box_start();
            echo '  --- 実行結果 ---';
            newline();
            if (empty($ret)){
                echo color_red('  実行できませんでした').'．'; newline();
            } else echo $ret;
             echo '  --- ここまで ---';
            if (empty($ret)){
                echo color_red('  xpdfは正しくインストールされているでしょうか？');
                echo color_red('  コマンド名をもう一度，よく確認して下さい．');
                newline();
            }
            fs_box_end();
        }
    }
    print_subsubsection_footer();

    print_subsubsection_header('antiwordの設定');
    echo '　'.color_blue('doctotextコマンドのパス').'と'.color_blue('MSWordコンバータの環境設定').'を設定する必要があります．';
    echo 'antiwordは少々特殊な仕様があります．';
    echo '環境変数HOMEで指定したパスに設定ファイルを読みに行くのではなく，HOME/antiwordの設定ファイルを読みます．';
    echo 'したがって，'.color_blue('lib/antiword/win32/antiword').'のようなフォルダ構造にする必要があります．';
    newline();
    echo '　現在，パスは';
    if (empty($CFG->block_search_word_to_text_cmd)) {
        echo color_red('未設定').'です．';
    } else {
        echo color_blue($CFG->block_search_word_to_text_cmd).'です．';
        echo '環境変数は';
        if ($CFG->block_search_word_to_text_env){
            echo color_blue($CFG->block_search_word_to_text_env).'です．';
            putenv($CFG->block_search_word_to_text_env);
        } else {
            echo color_red('未設定').'です．';
        }
        $moodleroot = (@$CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ;
        if (!fs_file_exists("{$moodleroot}{$CFG->block_search_word_to_text_cmd}")){
            echo color_red('外部コンバータが存在しません！');
        } else {
            global $titleonly;
            if (empty($titleonly)) {
                $command = trim($CFG->block_search_word_to_text_cmd);
                $text_converter_cmd = "{$moodleroot}{$command} -m UTF-8.txt antiword_test.doc";
                $ret = fs_shell_exec($text_converter_cmd, true);
                fs_box_start();
                echo '  --- 実行結果 ---';
                newline();
                if (empty($ret)){
                    echo color_red('  実行できませんでした').'．<br/>';
                } else echo $ret;
                echo '  --- ここまで ---';
                fs_box_end();
                if (empty($ret)){
                    echo color_red('  antiwordは正しくインストールされているでしょうか？');
                    echo color_red('  コマンド名をもう一度，よく確認して下さい．');
                    newline();
                }
            }
        }
    }
    print_subsubsection_footer();
    print_subsection_footer();
    print_section_footer();
}

function fsconfig_check_globalSearchSettings()
{
    global $fsCFG;

    print_section_header('グローバルサーチに関する設定');

    print_subsection_header_fs_switch('FS_ENABLE_GS_DISPLAY_TOKENIZED_WORDS');
    print_notice_message('注意', 'この設定はMoodle1.9以降においてのみ意味を持ちます．');
    echo '　ユーザが入力した検索キーワードがどのようなトークンとして認識されているのかをグローバルサーチの検索時に表示します．';
    echo 'たとえば標準の解析器では，表１.docという検索キーワードは，[表]と[doc]の二つのトークンに切り分けられます．';
    echo 'つまり１という情報は消えてしまいます．';
    echo 'このことを知らずに検索を行っても，効率よく目的のコンテンツを発見できません．';
    echo 'この機能はグローバルサーチの仕組みをある程度，了解しているユーザにとっては極めて便利な機能ですが，';
    echo color_red('後述するように情報漏えいの恐れがありますので，気軽に有効にするのはお勧めできません．');
    print_fs_switch_condition('FS_ENABLE_GS_DISPLAY_TOKENIZED_WORDS');

    if (fs_function_enable('FS_ENABLE_GS_DISPLAY_TOKENIZED_WORDS') != true) {
        echo '<B>'.color_red('　機能が無効ですので，以下の設定値に関するチェックは行っていません．').'</B>';
        newline();
    }

    print_subsubsection_header_fs_cfg('gsDisplayTokenLevel');
    echo '　標準の解析器は上述したように日本語の文法規則に対応していませんので，';
    echo '予想以上に長い文字列がトークンとして認識されてインデックス化されている恐れがあります．';
    echo '本機能は単に入力された検索キーワードを解析器でトークン化した結果を表示するだけではなく，';
    echo 'ワイルドカード指定された場合にはデータベースに登録されているトークン化されたインデックスキーの内，';
    echo 'ワイルドカード指定された検索キーワードにマッチするインデックスをリストアップして表示する機能も含みます．';
    echo 'その結果，外部秘の情報が誤ってインデックスとして登録されてしまっていた場合に，';
    echo 'その情報が外部に漏れる恐れがあります．';
    newline();
    echo '　この便利な機能を利用可能なユーザの権限を制限します．';
    echo 'この変数には以下の選択肢があります．';
    table_of_select_data('gsDisplayTokenLevel');
/*  echo color_blue('$fsCFG->gsDisplayTokenLevel').'の値によって以下のように挙動が変化します．';
    echo '<ol>';
    echo '<li value="1"> : 管理者のみ表示可能です．</li>';
    echo '<li value="2"> : ブロックの設置されたコースの編集権限を持つ者（主に教師以上）のみ表示可能です．つまり学生は表示できません．</li>';
    echo '<li value="4"> : ゲスト以外の利用者に対して表示します．</li>';
    echo '<li value="8"> : 全ての利用者に対して表示可能としますが，この設定はあまりお勧めできません．</li>';
    echo '</ol>';
*/
    echo '　現在，'.color_blue('$fsCFG->gsDisplayTokenLevel').'の設定値は'.color_blue($fsCFG->gsDisplayTokenLevel).'です．';
    switch ($fsCFG->gsDisplayTokenLevel) {
        case 1: echo color_blue('管理者のみが表示可能').'ですので安全性が高いです．'; break;
        case 2: echo color_blue('ブロックの設置されたコースの編集権限を持つ者のみ表示可能').'ですので比較的安全です．'; break;
        case 4: echo color_red('ゲスト以外の利用者に対して表示可能').'ですので，学生にも見えてしまいますので注意が必要です．'; break;
        case 8: echo color_red('全ての利用者に対して表示可能').'ですので安全性が極めて低いので'.color_red('要注意').'です．'; break;
        default: echo color_red('');
    }
    print_fs_cfg_condition('gsDisplayTokenLevel');
    print_subsubsection_footer();

    print_subsubsection_header_fs_cfg('gsDisplayTokenLength');
    echo '　この変数で指定した長さの文字列を超えるトークンは末尾を省略して表示します．';
    echo 'たとえば'.color_blue('5').'が指定されていた場合，トークン化された文字列が'.color_blue('”白井先生の試験は難しい”').'だったとすると，';
    echo color_blue('[白井先生の...]').'と表示されます．';
    echo 'これでセキュリティ上の情報漏えいの危険性は少し軽減します．';
    echo '　'.color_blue('$fsCFG->gsDisplayTokenLength').'の値が負の値の場合は無制限に表示します．';
    newline();
    newline();
    echo '　現在，'.color_blue('$fsCFG->gsDisplayTokenLength').'の設定値は'.color_blue($fsCFG->gsDisplayTokenLength).'です．';
    if ($fsCFG->gsDisplayTokenLength < 0) {
        echo 'したがって，'.color_blue('無制限に表示').'します．';
    } else if ($fsCFG->gsDisplayTokenLength > 0) {
        echo 'したがって，'.color_blue($fsCFG->gsDisplayTokenLength.'文字を超える文字は省略して表示').'します．';
    } else {
        echo color_red('不適切な設定値です．負の値か正の値を設定して下さい．');
    }
    print_fs_cfg_condition('gsDisplayTokenLength');
    print_subsubsection_footer();

    print_subsubsection_header_fs_cfg('gsDisplayTokenNumber');
    echo '　ワイルドカードで検索キーワードを指定した場合，大量の該当するインデックスが画面に表示されてしまいます．';
    echo color_blue('$fsCFG->gsDisplayTokenNumber').'によって画面に表示するインデックスの数を制限できます．';
    newline();
    newline();
    echo '　現在，'.color_blue('$fsCFG->gsDisplayTokenNumber').'は'.color_blue($fsCFG->gsDisplayTokenNumber).'が設定されています．';
    if ($fsCFG->gsDisplayTokenNumber < 0) {
        echo 'したがって'.color_blue('無制限に表示').'します．';
    } else if ($fsCFG->gsDisplayTokenNumber > 0) {
        echo 'したがって，画面には最大で'.color_blue($fsCFG->gsDisplayTokenNumber.'個').'のインデックスしか表示しません．';
    } else {
        echo color_red('不適切な設定値です．負の値か正の値を設定して下さい．');
    }
    print_fs_cfg_condition('gsDisplayTokenNumber');
    print_subsubsection_footer();
    print_subsection_footer();

    print_subsection_header('インデックスの作成に関する設定');
    print_subsubsection_header_fs_switch('FS_ENABLE_GS_INDEXFORUMATTACHMENTS');
    echo '　2009/06/26現在，Moodleオリジナルのグローバルサーチではフォーラムの添付ファイルのインデックス化には対応していません．';
    echo 'fs_moodleでは独自に改良を施してフォーラムの添付ファイルのインデックス化に対応していますが，';
    echo '試験的な実装に過ぎません．';
    echo 'もし不安がある場合はこの機能をオフにして下さい．';
    print_fs_switch_condition('FS_ENABLE_GS_INDEXFORUMATTACHMENTS');
    print_notice_message('注意', 'もし，オリジナルのMoodleがこの機能を搭載した場合はこの設定は無視されます．');
    print_subsubsection_footer();
    print_subsection_footer();
    print_section_footer();
}

description_globalsearch();
check_globalsearch();
fsconfig_check_globalSearchSettings();

?>