add_settings();
}
$auth_info = get_option(CODOC_AUTHINFO_OPTION_NAME);
if (!$auth_info) {
return $this;
}
// データ同期 (save_postはis_adminで実行されないケースがある)
add_action( 'save_post', [$this,'save_post'], 20, 3 );
add_action( 'added_post_meta', [$this,'updated_post_meta'], 10, 3 );
add_action( 'updated_post_meta',[$this,'updated_post_meta'], 10, 3 );
add_action( 'deleted_post_meta',[$this,'deleted_post_meta'], 10, 4 );
if (is_admin()) {
// gutenberg
require_once 'src/init.php';
// tinymce
$this->add_mce();
add_action('wp_loaded', function() {
wp_localize_script('wordpress-cgb-block-js', 'OPTIONS', array(
'codoc_url' => CODOC_URL,
'codoc_usercode' => get_option(CODOC_USERCODE_OPTION_NAME),
'codoc_plugin_version' => CODOC_PLUGIN_VERSION,
));
});
return $this;
}
// codocのJS登録
add_action( 'wp_enqueue_scripts', function() {
wp_enqueue_script( 'codoc-injector-js', CODOC_URL . '/js/cms.js' );
});
// 登録したscriptタグに属性をつける
add_filter('script_loader_tag', [$this,'modifier_script_tag'],10,2);
// tinymce用のショートコード
add_shortcode('codoc', [$this, 'injector_shortcode']);
// paywall用の本文非表示化とcodocタグへの属性追加
add_filter('the_content',[$this,'the_content']);
return $this;
}
public function modifier_script_tag($tag,$handle) {
if($handle !== 'codoc-injector-js') {
return $tag;
}
$CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
$data_css = '';
if ($css_path = $CODOC_SETTINGS['css_path']) {
$data_css = sprintf(' data-css="%s" ',$css_path);
}
return str_replace(' src=', $data_css . ' defer src=', $tag);
}
public function injector_shortcode($atts) {
global $post;
ob_start();
require 'views/codoc-injector.php';
return ob_get_clean();
}
public function callAPI($method,$path,$body = [],$headers = []) {
$usercode = get_option(CODOC_USERCODE_OPTION_NAME);
$token = get_option(CODOC_TOKEN_OPTION_NAME);
$headers['X-CodocToken'] = $token;
$host = CODOC_URL;
$sslverify = true;
if (preg_match('/local/',CODOC_URL)) {
$sslverify = false;
$host = 'https://host.docker.internal';
}
$url = sprintf("%s/api/v1/cms/%s%s",$host,$usercode,$path);
$http = new WP_Http();
try {
$response = $http->request(
$url,
[
'sslverify' => $sslverify,
'method' => $method,
'timeout' => 10,
'headers' => $headers,
'body' => $body,
]
);
if ( is_wp_error($response) || $response['response']['code'] != 200 ) {
//何もしない
//var_dump( $response );
}
} catch(Exception $e) {
}
if (!is_wp_error($response) and
isset($response['body']) and
is_string($response['body']) and
is_array(json_decode($response['body'], true)) and
(json_last_error() == JSON_ERROR_NONE)) {
return json_decode($response['body']);
} else {
return null;
}
}
# settings / 設定関連
public function add_settings() {
global $CODOC_SETTINGS;
add_action( 'admin_menu' ,function(){
add_options_page(
'codoc の設定', //ページタイトル
'codoc', //設定メニューに表示されるメニュータイトル
'edit_users', //権限
'codoc', //設定ページのURL。options-general.php?page=codoc
function() {
echo '
';
echo '
';
}
);
});
add_action( "admin_init", function() {
// codocからの認証データ処理
if (isset($_GET['page']) and $_GET['page'] == 'codoc' and isset($_GET['fetch_token_key'])) {
$key = sanitize_text_field($_GET['fetch_token_key']);
$usercode = sanitize_text_field($_GET['usercode']);
update_option(CODOC_USERCODE_OPTION_NAME,$usercode);
$data = $this->callAPI('GET','/token',[ "fetch_token_key" => $key ]);
if ($data->status and $token = $data->token) {
update_option(CODOC_TOKEN_OPTION_NAME,$token);
$data = $this->callAPI('GET','');
if ($data->status and $user = $data->user) {
update_option(CODOC_AUTHINFO_OPTION_NAME,[
'email' => $user->email,
'name' => $user->name,
]);
}
#$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
#$current_url = preg_replace('/(.*)fetch_token_key.*/','${1}&codoc_auth_finished=1',$current_url);
add_settings_error( 'general', 'settings_updated', __( 'OKKK' ), 'success' );
$current_url = admin_url('options-general.php') . '?page=codoc&codoc_auth_finished=1';
wp_redirect( $current_url);
exit;
}
}
global $CODOC_USERCODE;
global $CODOC_SETTINGS;
global $CODOC_TOKEN;
global $CODOC_AUTHINFO;
$CODOC_USERCODE = get_option(CODOC_USERCODE_OPTION_NAME);
$CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
$CODOC_TOKEN = get_option(CODOC_TOKEN_OPTION_NAME);
$CODOC_AUTHINFO = get_option(CODOC_AUTHINFO_OPTION_NAME);
if( !$CODOC_SETTINGS ) {
//デフォルト値
$CODOC_SETTINGS = array(
'css_path' => '',
);
update_option( CODOC_SETTINGS_OPTION_NAME, $CODOC_SETTINGS );
}
if (!isset($CODOC_SETTINGS['str_replace_binded_url_from'])) {
$CODOC_SETTINGS['str_replace_binded_url_from'] = '';
}
if (!isset($CODOC_SETTINGS['str_replace_binded_url_to'])) {
$CODOC_SETTINGS['str_replace_binded_url_to'] = '';
}
add_settings_section(
'setting_section_id', // id
'codoc 設定ページ', // title
function (){}, // callback
'codoc' // page
);
// 認証がある場合
if ($CODOC_AUTHINFO) {
register_setting(
'codoc_option_group', // option group
CODOC_SETTINGS_OPTION_NAME // option name(DB)
);
add_settings_field(
'css_path', // id
'カスタマイズ用CSSパス', // title
function() {
global $CODOC_SETTINGS;
echo sprintf('',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['css_path']);
},
'codoc', //page
'setting_section_id' //Section
);
add_settings_field(
'str_replace_binded_url', // id
'codoc側に登録するパーマリンクを置換', // title
function() {
global $CODOC_SETTINGS;
echo sprintf('',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['str_replace_binded_url_from']);
echo ('を');
echo sprintf('',CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS['str_replace_binded_url_to']);
echo ('に変換');
},
'codoc', //page
'setting_section_id' //Section
);
register_setting(
'codoc_option_group', // option group
CODOC_USERCODE_OPTION_NAME
);
register_setting(
'codoc_option_group', // option group
CODOC_TOKEN_OPTION_NAME
);
if (isset($_GET['codoc_auth_finished']) and $_GET['codoc_auth_finished']) {
add_settings_error( 'general', 'settings_updated', __( 'codocの認証が完了しました' ), 'success' );
}
add_settings_field(
'codoc_auth',
'認証',
function() {
global $CODOC_USERCODE;
global $CODOC_TOKEN;
global $CODOC_AUTHINFO;
$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';";
echo sprintf('%s で認証済
',$CODOC_AUTHINFO['email']);
echo sprintf('',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
echo sprintf('',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
echo sprintf('認証を解除する
');
},
'codoc',
'setting_section_id'
);
}
// ない場合
if (!$CODOC_AUTHINFO and !isset($_GET['auth_by_myself'])) {
add_settings_field(
'codoc_auth',
'認証',
function() {
//$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$current_url = admin_url('options-general.php') . '?page=codoc';
$login_url = sprintf("location.href='%s'",CODOC_URL . '/me/token?from_wp=1&return_url=' . urlencode($current_url));
$register_url = sprintf("location.href='%s'",CODOC_URL . '/register?from_wp=1&return_url=' . urlencode($current_url));
// submitを消しておく
echo ('');
echo ('codocをWordPressでご利用いただくには認証が必要です。
');
echo sprintf('ユーザーコードとAPIトークンを直接入力することでも認証できます。
',$current_url);
echo sprintf('
',$login_url,$register_url);
},
'codoc',
'setting_section_id'
);
}
// ない場合かつ自分で認証する場合
if (!$CODOC_AUTHINFO and (isset($_GET['auth_by_myself']) and $_GET['auth_by_myself'])) {
register_setting(
'codoc_option_group', // option group
CODOC_USERCODE_OPTION_NAME
);
add_settings_field(
'codoc_usercode',
'ユーザーコード',
function() {
global $CODOC_USERCODE;
echo sprintf('',CODOC_USERCODE_OPTION_NAME,$CODOC_USERCODE);
},
'codoc',
'setting_section_id'
);
register_setting(
'codoc_option_group', // option group
CODOC_TOKEN_OPTION_NAME
);
add_settings_field(
'codoc_token',
'APIトークン',
function() {
global $CODOC_TOKEN;
echo sprintf('',CODOC_TOKEN_OPTION_NAME,$CODOC_TOKEN);
},
'codoc',
'setting_section_id'
);
}
// 認証情報を保存
add_action( 'update_option_' . CODOC_USERCODE_OPTION_NAME, function( $old_value, $new_value ) {
global $CODOC_RE_AUTHORIZE;
$CODOC_RE_AUTHORIZE = 1;
},9,2); // $hook, $function_to_add, $priority, $accepted_args
add_action( 'update_option_' . CODOC_TOKEN_OPTION_NAME, function( $old_value, $new_value ) {
global $CODOC_RE_AUTHORIZE;
$CODOC_RE_AUTHORIZE = 1;
},10,2);
add_action('updated_option',function(){
global $CODOC_RE_AUTHORIZE;
if ($CODOC_RE_AUTHORIZE) {
$data = $this->callAPI('GET','');
if ($data->status and $user = $data->user) {
update_option(CODOC_AUTHINFO_OPTION_NAME,[
'email' => $user->email,
'name' => $user->name,
]);
} else {
update_option(CODOC_AUTHINFO_OPTION_NAME,'');
}
}
});
});
}
public function add_mce() {
// Add Shortcode options in the WordPres visual editors
// wp_enqueue_script( 'codoc-editor-script', plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ ));
add_action( 'init', function() {
if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
return;
}
if ( get_user_option( 'rich_editing' ) == 'true' ) {
// プラグイン内で使うCSRF を生成
$path = plugins_url( 'codoc/src_mce/codoc-editor-onload.js', __DIR__ );
wp_enqueue_script( 'codoc-editor-onload', $path, array('jquery'), '', true );
// I just want to insert this global variables but i don't know how i can do it..
wp_localize_script(
'codoc-editor-onload',
'CODOCEDITOR',
array(
'action' => 'codoc_shortcodes',
'nonce' => wp_create_nonce( 'codoc_shortcodes' )
)
);
// ここでtinymceのプラグイン追加
wp_enqueue_style( 'codoc-admin-style', plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) );
add_filter( 'mce_external_plugins', function( $plugin_array ) {
$plugin_array['codoc'] = plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ );
return $plugin_array;
} );
add_filter( 'mce_buttons', function( $buttons ) {
array_push( $buttons, "|", "codoc" );
return $buttons;
} );
add_action( 'wp_ajax_codoc_shortcodes', function(){
check_ajax_referer( 'codoc_shortcodes' );
if ($usercode = sanitize_text_field($_GET['usercode'])) {
update_option('codoc_usercode',$usercode);
}
$usercode = get_option(CODOC_USERCODE_OPTION_NAME) ? get_option(CODOC_USERCODE_OPTION_NAME) : 'nocode';
$uri = CODOC_URL . '/api/v1/paywall/' . $usercode . '/entries';
if ($entrycode = sanitize_text_field($_GET['entrycode'])) {
$uri = $uri . '/' . $entrycode;
}
$args = preg_match('/local/',CODOC_URL) ? ['sslverify' => false ] : [];
$response = wp_remote_request( $uri, $args );
if ($response instanceof WP_Error) {
exit;
}
$response['body'] = json_decode($response['body'], true);
$entries = $response['body']['entries'];
require 'views/codoc-shortcodes-list.php';
wp_die();
} );
}
} );
}
public function save_post($post_ID,$post,$update) {
if (preg_match('/^(auto-draft|inherit)$/',$post->post_status)) {
return;
}
$post_content = $post->post_content;
preg_match('/wp:codoc\/codoc-block +?({.*})/',$post_content,$matches);
// GUTENBERG で指定されたjson(記事情報)がない場合
if (!$matches) {
return;
}
// GUTENBERG で保存している内容を取得
$codoc_info = json_decode($matches[1],true);
// codoc タグがない場合はなにもしない
preg_match('/(]+>(?:.+|)<\/span>)/',$post_content,$matches);
if (!$matches) {
return;
}
// TODO: split or html parse? HTMLがつながってる場合はおかしくなる
$splited = preg_split('/<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->/s',$post_content);
$status = $post->post_status == 'publish' ? 1 : 0;
# $body_free = '';
# $body_paywalled = '';
# if (count($splited) >= 2) {
#
# }
$binded_url = get_permalink($post_ID);
$CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME);
if (isset($CODOC_SETTINGS['str_replace_binded_url_from']) and
isset($CODOC_SETTINGS['str_replace_binded_url_to']) and
$CODOC_SETTINGS['str_replace_binded_url_from']) {
$binded_url = str_replace(sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_from']),
sanitize_text_field($CODOC_SETTINGS['str_replace_binded_url_to']),
$binded_url);
}
$params = [
'title' => $post->post_title,
'body_free' => $splited[0],
'body_paywalled' => $splited[1],
'status' => $status,
'binded_url' => $binded_url,
'show_price' => isset($codoc_info['showPrice']) ? ($codoc_info['showPrice'] ? 1 : 0) : 0,
'price' => isset($codoc_info['price']) ? $codoc_info['price'] : 100,
'limited' => isset($codoc_info['limited']) ? ($codoc_info['limited'] ? 1 : 0) : 0,
'limited_count' => isset($codoc_info['limitedCount']) ? $codoc_info['limitedCount'] : 1,
'affiliate_mode' => isset($codoc_info['affiliateMode']) ? ($codoc_info['affiliateMode'] ? 1 : 0) : 0,
'affiliate_rate' => isset($codoc_info['affiliateRate']) ? $codoc_info['affiliateRate'] : '0.0500',
'show_support' => isset($codoc_info['showSupport']) ? ($codoc_info['showSupport'] ? 1 : 0) : 0,
'subscriptions' => isset($codoc_info['subscriptions']) ? array_keys($codoc_info['subscriptions']) : [],
];
$entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
if ($entryCode) {
$res = $this->callAPI('PUT','/entries/' . $entryCode ,$params);
} else {
$res = $this->callAPI('POST', '/entries', $params);
if (is_object($res) and $res->status) {
update_post_meta($post_ID,'codoc_entry_code',$res->entry->code);
}
}
return true;
}
function updated_post_meta( $meta_ID, $post_ID, $meta_key ) {
if ($meta_key != '_thumbnail_id') {
return;
}
if ( has_post_thumbnail($post_ID) ) {
$attachment = wp_get_attachment_metadata( get_post_thumbnail_id($post_ID));
$upload_dir = wp_upload_dir();
$file_path = sprintf ('%s/%s',$upload_dir['basedir'],$attachment['file']);
if (is_readable($file_path)) {
$name = 'file';
$boundary = wp_generate_password(24);
$payload = '';
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . basename( $file_path ) . '"' . "\r\n";
$payload .= "Content-Type: application/octet-stream\r\n";
$payload .= "Content-Transfer-Encoding: binary\r\n";
$payload .= "\r\n";
$payload .= file_get_contents( $file_path );
$payload .= "\r\n";
$payload .= '--' . $boundary . '--';
$entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
$res = $this->callAPI(
'POST',
'/entries/' . $entryCode . '/thumbnail',
$payload,
['content-type' => 'multipart/form-data; boundary=' . $boundary]
);
}
}
}
function deleted_post_meta( $meta_ids, $post_ID, $meta_key,$meta_value ) {
if ($meta_key != '_thumbnail_id') {
return;
}
$entryCode = get_post_meta($post_ID,'codoc_entry_code',true);
$res = $this->callAPI(
'POST',
'/entries/' . $entryCode . '/thumbnail',
[ "reset" => 1 ]
);
}
function the_content( $post_content ) {
if ( is_single() && in_the_loop() && is_main_query() ) {
}
// codoc タグがあるかどうか
preg_match('/(]+>(?:.+|)<\/span>)/',$post_content,$matches);
// data-wp-plugin-ver が無いタグは分割しない
if (!$matches) {
return $post_content;
}
if ( is_preview() ) {
return $post_content;
}
// codoc タグの前後で分ける
$splited = preg_split('/(?:.+|)<\/span><\/div>/',$post_content);
//$splited = preg_split('/.*<\/div>/s',$post_content);
// codco タグにentrycodeをつける
$post = get_post();
$entryCode = sprintf('"codoc-entry-%s" ',get_post_meta($post->ID,'codoc_entry_code',true));
$codoc_tag = str_replace('span','span id=' . $entryCode, $matches[1]);
// codoc タグに属性をつける
$codoc_tag = str_replace('span','span data-without-body="1" ',$codoc_tag);
// 無料部分のみ表示
return $splited[0] . sprintf('
%s
',$codoc_tag);
}
}