PluginProbe
codoc / 0.7
codoc v0.7
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.7, at class-codoc.php

540 lines 19.4 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&return_url=' . urlencode($current_url));
257 $register_url = sprintf("location.href='%s'",CODOC_URL . '/register?from=wp&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 add_filter( 'plugin_action_links_' . plugin_basename( plugin_dir_path( __FILE__ ) . 'codoc' . '.php' ),
332 function( $links ) {
333 $setting_link = sprintf( '<a href="%s">%s</a>', esc_url( add_query_arg( 'page', 'codoc', admin_url( 'options-general.php' ) ) ), esc_html( '設定' ) );
334 array_unshift( $links, $setting_link );
335
336 return $links;
337 }
338 );
339
340 }
341 public function add_mce() {
342 // Add Shortcode options in the WordPres visual editors
343 // wp_enqueue_script( 'codoc-editor-script', plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ ));
344 add_action( 'init', function() {
345 if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
346 return;
347 }
348 if ( get_user_option( 'rich_editing' ) == 'true' ) {
349 // プラグイン�
350 で使うCSRF を生成
351 $path = plugins_url( 'codoc/src_mce/codoc-editor-onload.js', __DIR__ );
352 wp_enqueue_script( 'codoc-editor-onload', $path, array('jquery'), '', true );
353 // I just want to insert this global variables but i don't know how i can do it..
354 wp_localize_script(
355 'codoc-editor-onload',
356 'CODOCEDITOR',
357 array(
358 'action' => 'codoc_shortcodes',
359 'nonce' => wp_create_nonce( 'codoc_shortcodes' )
360 )
361 );
362 // ここでtinymceのプラグイン追加
363 wp_enqueue_style( 'codoc-admin-style', plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) );
364 add_filter( 'mce_external_plugins', function( $plugin_array ) {
365 $plugin_array['codoc'] = plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ );
366 return $plugin_array;
367 } );
368 add_filter( 'mce_buttons', function( $buttons ) {
369 array_push( $buttons, "|", "codoc" );
370 return $buttons;
371 } );
372 add_action( 'wp_ajax_codoc_shortcodes', function(){
373 check_ajax_referer( 'codoc_shortcodes' );
374 if ($usercode = sanitize_text_field($_GET['usercode'])) {
375 update_option('codoc_usercode',$usercode);
376 }
377 $usercode = get_option(CODOC_USERCODE_OPTION_NAME) ? get_option(CODOC_USERCODE_OPTION_NAME) : 'nocode';
378 $uri = CODOC_URL . '/api/v1/paywall/' . $usercode . '/entries';
379 if ($entrycode = sanitize_text_field($_GET['entrycode'])) {
380 $uri = $uri . '/' . $entrycode;
381 }
382 $args = preg_match('/local/',CODOC_URL) ? ['sslverify' => false ] : [];
383 $response = wp_remote_request( $uri, $args );
384
385 if ($response instanceof WP_Error) {
386 exit;
387 }
388
389 $response['body'] = json_decode($response['body'], true);
390 $entries = $response['body']['entries'];
391
392 require 'views/codoc-shortcodes-list.php';
393
394 wp_die();
395 } );
396 }
397 } );
398 }
399 public function save_post($post_ID,$post,$update) {
400 if (preg_match('/^(auto-draft|inherit)$/',$post->post_status)) {
401 return;
402 }
403
404 $post_content = $post->post_content;
405 preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
406 // GUTENBERG で指定されたjson(記事�
407 )がない場合
408 if (!$matches) {
409 return;
410 }
411 // GUTENBERG で保存している�
412 容を取得
413 $codoc_info = json_decode($matches[1],true);
414 // codoc タグがない場合はなにもしない
415 preg_match('/(<span +data-id="codoc-tag"[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
416 if (!$matches) {
417 return;
418 }
419 // TODO: split or html parse? HTMLがつながってる場合はおかしくなる
420 $splited = preg_split('/<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->/s',$post_content);
421 $status = $post->post_status == 'publish' ? 1 : 0;
422 # $body_free = '';
423 # $body_paywalled = '';
424 # if (count($splited) >= 2) {
425 #
426 # }
427 $binded_url = get_permalink($post_ID);
428 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
429 if (isset($CODOC_SETTINGS['str_replace_binded_url_from']) and
430 isset($CODOC_SETTINGS['str_replace_binded_url_to']) and
431 $CODOC_SETTINGS['str_replace_binded_url_from']) {
432 $binded_url = str_replace(sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_from']),
433 sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_to']),
434 $binded_url);
435 }
436
437 $params = [
438 'title' => $post->post_title,
439 'body_free' => $splited[0],
440 'body_paywalled' => $splited[1],
441 'status' => $status,
442 'binded_url' => $binded_url,
443 'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
444 'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
445 'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
446 'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
447 'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
448 'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
449 'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
450 'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
451 ];
452 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
453 if ($entryCode) {
454 $res = $this->callAPI('PUT','/entries/' . $entryCode ,$params);
455 } else {
456 $res = $this->callAPI('POST', '/entries', $params);
457 if (is_object($res) and $res->status) {
458 update_post_meta($post_ID,'codoc_entry_code',$res->entry->code);
459 }
460 }
461 return true;
462 }
463 function updated_post_meta( $meta_ID, $post_ID, $meta_key ) {
464 if ($meta_key != '_thumbnail_id') {
465 return;
466 }
467 if ( has_post_thumbnail($post_ID) ) {
468 $attachment = wp_get_attachment_metadata( get_post_thumbnail_id($post_ID));
469 $upload_dir = wp_upload_dir();
470 $file_path = sprintf ('%s/%s',$upload_dir['basedir'],$attachment['file']);
471
472 if (is_readable($file_path)) {
473 $name = 'file';
474
475 $boundary = wp_generate_password(24);
476
477 $payload = '';
478 $payload .= '--' . $boundary;
479 $payload .= "\r\n";
480 $payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
481 $payload .= "Content-Type: application/octet-stream\r\n";
482 $payload .= "Content-Transfer-Encoding: binary\r\n";
483 $payload .= "\r\n";
484 $payload .= file_get_contents( $file_path );
485 $payload .= "\r\n";
486
487 $payload .= '--' . $boundary . '--';
488
489
490 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
491 $res = $this->callAPI(
492 'POST',
493 '/entries/' . $entryCode . '/thumbnail',
494 $payload,
495 ['content-type' => 'multipart/form-data; boundary=' . $boundary]
496 );
497 }
498 }
499 }
500 function deleted_post_meta( $meta_ids, $post_ID, $meta_key,$meta_value ) {
501 if ($meta_key != '_thumbnail_id') {
502 return;
503 }
504 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
505 $res = $this->callAPI(
506 'POST',
507 '/entries/' . $entryCode . '/thumbnail',
508 [ "reset" => 1 ]
509 );
510 }
511 function the_content( $post_content ) {
512 if ( is_single() && in_the_loop() && is_main_query() ) {
513 }
514 // codoc タグがあるかどうか
515 preg_match('/(<span +data-id="codoc-tag[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
516 // data-wp-plugin-ver が無いタグは分割しない
517 if (!$matches) {
518 return $post_content;
519 }
520 $tag_regex = '/<div><span data-id="codoc-tag" class="codoc-entries">(?:.+|)<\/span><\/div>/';
521 if ( is_preview() ) {
522 $post_content = preg_replace($tag_regex,'<div class="codoc-continue">ここから上は無料で表示されます</div>',$post_content);
523 return $post_content;
524 }
525 // codoc タグの前後で分ける
526 $splited = preg_split($tag_regex,$post_content);
527 // codco タグにentrycodeをつける
528 $post = get_post();
529 $entryCode = sprintf('"codoc-entry-%s" ',get_post_meta($post->ID,'codoc_entry_code',true));
530 $codoc_tag = str_replace('span','span id=' . $entryCode, $matches[1]);
531 // codoc タグに属性をつける
532 $codoc_tag = str_replace('span','span data-without-body="1" ',$codoc_tag);
533 // 無料部分のみ表示
534 return $splited[0] . sprintf('<div class="wp-block-codoc-codoc-block">%s</div>',$codoc_tag);
535 }
536
537
538 }
539
540