PluginProbe
codoc / 0.5
codoc v0.5
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.php

class-codoc.php in codoc 0.5, at class-codoc.php

529 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 final class Codoc {
4
5 public function __construct() {
6 if (is_admin()) {
7 // setting
8 $this->add_settings();
9 }
10 $auth_info = get_option(CODOC_AUTHINFO_OPTION_NAME);
11 if (!$auth_info) {
12 return $this;
13 }
14
15 // データ同期 (save_postはis_adminで実行されないケースがある)
16 add_action( 'save_post', [$this,'save_post'], 20, 3 );
17 add_action( 'added_post_meta', [$this,'updated_post_meta'], 10, 3 );
18 add_action( 'updated_post_meta',[$this,'updated_post_meta'], 10, 3 );
19 add_action( 'deleted_post_meta',[$this,'deleted_post_meta'], 10, 4 );
20
21 if (is_admin()) {
22 // gutenberg
23 require_once 'src/init.php';
24 // tinymce
25 $this->add_mce();
26 add_action('wp_loaded', function() {
27 wp_localize_script('wordpress-cgb-block-js', 'OPTIONS', array(
28 'codoc_url' => CODOC_URL,
29 'codoc_usercode' => get_option(CODOC_USERCODE_OPTION_NAME),
30 'codoc_plugin_version' => CODOC_PLUGIN_VERSION,
31 ));
32 });
33 return $this;
34 }
35
36 // codocのJS登録
37 add_action( 'wp_enqueue_scripts', function() {
38 wp_enqueue_script( 'codoc-injector-js', CODOC_URL . '/js/cms.js' );
39 });
40 // 登録したscriptタグに属性をつける
41 add_filter('script_loader_tag', [$this,'modifier_script_tag'],10,2);
42 // tinymce用のショートコード
43 add_shortcode('codoc', [$this, 'injector_shortcode']);
44
45 // paywall用の本文非表示化とcodocタグへの属性追加
46 add_filter('the_content',[$this,'the_content']);
47 return $this;
48 }
49
50 public function modifier_script_tag($tag,$handle) {
51 if($handle !== 'codoc-injector-js') {
52 return $tag;
53 }
54 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
55 $data_css = '';
56 if ($css_path = $CODOC_SETTINGS['css_path']) {
57 $data_css = sprintf(' data-css="%s" ',$css_path);
58 }
59 return str_replace(' src=', $data_css . ' defer src=', $tag);
60 }
61 public function injector_shortcode($atts) {
62 global $post;
63 ob_start();
64 require 'views/codoc-injector.php';
65 return ob_get_clean();
66 }
67 public function callAPI($method,$path,$body = [],$headers = []) {
68 $usercode = get_option(CODOC_USERCODE_OPTION_NAME);
69 $token = get_option(CODOC_TOKEN_OPTION_NAME);
70
71 $headers['X-CodocToken'] = $token;
72 $host = CODOC_URL;
73 $sslverify = true;
74
75 if (preg_match('/local/',CODOC_URL)) {
76 $sslverify = false;
77 $host = 'https://host.docker.internal';
78 }
79 $url = sprintf("%s/api/v1/cms/%s%s",$host,$usercode,$path);
80 $http = new WP_Http();
81 try {
82 $response = $http->request(
83 $url,
84 [
85 'sslverify' => $sslverify,
86 'method' => $method,
87 'timeout' => 10,
88 'headers' => $headers,
89 'body' => $body,
90 ]
91 );
92 if ( is_wp_error($response) || $response['response']['code'] != 200 ) {
93 //何もしない
94 //var_dump( $response );
95 }
96 } catch(Exception $e) {
97 }
98
99 if (!is_wp_error($response) and
100 isset($response['body']) and
101 is_string($response['body']) and
102 is_array(json_decode($response['body'], true)) and
103 (json_last_error() == JSON_ERROR_NONE)) {
104 return json_decode($response['body']);
105 } else {
106 return null;
107 }
108 }
109 # settings / 設定関連
110 public function add_settings() {
111 global $CODOC_SETTINGS;
112 add_action( 'admin_menu' ,function(){
113 add_options_page(
114 'codoc の設定', //ページタイトル
115 'codoc', //設定メニューに表示されるメニュータイトル
116 'edit_users', //権限
117 'codoc', //設定ページのURL。options-general.php?page=codoc
118 function() {
119 echo '<div clas="wrap">';
120 echo '<form method="post" action="options.php">';
121 settings_fields( 'codoc_option_group' );
122 do_settings_sections( 'codoc' );
123 submit_button(); // 送信ボタン
124 echo '</div>';
125 }
126 );
127 });
128
129 add_action( "admin_init", function() {
130 // codocからの認証データ処理
131 if (isset($_GET['page']) and $_GET['page'] == 'codoc' and isset($_GET['fetch_token_key'])) {
132 $key = sanitize_text_field($_GET['fetch_token_key']);
133 $usercode = sanitize_text_field($_GET['usercode']);
134 update_option(CODOC_USERCODE_OPTION_NAME,$usercode);
135 $data = $this->callAPI('GET','/token',[ "fetch_token_key" => $key ]);
136 if ($data->status and $token = $data->token) {
137 update_option(CODOC_TOKEN_OPTION_NAME,$token);
138 $data = $this->callAPI('GET','');
139 if ($data->status and $user = $data->user) {
140 update_option(CODOC_AUTHINFO_OPTION_NAME,[
141 'email' => $user->email,
142 'name' => $user->name,
143 ]);
144 }
145 #$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
146 #$current_url = preg_replace('/(.*)fetch_token_key.*/','${1}&codoc_auth_finished=1',$current_url);
147 add_settings_error( 'general', 'settings_updated', __( 'OKKK' ), 'success' );
148 $current_url = admin_url('options-general.php') . '?page=codoc&codoc_auth_finished=1';
149
150 wp_redirect( $current_url);
151 exit;
152 }
153 }
154
155 global $CODOC_USERCODE;
156 global $CODOC_SETTINGS;
157 global $CODOC_TOKEN;
158 global $CODOC_AUTHINFO;
159 $CODOC_USERCODE = get_option(CODOC_USERCODE_OPTION_NAME);
160 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
161 $CODOC_TOKEN = get_option(CODOC_TOKEN_OPTION_NAME);
162 $CODOC_AUTHINFO = get_option(CODOC_AUTHINFO_OPTION_NAME);
163 if( !$CODOC_SETTINGS ) {
164 //デフォルト値
165 $CODOC_SETTINGS = array(
166 'css_path' => '',
167 );
168 update_option( CODOC_SETTINGS_OPTION_NAME, $CODOC_SETTINGS );
169 }
170 if (!isset($CODOC_SETTINGS['str_replace_binded_url_from'])) {
171 $CODOC_SETTINGS['str_replace_binded_url_from'] = '';
172 }
173 if (!isset($CODOC_SETTINGS['str_replace_binded_url_to'])) {
174 $CODOC_SETTINGS['str_replace_binded_url_to'] = '';
175 }
176
177 add_settings_section(
178 'setting_section_id', // id
179 'codoc 設定ページ', // title
180 function (){}, // callback
181 'codoc' // page
182 );
183 // 認証がある場合
184 if ($CODOC_AUTHINFO) {
185 register_setting(
186 'codoc_option_group', // option group
187 CODOC_SETTINGS_OPTION_NAME // option name(DB)
188 );
189 add_settings_field(
190 'css_path', // id
191 'カスタマイズ用CSSパス', // title
192 function() {
193 global $CODOC_SETTINGS;
194 echo sprintf('<input type="text" name="%s[css_path]" value="%s">',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['css_path']);
195 },
196 'codoc', //page
197 'setting_section_id' //Section
198 );
199 add_settings_field(
200 'str_replace_binded_url', // id
201 'codoc側に登録するパーマリンクを置換', // title
202 function() {
203 global $CODOC_SETTINGS;
204 echo sprintf('<input type="text" name="%s[str_replace_binded_url_from]" value="%s">',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['str_replace_binded_url_from']);
205 echo ('');
206 echo sprintf('<input type="text" name="%s[str_replace_binded_url_to]" value="%s">',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['str_replace_binded_url_to']);
207 echo ('に変換');
208 },
209 'codoc', //page
210 'setting_section_id' //Section
211 );
212
213 register_setting(
214 'codoc_option_group', // option group
215 CODOC_USERCODE_OPTION_NAME
216 );
217 register_setting(
218 'codoc_option_group', // option group
219 CODOC_TOKEN_OPTION_NAME
220 );
221
222 if (isset($_GET['codoc_auth_finished']) and $_GET['codoc_auth_finished']) {
223 add_settings_error( 'general', 'settings_updated', __( 'codocの認証が完了しました' ), 'success' );
224 }
225
226 add_settings_field(
227 'codoc_auth',
228 '認証',
229 function() {
230 global $CODOC_USERCODE;
231 global $CODOC_TOKEN;
232 global $CODOC_AUTHINFO;
233 $script = "javascript:document.getElementById('codoc-usercode').value='';document.getElementById('codoc-token').value=' ';document.getElementById('codoc-auth-message').innerText='解除を完了するには変更を保存してください';document.getElementById('codoc-auth-message').color='red';";
234
235 echo sprintf('<p><font color="green" id="codoc-auth-message"><strong>%s</strong> で認証済</font></p>',$CODOC_AUTHINFO['email']);
236
237 echo sprintf('<input id="codoc-usercode" type="hidden" name="%s" value="%s">',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
238 echo sprintf('<input id="codoc-token" type="hidden" name="%s" value="%s">',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
239 echo sprintf('<p>認証を<a href="javascript:void(0);" onClick="' . $script . '">解除する</p>');
240 },
241 'codoc',
242 'setting_section_id'
243 );
244
245 }
246
247 // ない場合
248 if (!$CODOC_AUTHINFO and !isset($_GET['auth_by_myself'])) {
249 add_settings_field(
250 'codoc_auth',
251 '認証',
252 function() {
253
254 //$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
255 $current_url = admin_url('options-general.php') . '?page=codoc';
256 $login_url = sprintf("location.href='%s'",CODOC_URL . '/me/token?from_wp=1&return_url=' . urlencode($current_url));
257 $register_url = sprintf("location.href='%s'",CODOC_URL . '/register?from_wp=1&return_url=' . urlencode($current_url));
258 // submitを消しておく
259 echo ('<script type="text/javascript">window.onload=function(){document.getElementById(\'submit\').style.display = \'none\'}</script>');
260 echo ('codocをWordPressでご利用いただくには認証が�
261 要です。<br />');
262 echo sprintf('ユーザーコードとAPIトークンを<a href="%s&auth_by_myself=1">直接�
263 �力</a>することでも認証できます。<br /><br />',$current_url);
264 echo sprintf('<input type="button" class="button button-primary" value="ログインして認証" onClick="%s"> <input type="button" class="button button-primary" value="登録して認証" onClick="%s"><br /><br />',$login_url,$register_url);
265
266
267 },
268 'codoc',
269 'setting_section_id'
270 );
271 }
272 // ない場合かつ自分で認証する場合
273 if (!$CODOC_AUTHINFO and (isset($_GET['auth_by_myself']) and $_GET['auth_by_myself'])) {
274 register_setting(
275 'codoc_option_group', // option group
276 CODOC_USERCODE_OPTION_NAME
277 );
278 add_settings_field(
279 'codoc_usercode',
280 'ユーザーコード',
281 function() {
282 global $CODOC_USERCODE;
283 echo sprintf('<input type="text" name="%s" value="%s">',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
284 },
285 'codoc',
286 'setting_section_id'
287 );
288 register_setting(
289 'codoc_option_group', // option group
290 CODOC_TOKEN_OPTION_NAME
291 );
292 add_settings_field(
293 'codoc_token',
294 'APIトークン',
295 function() {
296 global $CODOC_TOKEN;
297 echo sprintf('<input type="text" name="%s" value="%s">',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
298 },
299 'codoc',
300 'setting_section_id'
301 );
302 }
303
304 // 認証�
305 報を保存
306 add_action( 'update_option_' . CODOC_USERCODE_OPTION_NAME, function( $old_value, $new_value ) {
307 global $CODOC_RE_AUTHORIZE;
308 $CODOC_RE_AUTHORIZE = 1;
309 },9,2); // $hook, $function_to_add, $priority, $accepted_args
310 add_action( 'update_option_' . CODOC_TOKEN_OPTION_NAME, function( $old_value, $new_value ) {
311 global $CODOC_RE_AUTHORIZE;
312 $CODOC_RE_AUTHORIZE = 1;
313 },10,2);
314 add_action('updated_option',function(){
315 global $CODOC_RE_AUTHORIZE;
316 if ($CODOC_RE_AUTHORIZE) {
317 $data = $this->callAPI('GET','');
318 if ($data->status and $user = $data->user) {
319 update_option(CODOC_AUTHINFO_OPTION_NAME,[
320 'email' => $user->email,
321 'name' => $user->name,
322 ]);
323 } else {
324 update_option(CODOC_AUTHINFO_OPTION_NAME,'');
325 }
326 }
327 });
328
329 });
330 }
331 public function add_mce() {
332 // Add Shortcode options in the WordPres visual editors
333 // wp_enqueue_script( 'codoc-editor-script', plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ ));
334 add_action( 'init', function() {
335 if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
336 return;
337 }
338 if ( get_user_option( 'rich_editing' ) == 'true' ) {
339 // プラグイン�
340 で使うCSRF を生成
341 $path = plugins_url( 'codoc/src_mce/codoc-editor-onload.js', __DIR__ );
342 wp_enqueue_script( 'codoc-editor-onload', $path, array('jquery'), '', true );
343 // I just want to insert this global variables but i don't know how i can do it..
344 wp_localize_script(
345 'codoc-editor-onload',
346 'CODOCEDITOR',
347 array(
348 'action' => 'codoc_shortcodes',
349 'nonce' => wp_create_nonce( 'codoc_shortcodes' )
350 )
351 );
352 // ここでtinymceのプラグイン追加
353 wp_enqueue_style( 'codoc-admin-style', plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) );
354 add_filter( 'mce_external_plugins', function( $plugin_array ) {
355 $plugin_array['codoc'] = plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ );
356 return $plugin_array;
357 } );
358 add_filter( 'mce_buttons', function( $buttons ) {
359 array_push( $buttons, "|", "codoc" );
360 return $buttons;
361 } );
362 add_action( 'wp_ajax_codoc_shortcodes', function(){
363 check_ajax_referer( 'codoc_shortcodes' );
364 if ($usercode = sanitize_text_field($_GET['usercode'])) {
365 update_option('codoc_usercode',$usercode);
366 }
367 $usercode = get_option(CODOC_USERCODE_OPTION_NAME) ? get_option(CODOC_USERCODE_OPTION_NAME) : 'nocode';
368 $uri = CODOC_URL . '/api/v1/paywall/' . $usercode . '/entries';
369 if ($entrycode = sanitize_text_field($_GET['entrycode'])) {
370 $uri = $uri . '/' . $entrycode;
371 }
372 $args = preg_match('/local/',CODOC_URL) ? ['sslverify' => false ] : [];
373 $response = wp_remote_request( $uri, $args );
374
375 if ($response instanceof WP_Error) {
376 exit;
377 }
378
379 $response['body'] = json_decode($response['body'], true);
380 $entries = $response['body']['entries'];
381
382 require 'views/codoc-shortcodes-list.php';
383
384 wp_die();
385 } );
386 }
387 } );
388 }
389 public function save_post($post_ID,$post,$update) {
390 if (preg_match('/^(auto-draft|inherit)$/',$post->post_status)) {
391 return;
392 }
393
394 $post_content = $post->post_content;
395 preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
396 // GUTENBERG で指定されたjson(記事�
397 )がない場合
398 if (!$matches) {
399 return;
400 }
401 // GUTENBERG で保存している�
402 容を取得
403 $codoc_info = json_decode($matches[1],true);
404 // codoc タグがない場合はなにもしない
405 preg_match('/(<span +data-id="codoc-tag"[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
406 if (!$matches) {
407 return;
408 }
409 // TODO: split or html parse? HTMLがつながってる場合はおかしくなる
410 $splited = preg_split('/<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->/s',$post_content);
411 $status = $post->post_status == 'publish' ? 1 : 0;
412 # $body_free = '';
413 # $body_paywalled = '';
414 # if (count($splited) >= 2) {
415 #
416 # }
417 $binded_url = get_permalink($post_ID);
418 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
419 if (isset($CODOC_SETTINGS['str_replace_binded_url_from']) and
420 isset($CODOC_SETTINGS['str_replace_binded_url_to']) and
421 $CODOC_SETTINGS['str_replace_binded_url_from']) {
422 $binded_url = str_replace(sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_from']),
423 sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_to']),
424 $binded_url);
425 }
426
427 $params = [
428 'title' => $post->post_title,
429 'body_free' => $splited[0],
430 'body_paywalled' => $splited[1],
431 'status' => $status,
432 'binded_url' => $binded_url,
433 'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
434 'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
435 'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
436 'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
437 'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
438 'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
439 'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
440 'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
441 ];
442 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
443 if ($entryCode) {
444 $res = $this->callAPI('PUT','/entries/' . $entryCode ,$params);
445 } else {
446 $res = $this->callAPI('POST', '/entries', $params);
447 if (is_object($res) and $res->status) {
448 update_post_meta($post_ID,'codoc_entry_code',$res->entry->code);
449 }
450 }
451 return true;
452 }
453 function updated_post_meta( $meta_ID, $post_ID, $meta_key ) {
454 if ($meta_key != '_thumbnail_id') {
455 return;
456 }
457 if ( has_post_thumbnail($post_ID) ) {
458 $attachment = wp_get_attachment_metadata( get_post_thumbnail_id($post_ID));
459 $upload_dir = wp_upload_dir();
460 $file_path = sprintf ('%s/%s',$upload_dir['basedir'],$attachment['file']);
461
462 if (is_readable($file_path)) {
463 $name = 'file';
464
465 $boundary = wp_generate_password(24);
466
467 $payload = '';
468 $payload .= '--' . $boundary;
469 $payload .= "\r\n";
470 $payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
471 $payload .= "Content-Type: application/octet-stream\r\n";
472 $payload .= "Content-Transfer-Encoding: binary\r\n";
473 $payload .= "\r\n";
474 $payload .= file_get_contents( $file_path );
475 $payload .= "\r\n";
476
477 $payload .= '--' . $boundary . '--';
478
479
480 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
481 $res = $this->callAPI(
482 'POST',
483 '/entries/' . $entryCode . '/thumbnail',
484 $payload,
485 ['content-type' => 'multipart/form-data; boundary=' . $boundary]
486 );
487 }
488 }
489 }
490 function deleted_post_meta( $meta_ids, $post_ID, $meta_key,$meta_value ) {
491 if ($meta_key != '_thumbnail_id') {
492 return;
493 }
494 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
495 $res = $this->callAPI(
496 'POST',
497 '/entries/' . $entryCode . '/thumbnail',
498 [ "reset" => 1 ]
499 );
500 }
501 function the_content( $post_content ) {
502 if ( is_single() && in_the_loop() && is_main_query() ) {
503 }
504 // codoc タグがあるかどうか
505 preg_match('/(<span +data-id="codoc-tag[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
506 // data-wp-plugin-ver が無いタグは分割しない
507 if (!$matches) {
508 return $post_content;
509 }
510 if ( is_preview() ) {
511 return $post_content;
512 }
513 // codoc タグの前後で分ける
514 $splited = preg_split('/<div><span data-id="codoc-tag" class="codoc-entries">(?:.+|)<\/span><\/div>/',$post_content);
515 //$splited = preg_split('/<div +class="wp-block-codoc-codoc-block">.*<\/div>/s',$post_content);
516 // codco タグにentrycodeをつける
517 $post = get_post();
518 $entryCode = sprintf('"codoc-entry-%s" ',get_post_meta($post->ID,'codoc_entry_code',true));
519 $codoc_tag = str_replace('span','span id=' . $entryCode, $matches[1]);
520 // codoc タグに属性をつける
521 $codoc_tag = str_replace('span','span data-without-body="1" ',$codoc_tag);
522 // 無料部分のみ表示
523 return $splited[0] . sprintf('<div class="wp-block-codoc-codoc-block">%s</div>',$codoc_tag);
524 }
525
526
527 }
528
529