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

501 lines 17.6 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
171 add_settings_section(
172 'setting_section_id', // id
173 'codoc 設定ページ', // title
174 function (){}, // callback
175 'codoc' // page
176 );
177 // 認証がある場合
178 if ($CODOC_AUTHINFO) {
179 register_setting(
180 'codoc_option_group', // option group
181 CODOC_SETTINGS_OPTION_NAME // option name(DB)
182 );
183 add_settings_field(
184 'css_path', // id
185 'カスタマイズ用CSSパス:', // title
186 function() {
187 global $CODOC_SETTINGS;
188 echo sprintf('<input type="text" name="%s[css_path]" value="%s">',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['css_path']);
189 },
190 'codoc', //page
191 'setting_section_id' //Section
192 );
193
194 register_setting(
195 'codoc_option_group', // option group
196 CODOC_USERCODE_OPTION_NAME
197 );
198 register_setting(
199 'codoc_option_group', // option group
200 CODOC_TOKEN_OPTION_NAME
201 );
202
203 if (isset($_GET['codoc_auth_finished']) and $_GET['codoc_auth_finished']) {
204 add_settings_error( 'general', 'settings_updated', __( 'codocの認証が完了しました' ), 'success' );
205 }
206
207 add_settings_field(
208 'codoc_auth',
209 '認証',
210 function() {
211 global $CODOC_USERCODE;
212 global $CODOC_TOKEN;
213 global $CODOC_AUTHINFO;
214 $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';";
215
216 echo sprintf('<p><font color="green" id="codoc-auth-message"><strong>%s</strong> で認証済</font></p>',$CODOC_AUTHINFO['email']);
217
218 echo sprintf('<input id="codoc-usercode" type="hidden" name="%s" value="%s">',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
219 echo sprintf('<input id="codoc-token" type="hidden" name="%s" value="%s">',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
220 echo sprintf('<p>認証を<a href="javascript:void(0);" onClick="' . $script . '">解除する</p>');
221 },
222 'codoc',
223 'setting_section_id'
224 );
225
226 }
227
228 // ない場合
229 if (!$CODOC_AUTHINFO and !isset($_GET['auth_by_myself'])) {
230 add_settings_field(
231 'codoc_auth',
232 '認証',
233 function() {
234
235 //$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
236 $current_url = admin_url('options-general.php') . '?page=codoc';
237 $login_url = sprintf("location.href='%s'",CODOC_URL . '/me/token?from_wp=1&return_url=' . urlencode($current_url));
238 $register_url = sprintf("location.href='%s'",CODOC_URL . '/register?from_wp=1&return_url=' . urlencode($current_url));
239 // submitを消しておく
240 echo ('<script type="text/javascript">window.onload=function(){document.getElementById(\'submit\').style.display = \'none\'}</script>');
241 echo ('codocをWordPressでご利用いただくには認証が�
242 要です。<br />');
243 echo sprintf('ユーザーコードとAPIトークンを<a href="%s&auth_by_myself=1">直接�
244 �力</a>することでも認証できます。<br /><br />',$current_url);
245 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);
246
247
248 },
249 'codoc',
250 'setting_section_id'
251 );
252 }
253 // ない場合かつ自分で認証する場合
254 if (!$CODOC_AUTHINFO and (isset($_GET['auth_by_myself']) and $_GET['auth_by_myself'])) {
255 register_setting(
256 'codoc_option_group', // option group
257 CODOC_USERCODE_OPTION_NAME
258 );
259 add_settings_field(
260 'codoc_usercode',
261 'ユーザーコード',
262 function() {
263 global $CODOC_USERCODE;
264 echo sprintf('<input type="text" name="%s" value="%s">',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
265 },
266 'codoc',
267 'setting_section_id'
268 );
269 register_setting(
270 'codoc_option_group', // option group
271 CODOC_TOKEN_OPTION_NAME
272 );
273 add_settings_field(
274 'codoc_token',
275 'APIトークン',
276 function() {
277 global $CODOC_TOKEN;
278 echo sprintf('<input type="text" name="%s" value="%s">',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
279 },
280 'codoc',
281 'setting_section_id'
282 );
283 }
284
285 // 認証�
286 報を保存
287 add_action( 'update_option_' . CODOC_USERCODE_OPTION_NAME, function( $old_value, $new_value ) {
288 global $CODOC_RE_AUTHORIZE;
289 $CODOC_RE_AUTHORIZE = 1;
290 },9,2); // $hook, $function_to_add, $priority, $accepted_args
291 add_action( 'update_option_' . CODOC_TOKEN_OPTION_NAME, function( $old_value, $new_value ) {
292 global $CODOC_RE_AUTHORIZE;
293 $CODOC_RE_AUTHORIZE = 1;
294 },10,2);
295 add_action('updated_option',function(){
296 global $CODOC_RE_AUTHORIZE;
297 if ($CODOC_RE_AUTHORIZE) {
298 $data = $this->callAPI('GET','');
299 if ($data->status and $user = $data->user) {
300 update_option(CODOC_AUTHINFO_OPTION_NAME,[
301 'email' => $user->email,
302 'name' => $user->name,
303 ]);
304 } else {
305 update_option(CODOC_AUTHINFO_OPTION_NAME,'');
306 }
307 }
308 });
309
310 });
311 }
312 public function add_mce() {
313 // Add Shortcode options in the WordPres visual editors
314 // wp_enqueue_script( 'codoc-editor-script', plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ ));
315 add_action( 'init', function() {
316 if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
317 return;
318 }
319 if ( get_user_option( 'rich_editing' ) == 'true' ) {
320 // プラグイン�
321 で使うCSRF を生成
322 $path = plugins_url( 'codoc/src_mce/codoc-editor-onload.js', __DIR__ );
323 wp_enqueue_script( 'codoc-editor-onload', $path, array('jquery'), '', true );
324 // I just want to insert this global variables but i don't know how i can do it..
325 wp_localize_script(
326 'codoc-editor-onload',
327 'CODOCEDITOR',
328 array(
329 'action' => 'codoc_shortcodes',
330 'nonce' => wp_create_nonce( 'codoc_shortcodes' )
331 )
332 );
333 // ここでtinymceのプラグイン追加
334 wp_enqueue_style( 'codoc-admin-style', plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) );
335 add_filter( 'mce_external_plugins', function( $plugin_array ) {
336 $plugin_array['codoc'] = plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ );
337 return $plugin_array;
338 } );
339 add_filter( 'mce_buttons', function( $buttons ) {
340 array_push( $buttons, "|", "codoc" );
341 return $buttons;
342 } );
343 add_action( 'wp_ajax_codoc_shortcodes', function(){
344 check_ajax_referer( 'codoc_shortcodes' );
345 if ($usercode = sanitize_text_field($_GET['usercode'])) {
346 update_option('codoc_usercode',$usercode);
347 }
348 $usercode = get_option(CODOC_USERCODE_OPTION_NAME) ? get_option(CODOC_USERCODE_OPTION_NAME) : 'nocode';
349 $uri = CODOC_URL . '/api/v1/paywall/' . $usercode . '/entries';
350 if ($entrycode = sanitize_text_field($_GET['entrycode'])) {
351 $uri = $uri . '/' . $entrycode;
352 }
353 $args = preg_match('/local/',CODOC_URL) ? ['sslverify' => false ] : [];
354 $response = wp_remote_request( $uri, $args );
355
356 if ($response instanceof WP_Error) {
357 exit;
358 }
359
360 $response['body'] = json_decode($response['body'], true);
361 $entries = $response['body']['entries'];
362
363 require 'views/codoc-shortcodes-list.php';
364
365 wp_die();
366 } );
367 }
368 } );
369 }
370 public function save_post($post_ID,$post,$update) {
371 if (preg_match('/^(auto-draft|inherit)$/',$post->post_status)) {
372 return;
373 }
374
375 $post_content = $post->post_content;
376 preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
377 // GUTENBERG で指定されたjson(記事�
378 )がない場合
379 if (!$matches) {
380 return;
381 }
382 // GUTENBERG で保存している�
383 容を取得
384 $codoc_info = json_decode($matches[1],true);
385 // codoc タグがない場合はなにもしない
386 preg_match('/(<span +data-id="codoc-tag"[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
387 if (!$matches) {
388 return;
389 }
390 // TODO: split or html parse? HTMLがつながってる場合はおかしくなる
391 $splited = preg_split('/<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->/s',$post_content);
392 $status = $post->post_status == 'publish' ? 1 : 0;
393 # $body_free = '';
394 # $body_paywalled = '';
395 # if (count($splited) >= 2) {
396 #
397 # }
398
399 $params = [
400 'title' => $post->post_title,
401 'body_free' => $splited[0],
402 'body_paywalled' => $splited[1],
403 'status' => $status,
404 'binded_url' => get_permalink($post_ID),
405 'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
406 'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
407 'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
408 'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
409 'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
410 'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
411 'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
412 'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
413 ];
414 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
415 if ($entryCode) {
416 $res = $this->callAPI('PUT','/entries/' . $entryCode ,$params);
417 } else {
418 $res = $this->callAPI('POST', '/entries', $params);
419 if (is_object($res) and $res->status) {
420 update_post_meta($post_ID,'codoc_entry_code',$res->entry->code);
421 }
422 }
423 return true;
424 }
425 function updated_post_meta( $meta_ID, $post_ID, $meta_key ) {
426 if ($meta_key != '_thumbnail_id') {
427 return;
428 }
429 if ( has_post_thumbnail($post_ID) ) {
430 $attachment = wp_get_attachment_metadata( get_post_thumbnail_id($post_ID));
431 $upload_dir = wp_upload_dir();
432 $file_path = sprintf ('%s/%s',$upload_dir['basedir'],$attachment['file']);
433
434 if (is_readable($file_path)) {
435 $name = 'file';
436
437 $boundary = wp_generate_password(24);
438
439 $payload = '';
440 $payload .= '--' . $boundary;
441 $payload .= "\r\n";
442 $payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
443 $payload .= "Content-Type: application/octet-stream\r\n";
444 $payload .= "Content-Transfer-Encoding: binary\r\n";
445 $payload .= "\r\n";
446 $payload .= file_get_contents( $file_path );
447 $payload .= "\r\n";
448
449 $payload .= '--' . $boundary . '--';
450
451
452 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
453 $res = $this->callAPI(
454 'POST',
455 '/entries/' . $entryCode . '/thumbnail',
456 $payload,
457 ['content-type' => 'multipart/form-data; boundary=' . $boundary]
458 );
459 }
460 }
461 }
462 function deleted_post_meta( $meta_ids, $post_ID, $meta_key,$meta_value ) {
463 if ($meta_key != '_thumbnail_id') {
464 return;
465 }
466 $entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
467 $res = $this->callAPI(
468 'POST',
469 '/entries/' . $entryCode . '/thumbnail',
470 [ "reset" => 1 ]
471 );
472 }
473 function the_content( $post_content ) {
474 if ( is_single() && in_the_loop() && is_main_query() ) {
475 }
476 // codoc タグがあるかどうか
477 preg_match('/(<span +data-id="codoc-tag[^>]+>(?:.+|)<\/span>)/',$post_content,$matches);
478 // data-wp-plugin-ver が無いタグは分割しない
479 if (!$matches) {
480 return $post_content;
481 }
482 if ( is_preview() ) {
483 return $post_content;
484 }
485 // codoc タグの前後で分ける
486 $splited = preg_split('/<div><span data-id="codoc-tag" class="codoc-entries">(?:.+|)<\/span><\/div>/',$post_content);
487 //$splited = preg_split('/<div +class="wp-block-codoc-codoc-block">.*<\/div>/s',$post_content);
488 // codco タグにentrycodeをつける
489 $post = get_post();
490 $entryCode = sprintf('"codoc-entry-%s" ',get_post_meta($post->ID,'codoc_entry_code',true));
491 $codoc_tag = str_replace('span','span id=' . $entryCode, $matches[1]);
492 // codoc タグに属性をつける
493 $codoc_tag = str_replace('span','span data-without-body="1" ',$codoc_tag);
494 // 無料部分のみ表示
495 return $splited[0] . sprintf('<div class="wp-block-codoc-codoc-block">%s</div>',$codoc_tag);
496 }
497
498
499 }
500
501