PluginProbe
codoc / 0.9.3
codoc v0.9.3
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 / trunk / class-codoc-util.php

class-codoc-util.php in codoc 0.9.3, at trunk/class-codoc-util.php

344 lines 15.4 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 setAuthInfo($params = [ "usercode" => null, "token" => null ]) {
67 if ($params["usercode"]) {
68 $this->usercode = $params["usercode"];
69 }
70 if ($params["token"]) {
71 $this->token = $params["token"];
72 }
73 return true;
74 }
75 public function get_token($params = ["fetch_token_key" => null],$auth_info = ["usercode" => null, "token" => null]) {
76 $this->setAuthInfo($auth_info);
77 return $this->callAPI('GET','/token',[ "fetch_token_key" => $params["fetch_token_key"] ]);
78 }
79 public function get_user_info($params = [] ,$auth_info = ["usercode" => null, "token" => null]) {
80 $this->setAuthInfo($auth_info);
81 return $this->callAPI('GET','');
82 }
83 public function get_support_entry($params = [] ,$auth_info = ["usercode" => null, "token" => null]) {
84 $this->setAuthInfo($auth_info);
85 return $this->callAPI('GET','/support_entry');
86 }
87 public function sync_entry($params = [
88 "post_title" => null,
89 "post_content" => null,
90 "post_status" => null, # 0, 1
91 "post_permalink" => null,
92 "codoc_entry_code" => null,
93 ],$auth_info = ["usercode" => null, "token" => null]) {
94
95 $this->setAuthInfo($auth_info);
96
97 $post_content = $params['post_content'];
98 preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
99 // GUTENBERG で指定されたjson(記事�
100 )がない場合
101 if (!$matches) {
102 return;
103 }
104 // GUTENBERG で保存している�
105 容を取得
106 $codoc_info = json_decode($matches[1],true);
107 // codoc タグがない場合はなにもしない
108 //preg_match('/(<span +data-id="codoc-tag"[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
109 preg_match('/(<(?:span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:span|div)>)/',$post_content,$matches);
110 if (!$matches) {
111 return;
112 }
113 // TODO: split or html parse? HTMLがつながってる場合はおかしくなる
114 // classic(tinymce)版の場合p、もしくはdivにかこまれている
115 $end_tag_regex = '/<(?:div|p)>::CODOC_WP_END_PAYWALL::<\/(?:div|p)>/';
116 $before_splited = preg_split($end_tag_regex,$post_content);
117 $post_content = $before_splited[0];
118 $splited = preg_split('/(?:<(?:div|p)(?:[^>]+|)>|)<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->(?:<\/(?:div|p)>|)/s',$post_content);
119 $status = $params['post_status'];
120 # $body_free = '';
121 # $body_paywalled = '';
122 # if (count($splited) >= 2) {
123 #
124 # }
125 $binded_url = $params['post_permalink'];
126 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
127 if (isset($CODOC_SETTINGS['str_replace_binded_url_from']) and
128 isset($CODOC_SETTINGS['str_replace_binded_url_to']) and
129 $CODOC_SETTINGS['str_replace_binded_url_from']) {
130 $binded_url = str_replace(sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_from']),
131 sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_to']),
132 $binded_url);
133 }
134 $api_params = [
135 'title' => $params['post_title'],
136 'body_free' => $splited[0],
137 'body_paywalled' => $splited[1],
138 'status' => $status,
139 'binded_url' => $binded_url,
140 'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
141 'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
142 'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
143 'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
144 'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
145 'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
146 'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
147 'show_paywalled_support' => isset($codoc_info['showPaywalledSupport']) ? ($codoc_info['showPaywalledSupport'] ? 1 : 0) : 0,
148 'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
149 ];
150 $entryCode = $params['codoc_entry_code'];
151 $res = null;
152 if ($entryCode) {
153 $res = $this->callAPI('PUT','/entries/' . $entryCode ,$api_params);
154 } else {
155 $res = $this->callAPI('POST', '/entries', $api_params);
156 }
157 return $res;
158 }
159
160 function post_thumbnail( $params = [
161 "file_path" => null,
162 "boundary" => null,
163 "codoc_entry_code" => null,
164 ], $auth_info = ["usercode" => null, "token" => null] ) {
165
166 $this->setAuthInfo($auth_info);
167
168 $file_path = $params['file_path'];
169 $boundary = $params['boundary']; # ランダム変数24桁 wp_generate_password(24);
170 $res = null;
171 if (is_readable($file_path)) {
172 $name = 'file';
173
174 $payload = '';
175 $payload .= '--' . $boundary;
176 $payload .= "\r\n";
177 $payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
178 $payload .= "Content-Type: application/octet-stream\r\n";
179 $payload .= "Content-Transfer-Encoding: binary\r\n";
180 $payload .= "\r\n";
181 $payload .= file_get_contents( $file_path );
182 $payload .= "\r\n";
183
184 $payload .= '--' . $boundary . '--';
185
186 $entryCode = $params['codoc_entry_code'];
187 $res = $this->callAPI(
188 'POST',
189 '/entries/' . $entryCode . '/thumbnail',
190 $payload,
191 ['content-type' => 'multipart/form-data; boundary=' . $boundary]
192 );
193 }
194 return $res;
195 }
196
197 function reset_thumbnail( $params = [
198 "codoc_entry_code" => null,
199 ],$auth_info = ["usercode" => null, "token" => null] ) {
200
201 $this->setAuthInfo($auth_info);
202
203 $entryCode = $params['codoc_entry_code'];
204 $res = $this->callAPI(
205 'POST',
206 '/entries/' . $entryCode . '/thumbnail',
207 [ "reset" => 1 ]
208 );
209 return $res;
210 }
211
212 function filter_content( $params = [
213 "post_content" => null,
214 "preview" => null,
215 "codoc_entry_code" => null,
216 "codoc_settings" => null,
217 "is_amp_endpoint" => null,
218 "post_permalink" => null,
219 "codoc_support_entry_code" => null,
220 ]) {
221 $CODOC_SETTINGS = $params['codoc_settings'];
222
223 $has_codoc_tag = '/(<(span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:div|span)>)/';
224 $post_content = $params['post_content'];
225 // codoc タグがあるかどうか (202001:span -> div に変更)
226 preg_match($has_codoc_tag,$post_content,$matches);
227
228 $show_support_message = '';
229 if (isset($CODOC_SETTINGS['show_support_message'])) {
230 $show_support_message = $CODOC_SETTINGS['show_support_message'];
231 }
232 $show_support_categories = '';
233 if (isset($CODOC_SETTINGS['show_support_categories'])) {
234 $show_support_categories = $CODOC_SETTINGS['show_support_categories'];
235 }
236 $show_support_location = 'bottom';
237 if (isset($CODOC_SETTINGS['show_support_location'])) {
238 $show_support_location = $CODOC_SETTINGS['show_support_location'];
239 }
240
241 $show_support_entry = (is_single() && preg_grep("/(?:$show_support_categories)/",array_map( function($c) { return $c->name; },get_the_category(get_post()->ID))));
242 if (!$matches && ($support_entry_code = $params['codoc_support_entry_code']) && $show_support_entry) {
243 $support_tag = sprintf(
244 '<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>',
245 htmlspecialchars($show_support_message,ENT_QUOTES),
246 $support_entry_code,
247 $CODOC_SETTINGS['support_button_text'],
248 $CODOC_SETTINGS['show_like'],
249 $CODOC_SETTINGS['show_about_codoc'],
250 $CODOC_SETTINGS['show_powered_by']
251 );
252 $post_content = $show_support_location == 'bottom' ?
253 $post_content . $support_tag :
254 $support_tag . $post_content ;
255 }
256
257 // data-wp-plugin-ver が無いタグは分割しない
258 if (!$matches) {
259 return $post_content;
260 }
261
262 // codocタグで分割 (202001: gutenbergで直前のdivタグを削除)
263 $tag_regex = '/(?:<div(?:[^>]+|)>|)<(?:span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:span|div)>(?:<\/div>|)/';
264 $end_tag_regex = '/<(?:div|p)>::CODOC_WP_END_PAYWALL::<\/(?:div|p)>/';
265 if ( $params['preview'] ) {
266 $post_content = preg_replace($tag_regex,'<div class="codoc-continue">ここから上は無料で表示されます</div>',$post_content);
267 $post_content = preg_replace($end_tag_regex,'<div class="codoc-continue">ここから下は無料で表示されます</div>',$post_content);
268 return $post_content;
269 }
270 // codoc タグの前後で分ける
271 $before_splited = preg_split($end_tag_regex,$post_content);
272 $splited = preg_split($tag_regex,$before_splited[0]);
273 // codoc タグにID属性のentrycodeとdata-without-body(無料分を非表示)をつける
274 $entryCodeFormated = sprintf('"codoc-entry-%s" ',$params['codoc_entry_code']);
275
276 // 文言系の設定をつける
277 $tagAttributes = '';
278 if (isset($CODOC_SETTINGS['show_like']) and $CODOC_SETTINGS['show_like'] != 1) {
279 $tagAttributes = $tagAttributes . sprintf(' data-show-like="%s"',$CODOC_SETTINGS['show_like']);
280 }
281 if (isset($CODOC_SETTINGS['show_about_codoc']) and $CODOC_SETTINGS['show_about_codoc'] != 1) {
282 $tagAttributes = $tagAttributes . sprintf(' data-show-about-codoc="%s"',$CODOC_SETTINGS['show_about_codoc']);
283 }
284 if (isset($CODOC_SETTINGS['show_powered_by']) and $CODOC_SETTINGS['show_powered_by'] != 1) {
285 $tagAttributes = $tagAttributes . sprintf(' data-show-powered-by="%s"',$CODOC_SETTINGS['show_powered_by']);
286 }
287 if ($CODOC_SETTINGS['entry_button_text']) {
288 $tagAttributes = $tagAttributes . sprintf(' data-entry-button-text="%s"',$CODOC_SETTINGS['entry_button_text']);
289 }
290 if ($CODOC_SETTINGS['subscription_button_text']) {
291 $tagAttributes = $tagAttributes . sprintf(' data-subscription-button-text="%s"',$CODOC_SETTINGS['subscription_button_text']);
292 }
293 if ($CODOC_SETTINGS['support_button_text']) {
294 $tagAttributes = $tagAttributes . sprintf(' data-support-button-text="%s"',$CODOC_SETTINGS['support_button_text']);
295 }
296 if ($CODOC_SETTINGS['subscription_message']) {
297 $tagAttributes = $tagAttributes . sprintf(' data-subscription-message="%s"',$CODOC_SETTINGS['subscription_message']);
298 }
299 if ($CODOC_SETTINGS['support_message']) {
300 $tagAttributes = $tagAttributes . sprintf(' data-support-message="%s"',$CODOC_SETTINGS['support_message']);
301 }
302 if ($CODOC_SETTINGS['codoc_tag_attributes']) {
303 $tagAttributes = $tagAttributes . sprintf(' %s',$CODOC_SETTINGS['codoc_tag_attributes']);
304 }
305
306 $codoc_tag = preg_replace('/<((?:span|div)[^>]+)data-id="[^"]+"((?:[^>]+|))>/','<${1} ${2} data-without-body="1" id=' . $entryCodeFormated . $tagAttributes . ">", $matches[1]);
307 # THE THOR の page-lp.php が " " をけずるための対策
308 # "div class" -> "div class"
309 $codoc_tag = preg_replace('/div +class/','div class',$codoc_tag);
310
311 if ($params['is_amp_endpoint']) {
312 $format = preg_replace_callback('/(<(?:span|div)[^>]+>)((?:[^<>]+|))(<\/(?:span|div)>)/',function($matches) {
313 $format = $matches[1] . '<a href="%%s">%s</a>' . $matches[3];
314 return sprintf($format,($matches[2] ? $matches[2] : '続きを読む'));
315 },$codoc_tag);
316 $codoc_tag = sprintf($format,$params["post_permalink"]);
317 }
318
319 # タグの前後にHTMLを挿�
320
321 if (!isset($CODOC_SETTINGS['str_before_codoc_tag'])) {
322 $CODOC_SETTINGS['str_before_codoc_tag'] = '';
323 }
324 if (!isset($CODOC_SETTINGS['str_after_codoc_tag'])) {
325 $CODOC_SETTINGS['str_after_codoc_tag'] = '';
326 }
327 // 無料部分のみ表示
328 $post_content = $splited[0] . sprintf(
329 '%s<div class="wp-block-codoc-codoc-block">%s</div>%s',
330 $CODOC_SETTINGS['str_before_codoc_tag'],
331 $codoc_tag,
332 $CODOC_SETTINGS['str_after_codoc_tag']
333 );
334 // ::CODOC_WP_END_PAYWALL:: の後を足す
335 if (isset($before_splited[1]) and $before_splited[1]) {
336 $post_content .= $before_splited[1];
337 }
338 return $post_content;
339 }
340
341
342 }
343
344