-
Notifications
You must be signed in to change notification settings - Fork 0
/
StaticFileMaker.txt
309 lines (273 loc) · 10.7 KB
/
StaticFileMaker.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/**
* StaticFileMaker
*
* リソースから静的ファイルを生成します(MovableTypeっぽい機能)。
* フレンドリーURL機能は有効にする事
*
* @category plugin
* @version 1.02
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License (GPL)
* @author soushi
* @internal @events OnDocFormRender,OnDocFormSave,OnManagerLogin,OnWebPageInit,OnManagerPageInit
* @internal @modx_category StaticFileMaker
* @internal @properties &rebuild_password=静的ファイル生成用パスワード;text; &defaultAction=既定の動作;list;生成する,生成しない;生成する &dirIndexFile=コンテナに付加するファイル名;text;index.html
*/
$eventid=999; //999 = Custom action
$logInfo=1; //情報
$logWarn=2; //警告
$logErr=3; //エラー
//フレンドリーURLが無効の時は何もしない
if( !($this->config['friendly_urls'] == 1 && $this->config['friendly_alias_urls'] == 1) ){
if( $this->event->name == 'OnManagerPageInit' ){
$this->logEvent($eventid,$logWarn,'StaticFileMakerを利用するにはフレンドリーURLを有効にする必要があります。','[plugin]StaticFileMaker');
}
return false;
}
//デフォルトの生成ルールを決定
if( $defaultAction == '生成する' ){
$defaultMake = true;
}else{
$defaultMake = false;
}
//コンテナに付けるファイル名を決定
$dirIndexFile = empty($dirIndexFile)?'index.html':$dirIndexFile;
//生成対象/対象外の判定関数
$makeJudge=function($id,$defaultMake=true){
global $modx; //クロージャの中で$thisが利用できるのは php5.4 以降
if( $modx->getPageInfo($id,1,'id') == false ){ //非公開リソースは強制的に生成対象外
return false;
}
$rslt = $defaultMake;
$sfmOption=$modx->getTemplateVarOutput(array('StaticFileMakerOption'),$id);
$sfmOption=$sfmOption['StaticFileMakerOption'];
if( preg_match('/exceptSelf/',$sfmOption) ){ //自分自身の設定
$rslt = !$rslt;
}elseif(! preg_match('/makeForce/',$sfmOption) ){ //親リソースからの継承
$pid=$modx->getParent($id,1,'id');
if( $pid === false ){ $pid = $modx->getParent($id,0,'id');}
while( $pid !== false ){ //親リソースの設定を確認
$pid=$pid['id'];
$sfmOptionParent=$modx->getTemplateVarOutput(array('StaticFileMakerOption'),$pid);
$sfmOptionParent=$sfmOptionParent['StaticFileMakerOption'];
if( preg_match('/exceptChildren/',$sfmOptionParent) ){
$rslt = !$rslt; //反転
$pid=0;
}
$tmp_pid=$modx->getParent($pid,1,'id');
if( $tmp_pid === false ){ $tmp_pid = $modx->getParent($pid,0,'id');}
$pid=$tmp_pid;
}
}
return $rslt;
};
switch ($this->event->name) {
case 'OnDocFormRender': //ボタン追加
$editFlag=0;
if( !empty($id) ){
$url=$this->makeUrl($id);
$editFlag=1;
$makeEnable=0;
if( $makeJudge($id,$defaultMake) ){
$makeEnable=1;
}
}
$output = <<< HTML_END
<input type="hidden" id="rebuild_flag" name="rebuild_flag" value="0" />
<script type="text/javascript">
//差し込むエレメント
var el_div = document.getElementById('actions');
// リストエレメント
var new_ul = document.createElement("ul");
new_ul.setAttribute("class", "actionButtons");
new_ul.setAttribute("style", "margin-top:8px;");
//ボタン生成 - 再構築
var newA = document.createElement("a");
var newText = document.createTextNode("全ファイル生成");
var newLi = document.createElement("li");
newA.appendChild( newText );
newA.setAttribute("href", "#");
newA.setAttribute("onclick", "window.open('/manager/index.php?a=998&sys=rebuild','rebuildAllFile','width=400, height=500, scrollbars=yes');");
newLi.appendChild ( newA );
new_ul.insertBefore( newLi,new_ul.firstChild );
//ボタン生成 - プレビュー
if( 1 == $editFlag && 1 == $makeEnable ){
var newA = document.createElement("a");
var newText = document.createTextNode("ファイルプレビュー");
var newLi = document.createElement("li");
newA.appendChild( newText );
newA.setAttribute("href", "#");
newA.setAttribute("onclick", "window.open('$url?__rebuild_pfile=1','previeWinPFile');");
newLi.appendChild ( newA );
new_ul.insertBefore( newLi,new_ul.firstChild );
}
//ボタン生成 - 保存+ファイル生成
if( 1 == $makeEnable ){
var newA = document.createElement("a");
var newText = document.createTextNode("保存+ファイル生成");
var newLi = document.createElement("li");
newA.appendChild( newText );
newA.setAttribute("href", "#");
newA.setAttribute("onclick", "if(window.confirm('保存後、静的ファイルを生成を行います(非公開にチェックをいれた場合は削除されます)。')){document.getElementById('rebuild_flag').value='1'; documentDirty=false; document.mutate.save.click();}");
newLi.appendChild ( newA );
new_ul.insertBefore( newLi,new_ul.firstChild );
}
//差し込み
el_div.appendChild( new_ul );
</script>
HTML_END;
$this->event->output($output);
break;
case 'OnDocFormSave': //ファイル生成
$url=$this->makeUrl($id);
if( preg_match('/\/$/',$url) ){
$url .= $dirIndexFile;
}
$makeEnable=$makeJudge($id,$defaultMake);
$tbl_site_content = $this->getFullTableName('site_content');
$rs=$this->db->select('id,published,deleted,privateweb',$tbl_site_content,"id={$id}");
$row = $this->db->getRow($rs);
if( $row === false ){
$this->logEvent($eventid,$logErr,'リソースが見つかりません:'.$id,'[plugin]StaticFileMaker');
}
//削除はrebuild_flagに関係なく実施する
if( $row['published'] == 0 ||
$row['deleted'] == 1 || //削除の判定は不要だけど一応
$row['privateweb'] == 1 ||
$makeEnable == false
){
//削除
if( is_file(MODX_BASE_PATH.$url) ){
if(! unlink(MODX_BASE_PATH.$url) ){
$this->logEvent($eventid,$logErr,'ファイルの削除に失敗しました:'.$url,'[plugin]StaticFileMaker');
}
}
}elseif( $_REQUEST['rebuild_flag'] == '1' && $makeEnable ){
//生成
$content = @file_get_contents(MODX_SITE_URL . "index.php?id={$id}&__rebuild={$rebuild_password}");
$urls=preg_split('/\//',$url);
$filename=array_pop($urls);
$path=MODX_BASE_PATH;
foreach($urls as $key => $val){
if( empty($val) ){continue;}
$path .= $val.'/';
if(! is_dir($path) ){
if(! mkdir($path) ){
$this->logEvent($eventid,$logErr,'ディレクトリの作成に失敗しました:'.$path,'[plugin]StaticFileMaker');
}
}
}
if( @file_put_contents($path.$filename,$content) === false){
$this->logEvent($eventid,$logErr,'ファイルの作成に失敗しました:'.$path.$filename,'[plugin]StaticFileMaker');
}
}
break;
case 'OnManagerLogin': //プレビューが確認できるようにcookieの生成
$rebuildCode=md5(rand(1000,9999).time().getmypid()); //適当な文字列を生成
setcookie('__rebuild',$rebuildCode,0,'/');
$_SESSION['__rebuild'] = $rebuildCode;
break;
case 'OnWebPageInit': //cookieとセッション値が合わない場合、隠しパスワードに合致しない場合は404へ
//ちょっと条件が複雑…
if( !(
(
(isset($_COOKIE['__rebuild']) && isset($_SESSION['__rebuild']) && $_COOKIE['__rebuild'] == $_SESSION['__rebuild']) ||
(isset($_GET['__rebuild']) && $_GET['__rebuild'] == $rebuild_password)
) && $_GET['__rebuild_pfile'] != '1'
)
){
//ファイル生成が無効になっている場合は素直に表示させるためスルー
if( $makeJudge($this->documentIdentifier,$defaultMake) ){
$this->sendErrorPage();
}
}
break;
case 'OnManagerPageInit': //全リソースファイル生成
if( $action == 998 && $_GET['sys']=='rebuild' ){
//共通フォーム
$outputForm = <<< HTML_END
<div style="text-align:center;margin-top:50px;">
<form method="GET" action="/manager/index.php">
<input type="hidden" id="a" name="a" value="998" />
<input type="hidden" id="sys" name="sys" value="rebuild" />
<input type="hidden" id="mode" name="mode" value="rebuild" />
<input type="submit" value="全ファイル生成">
<input type="button" onClick="window.close(); return false;" value="ウィンドウを閉じる"><br />
※公開状態になっている全リソースのファイルを生成します。<br />
※非公開/削除/プライベート設定になっているリソースのファイルは削除します。<br />
※リソース数が多いと時間がかかる場合があります。<br />
</form>
</div>
HTML_END;
$output = '';
$mode=isset($_GET['mode'])?$_GET['mode']:'';
switch ($mode) {
case 'rebuild':
$listMk='';
$listRm='';
$tbl_site_content = $this->getFullTableName('site_content');
$rs=$this->db->select('id,published,deleted,privateweb',$tbl_site_content);
while($row = $this->db->getRow($rs)){
$url=$this->makeUrl($row['id']);
if( preg_match('/\/$/',$url) ){
$url .= $dirIndexFile;
}
$makeEnable=$makeJudge($row['id'],$defaultMake);
if( $row['published'] == 0 ||
$row['deleted'] == 1 ||
$row['privateweb'] == 1 ||
$makeEnable == false ){
//削除
if( is_file(MODX_BASE_PATH.$url) ){
$err='';
if(! unlink(MODX_BASE_PATH.$url) ){
$err='※削除失敗';
}
$listRm.=$url.$err.'<br >';
}
}else{
//生成(ここの処理は単独の生成ロジックと似てるのでそのうち無名関数くらいにした方がいいかも)
$content = @file_get_contents(MODX_SITE_URL . "index.php?id={$row['id']}&__rebuild={$rebuild_password}");
$urls=preg_split('/\//',$url);
$filename=array_pop($urls);
$path=MODX_BASE_PATH;
$err='';
foreach($urls as $key => $val){
if( empty($val) ){continue;}
$path .= $val.'/';
if(! is_dir($path) ){
if(! mkdir($path) ){
$err='※ディレクトリ生成失敗';
}
}
}
if( @file_put_contents($path.$filename,$content) === false){
$err='※ファイル生成失敗';
}
$listMk.=$url.$err.'<br >';
}
}
if( $listMk == '' ){
$listMk = '生成ファイルなし';
}
if( $listRm == '' ){
$listRm = '削除ファイルなし';
}
$output = <<< HTML_END
{$outputForm}
<div style="text-align:left;margin-top:20px;margin-left:50px;">
<h2>ファイル生成完了しました!</h2>
<h3>生成ファイル</h3>
{$listMk}
<h3>削除ファイル</h3>
{$listRm}
</div>
HTML_END;
$this->event->output($output);
break;
default:
$this->event->output($outputForm);
break;
}
}
break;
}