PluginProbe
codoc / 0.3
codoc v0.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 / class-codoc.php

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

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