Movable Type検索結果画面のMTIncludeタグでファイルを読み込む方法
Movable Type検索結果画面のMTIncludeタグでファイルを読み込む方法を紹介します。
1.はじめに
MTで再構築するファイルの拡張子を".php"にして、そのページの中で頻繁に更新される部分を、
<?php include('foo.html'); ?>
で読み込むことで、ページ全体の再構築不要で情報を更新することができます。
ただ、検索結果ページはPerlのCGIで動作するため、PHPの方法を利用することができません。
ということで、検索結果画面のMTIncludeタグでファイルを読み込む方法を紹介します。
2.検索結果画面のMTIncludeタグでファイルを読み込む
1項のfoo.phpのパスを、仮に「/var/www/html/foo.html」とします。
このファイルを検索結果画面のMTIncludeタグで読み込むには、下記の手順が必要です。
まず、mt-config.cgiに
AllowFileInclude 1
を設定します(注:4項参照)。
次に、ファイル読み込み部分を次のようにします。
<$mt:Include file="/var/www/html/foo.html"$>
これで、検索結果画面でも情報を更新する部品を利用することができます。
3.サイトパスにテンプレートタグを使用する
2項ではファイルパスに「/var/www/html」を直接記述しましたが、テンプレートタグでサイトパスを取得するには次のように記述します。
<mt:Setvarblock name="foo"><$mt:SitePath$>/foo.html</mt:setvarblock>
<$mt:Include file="$foo"$>
1行目のMTSetVarBlockタグで、サイトパスとファイル名を文字列結合したものを、変数fooに設定します。
2行目のMTIncludeタグで、fileモディファイアに「$foo」と書くことで、変数fooの内容が展開され、
<$mt:Include file="/var/www/html/foo.html"$>
と同じ結果となります。
4.注意事項
AllowFileIncludeはセキュリティ対策として、デフォルトで無効(=0)となっています。
理由は「テンプレート編集の権限だけをもつユーザーが、ファイルシステム上の任意のファイルを読み出せるのは問題であるため」のようです。
このカスタマイズを利用する場合は、上記のセキュリティに十分配慮してください。
ansibleのcopyモジュールでディレクトリを生成する方法
ansibleのcopyモジュールでディレクトリを生成する方法を紹介します。
1.問題点
ansibleのcopyモジュールでファイルをコピーしたいのですが、コピー先のディレクトリがなく、エラーになります。
試したのは下記の2種類です。
test.yml
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb/hoge.txt2
remote_src: yes
または
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb
remote_src: yes
これを実行すると、下記のように"Destination directory /tmp/aaa/bbb does not exist"というエラーになります。
$ ansible-playbook -i inventory test.yml
PLAY [act] ***************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************
ok: [server]
TASK [test : test.ymlをインクルード] *************************************************************************************************************
included: /var/tmp/ansible/roles/test/tasks/test.yml for server
TASK [test : テスト] *****************************************************************************************************************************
fatal: [server]: FAILED! => {"changed": false, "msg": "Destination directory /tmp/aaa/bbb does not exist"}
TASK [test : エラーが発生したため停止] ***********************************************************************************************************
fatal: [server]: FAILED! => {"changed": false, "msg": "ロール実行中にエラー発生"}
PLAY RECAP ***************************************************************************************************************************************
server : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=1 ignored=0
ということで、ansibleのcopyモジュールでディレクトリを生成する方法を紹介します。
2.ansibleのcopyモジュールでディレクトリを生成する
ansibleのcopyモジュールでディレクトリを生成するには、destオプションを"/"で終わらせます。
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb/
remote_src: yes
このansibleを実行すると正常にディレクトリを生成してくれます。
$ ansible-playbook -i inventory test.yml
PLAY [act] ***************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************
ok: [server]
TASK [test : test.ymlをインクルード] *************************************************************************************************************
included: /var/tmp/ansible/roles/test/tasks/test.yml for server
TASK [test : テスト] *****************************************************************************************************************************
changed: [server]
PLAY RECAP ***************************************************************************************************************************************
server : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
jQuery+ajaxでモーダルのコンテンツを取得する方法
jQuery+ajaxでモーダルのコンテンツを取得する方法を紹介します。
1.はじめに
モーダル表示の使い方は、たとえば商品ページで、その商品の詳細画像を表示するといったことが多いと思います。
その場合、HTMLページ内にすべてのモーダル用コンテンツを配置して、そこから取得・表示する実装になると思います。
ですが、ページ内にモーダル用のコンテンツをすべて記述すると、場合によってはページのサイズが大きくなり、ロード時間に影響します。
また商品ページではなく、たとえばモーダルをブログの記事ページとして表示させたい場合、上記の方法では大量のコンテンツをページ内に書き出す必要がありますが、現実的ではありません。
ということで、本記事ではモーダル用コンテンツをjQuery+ajaxで取得し、さらの前後リンクのコンテンツもjQuery+ajaxで取得する方法を紹介します。
2.サンプル
下記のリンクをクリックするとサンプルページに遷移します。
テキスト途中にある「ひらく」をクリックするとモーダルが表示され、前後リンクをクリックするとコンテンツをajaxで読み出して表示を切り替えます。
「あああ」のテキストを大量に挿入しているのは、モーダル表示後にスクロールしてもモーダルが移動しないことを示すためのものです。
サンプルはモーダルコンテンツの取得と前後リンクだけに着目しているので、CSSは最小限です。またアニメーションや「閉じる」ボタンの実装もありません。
以下、ソースとjQueryの解説です。
3.ソース
<meta charset="UTF-8" />
<style>
#modal {
display: block;
position: fixed;
opacity: 1;
z-index: 11000;
left: 45%;
margin-left: -77px;
top: 100px;
}
#modal_content {
border: 1px solid #000000;
padding: 30px;
}
#left {
position: absolute;
top: 100px;
left: -170px;
}
#right {
position: absolute;
top: 100px;
right: -170px;
}
</style>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script>
$(function(){
$(".open_modal").on('click', function(){
var url = $(this).attr('data-url');
$.ajax({
type: "POST",
url: url,
dataType: "html"
}).done(function(data) {
let main = $($.parseHTML(data)).filter('#main').html();
let prev = $($.parseHTML(data)).filter('#previous').text();
let next = $($.parseHTML(data)).filter('#next').text();
$('#modal_content').html(main);
if ( prev ) {
$('#left').attr('data-url', prev);
$('#left').css('display', 'block');
} else {
$('#left').css('display', 'none');
}
if ( next ) {
$('#right').attr('data-url', next);
$('#right').css('display', 'block');
} else {
$('#right').css('display', 'none');
}
$('#modal').css('display', 'block');
});
});
});
</script>
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<div class="open_modal" data-url="https://www.koikikukan.com/samples/20240313/test1.html">ひらく</div>
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<div id="modal" style="display:none;">
<div class="open_modal" id="left" data-url=""><</div>
<div class="open_modal" id="right" data-url="">></div>
<div id="modal_content"></div>
</div>
4.解説
「ひらく」のclass属性"open_modal"をclickイベントで待ち合わせます。
<div class="open_modal" data-url="https://www.koikikukan.com/samples/20240313/test1.html">ひらく</div>
:
<script>
$(function(){
$(".open_modal").on('click', function(){
クリックされると要素内のdata-url属性値に設定したURLをattrメソッドで取得します。
var url = $(this).attr('data-url');
data-urlの値は下記のdata()でも取得できますが、この方法ではDOMのキャッシュが誤って取得されてしまうため、この記事の執筆時点ではdata()は絶対に使わないでください(この事象で2日ほど悩みました)。
var url = $(this).data('url');
取得したURLでコンテンツをajaxで取得します。
$.ajax({
type: "POST",
url: url,
dataType: "html"
$.ajax以外に$getでも取得可能です。
なお非同期による取得ではキャッシュが取得されてしまうこともあるので、POSTメソッドを使用する、cacheオプションをfalseにする等の対処を行ってください。
取得したコンテンツをそのままHTMLに展開できないケースを考慮して、部分取得を行います。
ここではコンテンツ部分と前後リンク部分をparseHTML()とfilter()を使います。この方法がベストプラクティスと思われます。
}).done(function(data) {
let main = $($.parseHTML(data)).filter('#main').html();
let prev = $($.parseHTML(data)).filter('#previous').text();
let next = $($.parseHTML(data)).filter('#next').text();
取得したHTMLをモーダルに反映します。
$('#modal_content').html(main);
URLを前後リンクに反映させます。このときも前述と同様の理由でdata()ではなく、attr()を使用してください。リンクがない場合は非表示にしています。
if ( prev ) {
$('#left').attr('data-url', prev);
$('#left').css('display', 'block');
} else {
$('#left').css('display', 'none');
}
if ( next ) {
$('#right').attr('data-url', next);
$('#right').css('display', 'block');
} else {
$('#right').css('display', 'none');
}
すべての設定が終わったらdisplayプロパティを使ってモーダル全体を表示します。
$('#modal').css('display', 'block');
ansibleでフィンガープリントを表示させない方法
ansibleでフィンガープリントを表示させない方法を紹介します。
1.問題点
ansibleでログイン経験がないサーバにログインをすると、下記のような「フィンガープリント」が表示されます。
The authenticity of host '[127.0.0.1]:22 ([127.0.0.1]:22)' can't be established.
RSA key fingerprint is SHA256:1pOx1qnpCf9UfJQPVaMRfJV/6LZkHWQXljHwwYGlN1g.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ansible実行時にフィンガープリントを表示させないのですが、方法がわかりません。
ということで、ansibleでフィンガープリントを表示させない方法を紹介します。
2.ansibleでフィンガープリントを表示させない
ansibleでフィンガープリントを表示させないようにするには、ansible.cfgに下記の設定を追加します。
[ssh_connection]
ssh_args = '-o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
オプションの意味は次の通りです。
- ControlMaster=auto:sshのセッションが存在するときにそのセッションを再利用する仕組み
- ControlPersist=60s:ControlMasterをバックグランドにまわしてくれる機能
- StrictHostKeyChecking=no:ホストの~/.ssh/known_hostsに存在しないときに確認なしに接続し、フィンガープリントは確認なしにknown_hostsに記録されます
- UserKnownHostsFile=/dev/null:ホストの~/.ssh/known_hostsを常に空(/dev/null)にすることで、サーバ交換等でフィンガープリントが変わったときにエラーとなってしまうのを回避します
FFmpegをWindowsにインストールする方法
FFmpegをWindowsにインストールする方法を紹介します。
1.はじめに
Windows端末で「ScreenToGif」という、デスクトップキャプチャで取得した動画をMP4で保存しようとしたら、「FFmpegのパスが通っていません」と警告が表示されました。
FFmpeg自体インストールした記憶がないので、本記事でFFmpegをWindowsにインストールする方法を紹介します。
ちなみに、FFmpegはオープンソースのマルチメディアフレームワークで、主にコマンドラインツールとして動作し、多くの音声・動画フォーマットに対応した、ストリームの保存や変換が可能です。
2.FFmpegのダウンロード
FFmpegのページにアクセスして「Download」をクリック。
Windowsのアイコンをクリック。
「Windows builds by BtbN」をクリック。
「ffmpeg-master-latest-win64-gpl.zip」をクリック。
ダウンロードしたアーカイブを展開し、ここでは
C:\Program Files (x86)\ffmpeg
となるように配置します。
2.パスを通す。
タスクバーの検索フィールドに「システムの詳細設定」を入力して、「システムの詳細設定の表示」をクリック。
「環境変数」をクリック。
「xxのユーザー環境変数」の「Path」を選択した状態で「編集」をクリック。
「新規」をクリック。
今回は下記のパスを追加して「OK」をクリック。
C:\Program Files (x86)\ffmpeg\bin
前の画面も「OK」をクリックして、すべて閉じます。
3.動作確認
コマンドプロンプトを開いて、下記のコマンドを実行。
ffmpeg -version
パスが正常に通っていれば、下記のメッセージが表示されます。
これでFFmpegのインストール完了です。
シェルスクリプトのexpectで応答メッセージを振り分ける方法
シェルスクリプトのexpectで確認メッセージを振り分ける方法を紹介します。
1.問題点
シェルスクリプトを使ってパスワード入力が必要なコマンド(scp)を実行するためにexpectを使っています(下記)。
#!/bin/bash
expect -c "
spawn scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
expect \"Are you sure you want to continue connecting (yes/no)?\"
send \"yes\n\"
expect \"password:\"
send \"hoge\n\"
interact
"
ですが、確認メッセージが2パターンあり、それらを振り分ける方法がわかりません。
具体的には、
% scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
というコマンドを実行すると、初回は、
Are you sure you want to continue connecting (yes/no)?
と聞かれて、そのあと
password:
を聞かれるのですが、2回目以降は、
password:
しか聞かれません。
ということで、シェルスクリプトのexpectで確認メッセージを振り分ける方法を紹介します。
2.シェルスクリプトのexpectで確認メッセージを振り分ける
確認メッセージを振り分けるには、次のように書き換えます。
#!/bin/bash
expect -c "
spawn scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
expect {
\"Are you sure you want to continue connecting (yes/no)?\" {
send \"yes\n\"
expect \"password:\"
send \"hoge\n\"
} \"password:\" {
send \"hoge\n\"
}
}
interact
"
具体的には、expect節で全体を括り、その中にifのthen節とelse節のように確認メッセージを分けて記述します。
Adobe Acrobat Reader(Adobe Reader)で電子印鑑を押印する方法
Adobe Acrobat Reader(Adobe Reader)で電子印鑑を押印する方法を紹介します。
1.電子印鑑の用意
電子印鑑は有料・無料など色々なサイトで作ることができます。
ここでは、画像の印鑑データを透過したり、テキスト打ち込みで印鑑が作れる「印鑑透過」で作ったものを利用します。
「STORES」というサイトでも無料ダウンロードできるようです。
2.PDFに電子印鑑を押印する
印鑑を押印したいPDFファイルを開き、「すべてのツール」タブの「入力と署名」または「電子サイン」をクリック。
「イニシャルを追加」をクリック。
「画像」をクリック。
電子印鑑にしたい画像を選択すると枠内に表示されるので「適用」をクリック(ここでサイズ等の調整はできません)。
なお、この印鑑を毎回使いたい場合は画面左下の「イニシャルを保存」をチェックしておくと便利です。ここではチェックした状態で進めます。
「適用」をクリックすると、PDFに適用した電子印鑑が表示され、マウスで移動できる状態になります。
位置を決めてクリックすると印鑑が固定されます。
印鑑に編集ボックスが表示されます。「A」は印鑑の拡大・縮小、ゴミ箱は印鑑の削除です。
その右の「…」は印鑑ではないイニシャル等におきかえるものです。
これでPDFを保存すれば、電子印鑑が捺印された状態になります。
次回以降は「電子サイン」に選択した印鑑が表示されるので、印鑑をクリックするだけでPDFに表示されます。×印をクリックすれば登録を解除できます。
ansibleのインベントリに設定した変数にアクセスする方法
ansibleのインベントリに設定した変数にアクセスする方法を紹介します。
1.問題点
ansibleで下記のインベントリを作成しました。
test00 ansible_host=192.168.0.10
test01 ansible_host=192.168.0.11
[all:vars]
ansible_user=test
ansible_ssh_pass=test
[server1]
test00
[server2]
test01
[server1:vars]
hoge=1
[server2:vars]
hoge=2
このインベントリでserver1ホスト指定で実行するときに、server2の変数hoge
[server2:vars]
hoge=2
の値を参照したいのですが、方法が分かりません。
ということで、ansibleのインベントリに設定した変数にアクセスする方法を紹介します。
2.ansibleのインベントリに設定した変数にアクセスする
ansibleのインベントリに設定した変数にアクセスするには、下記のように指定します。
hostvars[groups['server1'][0]]['hoge']
例:
- name: コマンド実行
command:
cmd: echo {{ hostvars[groups['server1'][0]]['hoge'] }}
register: result
- name: "結果出力"
debug:
msg: "{{ result.stdout_lines }}"
小粋空間プラグインのMovable Type8対応状況
小粋空間で販売させて頂いているプラグインのMovable Type8対応状況です。
Workflow
コンテンツデータ・記事・ウェブページで承認ワークフローを実現します。多段階承認やグループ別承認、複数承認も可能です。
すべてのグレードでMT8に対応しました。
CSVDataImExporter
CSV形式でMovable Typeのコンテンツデータ・記事・ウェブページデータのエクスポート・インポートが可能になるプラグインです。
通常版・機能拡張版、いずれもでMT8に対応しました。
SaveWithoutRebuild
Movable Typeでコンテンツデータや記事保存時に再構築を行わないためのプラグインです。
MT8に対応しました。
ListingFieldEditor
コンテンツデータや記事のカスタムフィールドのデータを一覧画面で編集できるプラグインです。
MT8に対応しました。
PowerListingFieldEditor
コンテンツデータや記事のカスタムフィールドのデータを一覧画面で一括編集できるプラグインです。
MT8に対応しました。
価格について
いずれも価格はMT7から据え置きですが、今後機能追加や機能差分等で改修を伴う場合は価格を変更させて頂くかもしれません。
その他
他のプラグインも随時、MT8に対応させて頂く予定です。
VirtualBoxにisoファイルをマウントしてローカルリポジトリでdnfを利用する方法
VirtualBoxにisoファイルをマウントしてローカルリポジトリでdnfを利用する方法を紹介します。
ここではWindowsマシンにVirtualBoxをインストールしてCentOSのゲストOSを作成し、Windowsのフォルダにisoファイルを配置している前提で進めます。
利用したいisoファイルは事前に入手し、Windowsの任意のフォルダにダウンロードしておいてください。
1.isoファイルのマウント
該当のゲストOSが停止・選択している状態で、VirtualBoxマネージャーの「設定」をクリック。
「ストレージ」をクリック。
「コントローラーIDE」にisoファイルを設定します。この例ではすでに設定してしまっているので、すいませんが他の記事を参考に設定してください。
また、このサンプルではCentOSのisoのみを設定していますが、デフォルトではVBoxGuestAdditions.isoがマウントされている可能性があります。その状態で後続のマウントを実施すると期待する結果にならないようなので、マウントしたいisoのみにしてください。
そしてゲストOSを起動して、/media配下にcdromディレクトリを作成し、mountコマンドを実行します。
# cd /media
# mkdir cdrom
# mount /dev/cdrom /media/cdrom
mount: /media/cdrom: 警告: デバイスは書き込み禁止です、読み込み専用でマウントします.
これで/media/cdrom配下が下記の状態になればOKです。
# pwd
/media/cdrom
# ls
AppStream BaseOS EFI TRANS.TBL images isolinux media.repo
2.リポジトリの設定変更
デフォルトでは外部のリポジトリを参照する設定になっているので、それらを変更します。
ちなみに、何も設定していない状態でdnf listを実行すると、次のようなエラーになります。
# dnf repolist
CentOS-8 - AppStream 6.8 B/s | 38 B 00:05
repo 'AppStream' のメタデータのダウンロードに失敗しました。
エラー: repo 'AppStream' のメタデータのダウンロードに失敗しました。
/etc/yum.repos.d/CentOS-AppStream.repoのenabledを1(有効)から0(無効)に変更します(★の行、以下同様)。
/etc/yum.repos.d/CentOS-AppStream.repo
:
[AppStream]
name=CentOS-$releasever - AppStream
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Base.repoのenabledを1(有効)から0(無効)に変更します。
/etc/yum.repos.d/CentOS-Base.repo
:
[BaseOS]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=BaseOS&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/BaseOS/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Extras.repoのenabledを1(有効)から0(無効)に変更します。
/etc/yum.repos.d/CentOS-Extras.repo
:
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/extras/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Media.repoのenabledを0(無効)から1(有効)に変更します。
/etc/yum.repos.d/CentOS-Media.repo
:
[c8-media-BaseOS]
name=CentOS-BaseOS-$releasever - Media
baseurl=file:///media/CentOS/BaseOS
file:///media/cdrom/BaseOS
file:///media/cdrecorder/BaseOS
gpgcheck=1
enabled=1★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
[c8-media-AppStream]
name=CentOS-AppStream-$releasever - Media
baseurl=file:///media/CentOS/AppStream
file:///media/cdrom/AppStream
file:///media/cdrecorder/AppStream
gpgcheck=1
enabled=1★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
これで、dnfコマンドでローカルリポジトリが利用できるようです。
# dnf repolist
CentOS-BaseOS-8 - Media 154 MB/s | 2.2 MB 00:00
CentOS-AppStream-8 - Media 177 MB/s | 5.4 MB 00:00
repo id repo の名前 状態
c8-media-AppStream CentOS-AppStream-8 - Media 4,755
c8-media-BaseOS CentOS-BaseOS-8 - Media 1,659
MovableTypeプラグインの独自CGIをNginxに対応させる方法
Category:[トラブルシューティング]
Tag:[MovableType, Plugin, TroubleShooting, Workflow]
Permalink
MovableTypeプラグインの独自CGIをNginxに対応させる方法を紹介します。
これはMovable Type Advent Calendar 2023の24日目の記事です。
1.はじめに
以前、Workflowプラグインの独自CGI(mt-preview.cgi)がNginx環境に対応しておらず、アクセスすると「Not Found」というお客様からの申告があり、そのときの対処方法を備忘録で残しておきます。
MTプラグインで独自CGIを実装される方は、変更後または追加部分のみ参照されればよいかと思います。
冗長な修正があるかもしれませんが、実際に修正して回復した内容ということでそのまま掲載しておきます。
2.対処方法
まず。独自CGIの下記の1行を修正。
変更前
use MT::Bootstrap App => 'Workflow::App';
変更後
use MT::Bootstrap App => 'MT::App::Workflow';
config.yamlに"key"を追加。
key: Workflow
プラグインアプリケーション(独自CGI)の定義を丸々追加。ここでは、
- handler
- script
- cgi_path
の3項目を定義します。
applications:
workflow:
handler: MT::App::Workflow
script: '$Workflow::MT::App::Workflow::script_name'
cgi_path: >
sub {
my $path = MT->config->CGIPath;
$path =~ s!/$!!;
$path =~ s!^https?://[^/]*!!;
$path .= '/plugins/Workflow';
return $path;
}
エラーが発生した状態のCGI(Workflow.pm)はMT::App::CMSを継承していたのを、MT::Appを継承するように変更。
変更前
use base qw( MT::App::CMS );
変更後
use base qw( MT::App );
それに伴い、lib/Workflow/App.pm → lib/MT/App/Workflow.pm に移動。
移動したWorkflow.pm に、idとscript_nameを追加。
sub id {'workflow'}
sub script_name {'mt-preview.cgi'}
修正前はinit_requestしかなかったので、initを追加し、旧init_requestのadd_methodsをinitに移動。
変更前(抜粋)
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->add_methods( preview => \&preview );
$app->{ default_mode } = 'main';
$app->{ requires_login } = 0;
}
変更後(抜粋)
sub init {
my $app = shift;
$app->SUPER::init(@_);
$app->add_methods( preview => \&preview );
$app->{ default_mode } = 'main';
$app;
}
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->{requires_login} = 0;
}
これで独自CGIがNginxで動作するようになりました。
メール送信で「smtp-source: fatal: connect: Connection refused」となる場合の対処
メール送信で「smtp-source: fatal: connect: Connection refused」となる場合の対処方法を紹介します。
1.問題点
以前、「さくらのVPSに送信メールサーバを設定する方法」で紹介した、メールサーバからメールがとばなくなりました。
具体的には、テストメールを送信すると、下記のように「Connection refused」となります。
# smtp-source -v -f "" -t "hoge@xxx.so-net.ne.jp" 127.0.0.1:25
smtp-source: name_mask: all
smtp-source: fatal: connect: Connection refused
ということで、メール送信で「smtp-source: fatal: connect: Connection refused」となる場合の対処方法を紹介します。
2.原因
単純に、何かの拍子にサービスが停止してしまっただけのようです。
netstatで確認したところ、25番ポートも開いていないようでした。
# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
:
tcp 0 0 :::80 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
ということで、サービス起動で解消しました。
# service postfix start
Starting postfix: [ OK ]
25番ポートも開きました。
# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
:
tcp 0 0 :::80 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
tcp 0 0 :::25 :::* LISTEN
ちなみにサービスを起動したところ、サービス停止で滞留していたメールが一斉に送信されたようです。
MovableTypeのDataAPIでコンテンツデータをモーダル表示させる方法
MovableTypeのDataAPIでコンテンツデータをモーダル表示させる方法を紹介します。
1.サンプル
下記のテンプレートをコピーしてインデックステンプレートとして再構築してください。
サンプルでは、デフォルトの「Site Page」コンテンツデータの一覧を表示して、リンクをクリックすると取得したデータ(JSON)をモーダル表示させます。
ユーザー、Webサービスパスワード、クライアントID、サイトID、コンテンツタイプIDは適宜書き換えてください。
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<script src="<$mt:StaticWebPath$>data-api/v4/js/mt-data-api.min.js"></script>
<mt:Contents content_type="Site Page">
<mt:ContentsHeader><dl></mt:ContentsHeader>
<dt><$mt:ContentLabel$></dt>
<dd><mt:ContentField content_field="Title"><a href="javascript:void(0);" class="mtlink" data-id="<mt:ContentID>"><$mt:ContentFieldValue$></a></mt:ContentField></dd>
<mt:ContentsFooter></dl></mt:ContentsFooter>
</mt:Contents>
<div id="main" style="display:none;">
<p id="hoge"></p>
</div>
<script>
$(function() {
var accessToken;
$.ajax({
url: "<$mt:CGIPath$><$mt:DataAPIScript$>/v<$mt:DataAPIVersion$>/authentication",
type: "POST",
dataType: "json",
data: {
'username': 'ユーザー名',
'password': 'ユーザーのWebサービスパスワード',
'clientId': '任意のID'
}
}).done(function(data){
accessToken = "MTAuth accessToken=" + data.accessToken;
});
$(".mtlink").click(function(){
$('#hoge').text('');
var content_data_id = $(this).data('id');
$("#main").dialog({
open: function(event, ui) {
// コンテンツデータ取得
$.ajax({
url: "<$mt:CGIPath$><$mt:DataAPIScript$>/v<$mt:DataAPIVersion$>/sites/1/contentTypes/1/data/" + content_data_id,
type: "GET",
dataType: "json",
headers: {
'X-MT-Authorization': accessToken
}
}).done(function(data){
$('#hoge').text(JSON.stringify(data));
});
},
modal:true, //モーダル表示
title:"テスト", //タイトル
width: 900,
height: 500,
});
});
});
</script>
2.解説
必要なライブラリを引き込みます。
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<script src="<$mt:StaticWebPath$>data-api/v4/js/mt-data-api.min.js"></script>
コンテンツデータの一覧を表示します。data-id属性にコンテンツデータIDを設定。リンクはページ遷移しないようにしておきます。
<mt:Contents content_type="Site Page">
<mt:ContentsHeader><dl></mt:ContentsHeader>
<dt><$mt:ContentLabel$></dt>
<dd><mt:ContentField content_field="Title"><a href="javascript:void(0);" class="mtlink" data-id="<mt:ContentID>"><$mt:ContentFieldValue$></a></mt:ContentField></dd>
<mt:ContentsFooter></dl></mt:ContentsFooter>
</mt:Contents>
モーダルとなるエリアです。
<div id="main" style="display:none;">
<p id="hoge"></p>
</div>
ページ読み込み時にアクセストークンを取得・保持します。
var accessToken;
$.ajax({
url: "<$mt:CGIPath$><$mt:DataAPIScript$>/v<$mt:DataAPIVersion$>/authentication",
type: "POST",
dataType: "json",
data: {
'username': 'ユーザー名',
'password': 'ユーザーのWebサービスパスワード',
'clientId': '任意のID'
}
}).done(function(data){
accessToken = "MTAuth accessToken=" + data.accessToken;
});
リンククリックで前回のモーダル表示の内容をクリアし、コンテンツデータIDを取得します。
$(".mtlink").click(function(){
$('#hoge').text('');
var content_data_id = $(this).data('id');
dialogでモーダル表示を実行し、openイベントを使って、モーダルが開いたタイミングでDataAPIを起動してコンテンツデータを取得します。
$("#main").dialog({
open: function(event, ui) {
// コンテンツデータ取得
$.ajax({
url: "<$mt:CGIPath$><$mt:DataAPIScript$>/v<$mt:DataAPIVersion$>/sites/1/contentTypes/1/data/" + content_data_id,
type: "GET",
dataType: "json",
headers: {
'X-MT-Authorization': accessToken
}
}).done(function(data){
$('#hoge').text(JSON.stringify(data));
});
},
modal:true, //モーダル表示
title:"テスト", //タイトル
width: 900,
height: 500,
});
Movable Type 8の共有プレビューでパスワードを設定する方法
Movable Type 8の共有プレビューでパスワードを設定する方法を紹介します。
共有プレビューの基本機能については下記の記事を参照してください。
1.パスワードの設定
パスワードはサイト別に複数設定可能です。
サイト管理画面の「設定」→「プラグイン」→「SharedPreview x.x」→「設定」をクリック。
パスワード入力画面に任意のパスワードを入力して「変更を保存」をクリック。
「パスワードを追加」をクリックすれば複数のパスワードを設定できます。
不要なパスワードは「削除」ボタンで削除できます。
2.共有プレビュー時のパスワード入力
パスワードを設定すれば、共有プレビュー時にパスワード入力を求める画面が表示されます。
Movable Type 8リリース
遅ればせながら、Movable Type 8が11/1にリリースされました。
ここでは主な機能を紹介します。
1.共有プレビュー
コンテンツデータや記事を下書き状態にすると「共有プレビュー」のリンクが表示されます。
リンクをクリックするとプレビュー画面が表示されます。
また、編集画面のリンクや、共有プレビューのリンク、公開ページのリンクも取得できます。
共有プレビューのリンク
公開ページのリンク
これまでのプレビューと異なるのは、コンテンツを編集して保存しても再度同じURLでプレビューを確認が可能です。
またパスワードも設定できるようです。
ちなみに共有プレビューは「mt-shared-preview.cgi」をキックしています。
2、新しいブロックエディタ
プラグインとして提供していた 新しいブロックエディタ(MTブロックエディタ)機能を同梱しました。
既存のブロックエディタも同梱されてますが、デフォルトは無効になっています。
「カスタムブロック」も作成可能です。
3.管理画面の多要素認証
プラグインとして提供されていた多要素認証機能が同梱されました。
現在は TOTP (Time-based One Time Password) による2要素認証に対応しているようです。
利用するには下記の認証アプリが必要です。
- Google Authenticator ( iOS版 / Android版 )
- Twilio Authy ( iOS版 / Android版 )
- Microsoft Authenticator ( iOS版 / Android版 )
- 2FA Authenticator (2FAS) ( iOS版 / Android版 )
設定方法は、各ユーザー編集画面に「認証デバイスの設定」が表示されます。
クリックするとQRコードが表示されるので、対応する認証アプリで読み込み、確認コードを入力。
これで設定完了です。
これで管理画面にログインすると、二段階認証画面に遷移するので、認証アプリに表示されたコードを入力すればログインできます。
解除したい場合は、ユーザー編集画面から解除できます。
4.ライセンス確認
システム管理画面の「設定」→「ライセンス確認」でライセンスを確認できるようになりました(手動で登録)、
5.検索機能への導線の改善
管理画面の左上に、検索ページへ遷移するボタンが設置されました。