PluginProbe
codoc / 0.9.45
codoc v0.9.45
0.9.8.8 0.9.8.9 0.9.9 0.9.9.1 trunk 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.8.1 0.8.2 0.8.3 0.8.4 0.8.6 0.8.7 0.8.8 0.8.9 0.9 0.9.1 0.9.10 0.9.11 All 114 releases
codoc / class-codoc-util.php

class-codoc-util.php in codoc 0.9.45, at class-codoc-util.php

445 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WPINC')) {
4 define( 'WPINC', 'wp-includes' );
5 }
6
7 if (!defined('CODOC_URL')) {
8 define( 'CODOC_URL', 'https://codoc.jp' );
9 }
10
11 require_once( ABSPATH . WPINC . '/class-http.php');
12 require_once( ABSPATH . WPINC . '/class-wp-error.php');
13
14 final class CodocUtil {
15 public $codoc_url = CODOC_URL;
16 public function __construct($params = ['usercode' => null, 'token' => null,'codoc_url' => null]) {
17 $this->setAuthInfo(['usercode' => $params['usercode'], 'token' => $params['token']]);
18 if (isset($params['codoc_url'])) {
19 $this->codoc_url = $params['codoc_url'];
20 }
21 return $this;
22 }
23
24 public function callAPI($method,$path,$body = [],$headers = []) {
25 $usercode = $this->usercode;
26 $token = $this->token;
27
28 $headers['X-CodocToken'] = $token;
29 $host = $this->codoc_url;
30 $sslverify = true;
31
32 if (preg_match('/local/',$this->codoc_url)) {
33 $sslverify = false;
34 $host = 'https://host.docker.internal';
35 }
36 $url = sprintf("%s/api/v1/cms/%s%s",$host,$usercode,$path);
37 $http = new WP_Http();
38 try {
39 $response = $http->request(
40 $url,
41 [
42 'sslverify' => $sslverify,
43 'method' => $method,
44 'timeout' => 10,
45 'headers' => $headers,
46 'body' => $body,
47 ]
48 );
49 if ( is_wp_error($response) || $response['response']['code'] != 200 ) {
50 //何もしない
51 //var_dump( $response );
52 }
53 } catch(Exception $e) {
54
55 }
56 if (!is_wp_error($response) and
57 isset($response['body']) and
58 is_string($response['body']) and
59 is_array(json_decode($response['body'], true)) and
60 (json_last_error() == JSON_ERROR_NONE)) {
61 return json_decode($response['body']);
62 } else {
63 return null;
64 }
65 }
66 public function callPaywallAPI($method,$path,$body = [],$headers = []) {
67 $site_usercode = get_option(CODOC_USERCODE_OPTION_NAME);
68 $paywall_token = $this->get_paywall_token_code();
69
70 $host = $this->codoc_url;
71 $sslverify = true;
72
73 if (preg_match('/local/',$this->codoc_url)) {
74 $sslverify = false;
75 $host = 'https://host.docker.internal';
76 }
77 $url = sprintf("%s/api/v1/paywall/%s%s",$host,$site_usercode,$path);
78 $http = new WP_Http();
79 try {
80 $response = $http->request(
81 $url,
82 [
83 'sslverify' => $sslverify,
84 'method' => $method,
85 'timeout' => 10,
86 'headers' => $headers,
87 'body' => $body,
88 ]
89 );
90 if ( is_wp_error($response) || $response['response']['code'] != 200 ) {
91 //何もしない
92 //var_dump( $response );
93 }
94 } catch(Exception $e) {
95
96 }
97 if (!is_wp_error($response) and
98 isset($response['body']) and
99 is_string($response['body']) and
100 is_array(json_decode($response['body'], true)) and
101 (json_last_error() == JSON_ERROR_NONE)) {
102 return json_decode($response['body']);
103 } else {
104 return null;
105 }
106 }
107 public function setAuthInfo($params = [ "usercode" => null, "token" => null ]) {
108 if ($params["usercode"]) {
109 $this->usercode = $params["usercode"];
110 }
111 if ($params["token"]) {
112 $this->token = $params["token"];
113 }
114 return true;
115 }
116 public function get_token($params = ["fetch_token_key" => null],$auth_info = ["usercode" => null, "token" => null]) {
117 $this->setAuthInfo($auth_info);
118 return $this->callAPI('GET','/token',[ "fetch_token_key" => $params["fetch_token_key"] ]);
119 }
120 public function get_user_info($params = [] ,$auth_info = ["usercode" => null, "token" => null]) {
121 $this->setAuthInfo($auth_info);
122 return $this->callAPI('GET','');
123 }
124 public function get_support_entry($params = [] ,$auth_info = ["usercode" => null, "token" => null]) {
125 $this->setAuthInfo($auth_info);
126 return $this->callAPI('GET','/support_entry');
127 }
128 public function sync_entry($params = [
129 "post_title" => null,
130 "post_content" => null,
131 "post_status" => null, # 0, 1
132 "post_permalink" => null,
133 "codoc_entry_code" => null,
134 ],$auth_info = ["usercode" => null, "token" => null]) {
135
136 $this->setAuthInfo($auth_info);
137
138 $post_content = $params['post_content'];
139 preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
140 // GUTENBERG で指定されたjson(記事�
141 )がない場合
142 if (!$matches) {
143 return;
144 }
145 // GUTENBERG で保存している�
146 容を取得
147 $codoc_info = json_decode($matches[1],true);
148 // codoc タグがない場合はなにもしない
149 //preg_match('/(<span +data-id="codoc-tag"[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
150 preg_match('/(<(?:span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:span|div)>)/',$post_content,$matches);
151 if (!$matches) {
152 return;
153 }
154 // TODO: split or html parse? HTMLがつながってる場合はおかしくなる
155 // classic(tinymce)版の場合p、もしくはdivにかこまれている
156 $end_tag_regex = '/<(?:div|p)>::CODOC_WP_END_PAYWALL::<\/(?:div|p)>/';
157 $before_splited = preg_split($end_tag_regex,$post_content);
158 $post_content = $before_splited[0];
159 $splited = preg_split('/(?:<(?:div|p)(?:[^>]+|)>|)<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->(?:<\/(?:div|p)>|)/s',$post_content);
160 $status = $params['post_status']; # 0: 非�
161 �開 1: �
162 �開 2:限定�
163 �開(パスワードの場合は限定�
164 �開で同期する)
165 // codoc設定で限定�
166 �開を有効で、�
167 �開の場合は 限定�
168 �開にする
169 if ($status == 1 and isset($codoc_info['statusLimited']) and $codoc_info['statusLimited']) {
170 $status = 2;
171 }
172 # $body_free = '';
173 # $body_paywalled = '';
174 # if (count($splited) >= 2) {
175 #
176 # }
177 $binded_url = $params['post_permalink'];
178 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
179 if (isset($CODOC_SETTINGS['str_replace_binded_url_from']) and
180 isset($CODOC_SETTINGS['str_replace_binded_url_to']) and
181 $CODOC_SETTINGS['str_replace_binded_url_from']) {
182 $binded_url = str_replace(sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_from']),
183 sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_to']),
184 $binded_url);
185 }
186 $api_params = [
187 'title' => $params['post_title'],
188 'body_free' => $splited[0],
189 'body_paywalled' => $splited[1],
190 'status' => $status,
191 'binded_url' => $binded_url,
192 'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
193 'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
194 'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
195 'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
196 'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
197 'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
198 'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
199 'show_paywalled_support' => isset($codoc_info['showPaywalledSupport']) ? ($codoc_info['showPaywalledSupport'] ? 1 : 0) : 0,
200 'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
201 ];
202 $entryCode = $params['codoc_entry_code'];
203 $res = null;
204 if ($entryCode) {
205 $res = $this->callAPI('PUT','/entries/' . $entryCode ,$api_params);
206 } else {
207 $res = $this->callAPI('POST', '/entries', $api_params);
208 }
209 return $res;
210 }
211
212 function post_thumbnail( $params = [
213 "file_path" => null,
214 "boundary" => null,
215 "codoc_entry_code" => null,
216 ], $auth_info = ["usercode" => null, "token" => null] ) {
217
218 $this->setAuthInfo($auth_info);
219
220 $file_path = $params['file_path'];
221 $boundary = $params['boundary']; # ランダム変数24桁 wp_generate_password(24);
222 $res = null;
223 if (is_readable($file_path)) {
224 $name = 'file';
225
226 $payload = '';
227 $payload .= '--' . $boundary;
228 $payload .= "\r\n";
229 $payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
230 $payload .= "Content-Type: application/octet-stream\r\n";
231 $payload .= "Content-Transfer-Encoding: binary\r\n";
232 $payload .= "\r\n";
233 $payload .= file_get_contents( $file_path );
234 $payload .= "\r\n";
235
236 $payload .= '--' . $boundary . '--';
237
238 $entryCode = $params['codoc_entry_code'];
239 $res = $this->callAPI(
240 'POST',
241 '/entries/' . $entryCode . '/thumbnail',
242 $payload,
243 ['content-type' => 'multipart/form-data; boundary=' . $boundary]
244 );
245 }
246 return $res;
247 }
248
249 function reset_thumbnail( $params = [
250 "codoc_entry_code" => null,
251 ],$auth_info = ["usercode" => null, "token" => null] ) {
252
253 $this->setAuthInfo($auth_info);
254
255 $entryCode = $params['codoc_entry_code'];
256 $res = $this->callAPI(
257 'POST',
258 '/entries/' . $entryCode . '/thumbnail',
259 [ "reset" => 1 ]
260 );
261 return $res;
262 }
263
264 function filter_content( $params = [
265 "post_content" => null,
266 "preview" => null,
267 "codoc_entry_code" => null,
268 "codoc_settings" => null,
269 "is_amp_endpoint" => null,
270 "post_permalink" => null,
271 "codoc_support_entry_code" => null,
272 ]) {
273 $CODOC_SETTINGS = $params['codoc_settings'];
274
275 $has_codoc_tag = '/(<(span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:div|span)>)/';
276 $post_content = $params['post_content'];
277 // codoc タグがあるかどうか (202001:span -> div に変更)
278 preg_match($has_codoc_tag,$post_content,$matches);
279
280 $show_support_message = '';
281 if (isset($CODOC_SETTINGS['show_support_message'])) {
282 $show_support_message = $CODOC_SETTINGS['show_support_message'];
283 }
284 $show_support_categories = '';
285 if (isset($CODOC_SETTINGS['show_support_categories'])) {
286 $show_support_categories = $CODOC_SETTINGS['show_support_categories'];
287 }
288 $show_support_location = 'bottom';
289 if (isset($CODOC_SETTINGS['show_support_location'])) {
290 $show_support_location = $CODOC_SETTINGS['show_support_location'];
291 }
292
293 $show_support_entry = (is_single() && preg_grep("/(?:$show_support_categories)/",array_map( function($c) { return $c->name; },get_the_category(get_post()->ID))));
294 if (!$matches && ($support_entry_code = $params['codoc_support_entry_code']) && $show_support_entry) {
295 $support_tag = sprintf(
296 '<div class="codoc-entries" data-without-body="1" data-support-message="%s" id="codoc-entry-%s" data-support-button-text="%s" data-show-like="%s" data-show-about-codoc="%s" data-show-powered-by="%s"></div>',
297 htmlspecialchars($show_support_message,ENT_QUOTES),
298 $support_entry_code,
299 $CODOC_SETTINGS['support_button_text'],
300 $CODOC_SETTINGS['show_like'],
301 $CODOC_SETTINGS['show_about_codoc'],
302 $CODOC_SETTINGS['show_powered_by']
303 );
304 $post_content = $show_support_location == 'bottom' ?
305 $post_content . $support_tag :
306 $support_tag . $post_content ;
307 }
308
309 // data-wp-plugin-ver が無いタグは分割しない
310 if (!$matches) {
311 return $post_content;
312 }
313
314 // codocタグで分割 (202001: gutenbergで直前のdivタグを削除)
315 $tag_regex = '/(?:<div(?:[^>]+|)>|)<(?:span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:span|div)>(?:<\/div>|)/';
316 $end_tag_regex = '/<(?:div|p)>::CODOC_WP_END_PAYWALL::<\/(?:div|p)>/';
317 if ( $params['preview'] ) {
318 $post_content = preg_replace($tag_regex,'<div class="codoc-continue">ここから上は無料で表示されます</div>',$post_content);
319 $post_content = preg_replace($end_tag_regex,'<div class="codoc-continue">ここから下は無料で表示されます</div>',$post_content);
320 return $post_content;
321 }
322 // codoc タグの前後で分ける
323 $before_splited = preg_split($end_tag_regex,$post_content);
324 $splited = preg_split($tag_regex,$before_splited[0]);
325 // codoc タグにID属性のentrycodeとdata-without-body(無料分を非表示)をつける
326 $entryCodeFormated = sprintf('"codoc-entry-%s" ',$params['codoc_entry_code']);
327
328 // 文言系の設定をつける
329 $tagAttributes = '';
330 if (isset($CODOC_SETTINGS['show_like']) and $CODOC_SETTINGS['show_like'] != 1) {
331 $tagAttributes = $tagAttributes . sprintf(' data-show-like="%s"',$CODOC_SETTINGS['show_like']);
332 }
333 if (isset($CODOC_SETTINGS['show_about_codoc']) and $CODOC_SETTINGS['show_about_codoc'] != 1) {
334 $tagAttributes = $tagAttributes . sprintf(' data-show-about-codoc="%s"',$CODOC_SETTINGS['show_about_codoc']);
335 }
336 if (isset($CODOC_SETTINGS['show_powered_by']) and $CODOC_SETTINGS['show_powered_by'] != 1) {
337 $tagAttributes = $tagAttributes . sprintf(' data-show-powered-by="%s"',$CODOC_SETTINGS['show_powered_by']);
338 }
339 if ($CODOC_SETTINGS['entry_button_text']) {
340 $tagAttributes = $tagAttributes . sprintf(' data-entry-button-text="%s"',$CODOC_SETTINGS['entry_button_text']);
341 }
342 if ($CODOC_SETTINGS['subscription_button_text']) {
343 $tagAttributes = $tagAttributes . sprintf(' data-subscription-button-text="%s"',$CODOC_SETTINGS['subscription_button_text']);
344 }
345 if ($CODOC_SETTINGS['support_button_text']) {
346 $tagAttributes = $tagAttributes . sprintf(' data-support-button-text="%s"',$CODOC_SETTINGS['support_button_text']);
347 }
348 if ($CODOC_SETTINGS['subscription_message']) {
349 $tagAttributes = $tagAttributes . sprintf(' data-subscription-message="%s"',$CODOC_SETTINGS['subscription_message']);
350 }
351 if ($CODOC_SETTINGS['support_message']) {
352 $tagAttributes = $tagAttributes . sprintf(' data-support-message="%s"',$CODOC_SETTINGS['support_message']);
353 }
354 if ($CODOC_SETTINGS['codoc_tag_attributes']) {
355 $tagAttributes = $tagAttributes . sprintf(' %s',$CODOC_SETTINGS['codoc_tag_attributes']);
356 }
357
358 $codoc_tag = preg_replace('/<((?:span|div)[^>]+)data-id="[^"]+"((?:[^>]+|))>/','<${1} ${2} data-without-body="1" id=' . $entryCodeFormated . $tagAttributes . ">", $matches[1]);
359 # THE THOR の page-lp.php が " " をけずるための対策
360 # "div class" -> "div class"
361 $codoc_tag = preg_replace('/div +class/','div class',$codoc_tag);
362
363 if ($params['is_amp_endpoint']) {
364 $format = preg_replace_callback('/(<(?:span|div)[^>]+>)((?:[^<>]+|))(<\/(?:span|div)>)/',function($matches) {
365 $format = $matches[1] . '<a href="%%s">%s</a>' . $matches[3];
366 return sprintf($format,($matches[2] ? $matches[2] : '続きを読む'));
367 },$codoc_tag);
368 $codoc_tag = sprintf($format,$params["post_permalink"]);
369 }
370
371 # タグの前後にHTMLを挿�
372
373 if (!isset($CODOC_SETTINGS['str_before_codoc_tag'])) {
374 $CODOC_SETTINGS['str_before_codoc_tag'] = '';
375 }
376 if (!isset($CODOC_SETTINGS['str_after_codoc_tag'])) {
377 $CODOC_SETTINGS['str_after_codoc_tag'] = '';
378 }
379 // 無料部分のみ表示
380 $post_content = $splited[0] . sprintf(
381 '%s<div class="wp-block-codoc-codoc-block">%s</div>%s',
382 $CODOC_SETTINGS['str_before_codoc_tag'],
383 $codoc_tag,
384 $CODOC_SETTINGS['str_after_codoc_tag']
385 );
386 // ::CODOC_WP_END_PAYWALL:: の後を足す
387 if (isset($before_splited[1]) and $before_splited[1]) {
388 $post_content .= $before_splited[1];
389 }
390 return $post_content;
391 }
392 /*
393
394 // Cookieの中のトークンを取得
395 $_CODOC->util->get_paywall_token_code();
396
397 */
398 function get_paywall_token_code() {
399 if (isset($_COOKIE['codocTokenCode']) and $codocTokenCode = $_COOKIE['codocTokenCode']) {
400 return $codocTokenCode;
401 }
402 return null;
403 }
404 /*
405
406 $_CODOC->util->check_login($mode); // cookie / strict
407
408 */
409 function check_login($mode = 'cookie') {
410 if ($codocTokenCode = $this->get_paywall_token_code()) {
411 if ($mode == 'cookie') {
412 // cookieの中にtokenがあればOK
413 return true;
414 }
415 if ($mode == 'strict') {
416 // ログイン状�
417 �を問い合わせ
418 $res = $this->callPaywallAPI('GET','/users',["paywall_token_code" => $codocTokenCode ]);
419 if ($res->status) {
420 return true;
421 } else {
422 return false;
423 }
424 }
425 }
426 return false;
427 }
428 /*
429
430 $_CODOC->util->check_owned($entry_code);
431
432 */
433 function check_owned($entry_code = null) {
434 if (!$entry_code) {
435 return false;
436 }
437 $res = $this->callPaywallAPI('GET','/entries/' . $entry_code, ["paywall_token_code" => $this->get_paywall_token_code(), "check_owned" => 1 ]);
438 if ($res->status) {
439 return true;
440 }
441 return false;
442 }
443 }
444
445