add_settings(); } // usercode, token はadminページのみDBから取得する $this->util = new CodocUtil([ 'usercode' => null, 'token' => null, 'codoc_url' => $this->get_codoc_url() ]); # the_content フィルタを実行しない状態 $this->do_not_filter_the_content = false; // paywall用の本文非表示化とcodocタグへの属性追加 #$priority = 999999999; $priority = 100000; # フィルターは最後に実施する default 10 $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); if (isset($CODOC_SETTINGS["debug_params"])) { $params_decoded = json_decode($CODOC_SETTINGS["debug_params"],true); if (isset($params_decoded["the_content_filter_priority"])) { $priority = $params_decoded["the_content_filter_priority"]; } } // ショーココードの退避 if (isset($CODOC_SETTINGS['shortcode_evacuation']) and $CODOC_SETTINGS['shortcode_evacuation']) { add_filter('the_content',[$this,'the_content_shortcode_evacuations'],0); } add_filter('the_content',[$this,'the_content'],$priority); // 2021-09-24 the_content を利用しない場合は個別に呼び出ししてもらう add_filter('codoc_the_content',[$this,'the_content'],$priority); // 2020-07-25 excerpt対応 add_filter('excerpt_allowed_blocks',[$this,'excerpt_allowed_blocks']); // テーマが allowed_block_types_all で制限している場合に codoc ブロックを許可リストに追加 add_filter('allowed_block_types_all', [$this,'allowed_block_types_all'], 100, 2); $auth_info = get_option(CODOC_AUTHINFO_OPTION_NAME); if ($auth_info) { // データ同期 (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 ); // 文字数バリデーションエラーの管理画面通知 add_action( 'admin_notices', [$this,'show_validation_notices'] ); } global $pagenow; //管理画面でcodoc認証があり投稿画面の場合 if (is_admin() and $auth_info and preg_match('/^post/',$pagenow)) { // Gutenberg のサポートがない場合は何もしない if ( function_exists( 'register_block_type' ) ) { // gutenberg - init.php handles all block registration and script enqueuing require_once 'src/init.php'; } // tinymce $this->add_mce(); } elseif(is_admin() and $auth_info and preg_match('/^edit/',$pagenow)) { // 記事編集ページ } elseif(!is_admin()) { // ブログ画面 // codocのJS登録 add_action( 'wp_enqueue_scripts', function() { $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); $load_script_condition = ''; if (isset($CODOC_SETTINGS["debug_params"]) and $params_decoded = json_decode($CODOC_SETTINGS["debug_params"],true) and isset($params_decoded["load_script_condition"]) ) { $load_script_condition = $params_decoded["load_script_condition"]; } if ($load_script_condition == 'not_list_page') { // not_list_pageの場合はトップページ等でスクリプトをロードしない if (!(is_archive() or is_category() or is_home() or is_front_page())) { wp_enqueue_script( 'codoc-injector-js', $this->get_codoc_url() . '/js/cms.js' ); } } else { wp_enqueue_script( 'codoc-injector-js', $this->get_codoc_url() . '/js/cms.js' ); } }); //登録したscriptタグに属性をつける add_filter('script_loader_tag', [$this,'modifier_script_tag'],10,2); // tinymce用のショートコード add_shortcode('codoc', [$this, 'injector_shortcode']); // テーマをbodyにも反映 add_filter('body_class', function($classes) { $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); // デフォルトを変更 $css_path = 'rainbow-square'; if (isset($CODOC_SETTINGS["css_path"]) and $CODOC_SETTINGS["css_path"]) { $css_path = $CODOC_SETTINGS["css_path"]; } array_push($classes,sprintf( "codoc-theme-%s",$css_path)); return $classes; }); } return $this; } function codoc_load_textdomain() { load_plugin_textdomain('codoc', false, dirname(plugin_basename( __FILE__ )) . '/languages/'); } public function get_codoc_url() { $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); if (isset($CODOC_SETTINGS["debug_params"])) { $params_decoded = json_decode($CODOC_SETTINGS["debug_params"],true); if (isset($params_decoded["codoc_url"])) { return $params_decoded["codoc_url"]; } } return CODOC_URL; } 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); } // connect用パラメータ $connect_attributes = ''; if (isset($CODOC_SETTINGS["codoc_connect_code"])) { $connect_code = $CODOC_SETTINGS["codoc_connect_code"]; $connect_attributes = sprintf(' data-connect-code="%s"',$connect_code); $tag = preg_replace('/cms\.js/','cms-connect.js',$tag); } if (isset($CODOC_SETTINGS["codoc_connect_registration_mode"]) and $CODOC_SETTINGS["codoc_connect_registration_mode"]) { $connect_attributes = $connect_attributes . sprintf(' data-connect-registration-mode="%s"',$CODOC_SETTINGS["codoc_connect_registration_mode"]); } $usercode_attributes = ''; $user_code = get_option(CODOC_USERCODE_OPTION_NAME); if ($user_code) { $usercode_attributes = sprintf(' data-usercode="%s"',$user_code); } $setting_attributes = ''; if (isset($CODOC_SETTINGS['codoc_script_tag_attributes']) and $CODOC_SETTINGS['codoc_script_tag_attributes']) { $setting_attributes = $CODOC_SETTINGS['codoc_script_tag_attributes']; } //return str_replace(' src=', $data_css . ' defer src=', $tag); return preg_replace('/(src=[^>]+)/',' ${1} ' . $data_css . $connect_attributes . $usercode_attributes . $setting_attributes . ' defer',$tag); } public function injector_shortcode($atts) { global $post; ob_start(); require 'views/codoc-injector.php'; return ob_get_clean(); } # settings / 設定関連 public function add_settings() { global $CODOC_SETTINGS; add_action( 'admin_menu' ,function(){ add_options_page( __('codoc Settings','codoc'), //ページタイトル 'codoc', //設定メニューに表示されるメニュータイトル 'edit_users', //権限 'codoc', //設定ページのURL。options-general.php?page=codoc function() { echo '
| ' . esc_html(__('Display of likes','codoc')) . ' | ';
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_like'] == '1' ? "checked" : ""));
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_like'] == '0' ? "checked" : "")); echo ' |
|---|---|
| ' . esc_html(__('Display of PoweredBy','codoc')) . ' | ';
echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME));
echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME));
echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME));
if (isset($CODOC_AUTHINFO['account_is_pro']) and $CODOC_AUTHINFO['account_is_pro']) {
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_copyright'] == '1' ? "checked" : ""));
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_copyright'] == '0' ? "checked" : "")); } else { echo esc_html(__('Only PRO accounts can be disabled.','codoc')); } echo ' |
| ' . esc_html(__('"Purchase Article" button text','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['entry_button_text'])); echo ' |
| ' . esc_html(__('"Purchase Subscription" button text.','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['subscription_button_text'])); echo ' |
| ' . esc_html(__('Support button text','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['support_button_text'])); echo ' |
| ' . esc_html(__('Text for "Articles Included in Subscription".','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['subscription_message'])); echo ' |
| ' . esc_html(__('Text for support description','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['support_message'])); echo ' |
%s
%s
| ' . esc_html(__('Automatic insertion','codoc')) . ' | ';
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['always_show_support'] == '1' ? "checked" : ""));
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['always_show_support'] == '0' ? "checked" : "")); echo ' |
|---|---|
| '. esc_html(__('Position','codoc')) . ' | ';
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_support_location'] == 'top' ? "checked" : ""));
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_attr($CODOC_SETTINGS['show_support_location'] == 'bottom' ? "checked" : "")); echo ' |
| ' . esc_html(__('Description','codoc')) . ' | '; echo sprintf('',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_html($CODOC_SETTINGS['show_support_message'])); echo ' |
| ' . esc_html(__('Category names','codoc')) . ' | ';
echo sprintf(' ',esc_attr(CODOC_SETTINGS_OPTION_NAME),esc_html($CODOC_SETTINGS['show_support_categories'])); echo ' |
' . 'showPrice (bool: true), ' . 'price (int: 500), ' . 'limited (bool: false), ' . 'limitedCount (int: 10), ' . 'affiliateMode (bool: false), ' . 'affiliateRate (string: "0.0500"), ' . 'showSupport (bool: false), ' . 'showPaywalledSupport (bool: false), ' . 'statusLimited (bool: false), ' . 'subscriptions (object: {})' . '
'; }, 'codoc', //page 'setting_section_id' //Section ); add_settings_field( 'cretor_info', // id __('Creator\'s Information','codoc'), // title function() { global $CODOC_SETTINGS; global $CODOC_AUTHINFO; echo sprintf('',""); // 変更を保存時に常に同期するのでこの表示は必要ないがUI上保持しておく $script = "document.getElementById('codoc-update-creator-info-message').innerText='" . __("Please save changes to update the information.","codoc") . "';document.getElementById('codoc-update-creator-info-message').color='red';"; if (isset($CODOC_AUTHINFO['profile_image_url'])) { echo sprintf('%s %s %s
',esc_html($CODOC_AUTHINFO['name']),esc_html((isset($CODOC_AUTHINFO['account_is_pro']) and $CODOC_AUTHINFO['account_is_pro']) ? ' [PRO]' : ''),esc_html(isset($CODOC_AUTHINFO['country']) ? $CODOC_AUTHINFO['country'] : '' )); if ($connect_code = $CODOC_SETTINGS['codoc_connect_code']) { // Translators: %s is the integration code, and %s is additional information based on the registration mode. echo sprintf('' . esc_html(__('Extensions integration completed (Extensions code: %1$s) %2$s','codoc')) . '
', esc_html($connect_code), esc_html($CODOC_SETTINGS['codoc_connect_registration_mode'] == 'dedicated' ? __('Set the audience as a private account.','codoc') : '')); } echo sprintf('' . esc_html(__('Update creator\'s Information','codoc')) . '
'); echo ('' . esc_html(__('Please update each time if you change the logo or cover image on the codoc side.','codoc')) . '
'); }, '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', esc_html(__( 'codoc authentication has been completed.' ,'codoc'), 'success' )); } add_settings_field( 'codoc_auth', __('Authentication','codoc'), 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='" . __('Please save changes to complete the unbinding.','codoc') . "';document.getElementById('codoc-auth-message').color='red';"; // Translators: %s is the email address. echo sprintf('' . esc_html(__('Authorized as %s','codoc')) . '
',esc_attr($CODOC_AUTHINFO['email'])); echo sprintf('',esc_attr(CODOC_USERCODE_OPTION_NAME),esc_attr($CODOC_USERCODE)); echo sprintf('',esc_attr(CODOC_TOKEN_OPTION_NAME),esc_attr($CODOC_TOKEN)); echo sprintf('' . esc_html(__('Unbind authorization','codoc')) . '
'); }, 'codoc', 'setting_section_id' ); } // ない場合 if (!$CODOC_AUTHINFO and !isset($_GET['auth_by_myself'])) { add_settings_field( 'codoc_auth', __('Authentication','codoc'), function() { $theme = wp_get_theme(); $from = 'wp'; if ($theme->get('Name') === 'codoc') { $from = 'wp_codoc'; } //$current_url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $current_url = admin_url('options-general.php') . '?page=codoc'; $direct_url = sprintf("location.href='%s&auth_by_myself=1'",$current_url); $login_url = sprintf("location.href='%s'",$this->get_codoc_url() . '/me/token?from=' . $from . '&return_url=' . urlencode($current_url)); $register_url = sprintf("location.href='%s'",$this->get_codoc_url() . '/register?from=' . $from . '&return_url=' . urlencode($current_url)); // submitを消しておく echo (''); if (isset($_GET['confirm_token'])) { $confirm_url = sprintf("location.href='%s&_wpnonce=%s&fetch_token_key=%s&usercode=%s'",$current_url, wp_create_nonce('fetch_token_nonce'), esc_attr($_GET['fetch_token_key']), esc_attr($_GET['usercode'])); echo (esc_html(__('The authentication information has been obtained. Please click the confirmation button to complete the setup.','codoc')) . 'Cannot communicate with the codoc server. Please allow communication to https://codoc.jp in your firewall settings on the server or WordPress side.
'); } }, 'codoc', 'setting_section_id' ); } // ない場合かつ自分で認証する場合 if (!$CODOC_AUTHINFO and ( (isset($_GET['auth_by_myself']) and $_GET['auth_by_myself']) or (isset($_POST['auth_by_myself']) and $_POST['auth_by_myself']) )) { register_setting( 'codoc_option_group', // option group CODOC_USERCODE_OPTION_NAME ); register_setting( 'codoc_option_group', // option group CODOC_TOKEN_OPTION_NAME ); add_settings_field( 'codoc_usercode', 'ユーザーコード', function() { global $CODOC_USERCODE; echo ''; echo sprintf('',esc_attr(CODOC_USERCODE_OPTION_NAME),esc_attr($CODOC_USERCODE)); }, 'codoc', 'setting_section_id' ); add_settings_field( 'codoc_token', 'APIトークン', function() { global $CODOC_TOKEN; echo sprintf('',esc_attr(CODOC_TOKEN_OPTION_NAME),esc_attr($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('update_option_' . CODOC_SETTINGS_OPTION_NAME,function(){ $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); if (isset($CODOC_SETTINGS['always_show_support']) and $CODOC_SETTINGS['always_show_support']) { $data = $this->util->get_support_entry([],[ "usercode" => get_option(CODOC_USERCODE_OPTION_NAME), "token" => get_option(CODOC_TOKEN_OPTION_NAME), ]); if ($data and $data->status and $entry = $data->entry) { update_option(CODOC_SUPPORT_ENTRYCODE_OPTION_NAME,$entry->code); } else { update_option(CODOC_SUPPORT_ENTRYCODE_OPTION_NAME,''); } } elseif(isset($CODOC_SETTINGS['always_show_support']) and !$CODOC_SETTINGS['always_show_support']) { update_option(CODOC_SUPPORT_ENTRYCODE_OPTION_NAME,''); } }); add_action('updated_option',function(){ global $CODOC_RE_AUTHORIZE; if ($CODOC_RE_AUTHORIZE) { //$data = $this->callAPI('GET',''); $data = $this->util->get_user_info([],[ "usercode" => get_option(CODOC_USERCODE_OPTION_NAME), "token" => get_option(CODOC_TOKEN_OPTION_NAME), ]); if ($data->status and $user = $data->user) { $this->update_codoc_authinfo($user); } else { update_option(CODOC_AUTHINFO_OPTION_NAME,''); } } }); }); // プラグイン一覧に設定のリンクをいれる add_filter( 'plugin_action_links_' . plugin_basename( plugin_dir_path( __FILE__ ) . 'codoc' . '.php' ), function( $links ) { $setting_link = sprintf( '%s', esc_url( add_query_arg( 'page', 'codoc', admin_url( 'options-general.php' ) ) ), esc_html( __('Settings') ) ); array_unshift( $links, $setting_link ); return $links; } ); } public function add_mce() { add_action( 'admin_enqueue_scripts', function() { if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) { return; } $current_screen = get_current_screen(); if ( ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) || ( function_exists( 'is_gutenberg_page' ) && is_gutenberg_page() ) ) { // Gutenberg Editor // なにもしない } else { // tinymce 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.. $auth_info = get_option(CODOC_AUTHINFO_OPTION_NAME); $codoc_settings = get_option(CODOC_SETTINGS_OPTION_NAME); $block_defaults_raw = isset($codoc_settings['block_defaults']) ? $codoc_settings['block_defaults'] : ''; $block_defaults_decoded = json_decode($block_defaults_raw, true); $block_defaults = is_array($block_defaults_decoded) ? $block_defaults_decoded : new stdClass(); wp_localize_script( 'codoc-editor-onload', 'CODOCEDITOR', array( 'action' => 'codoc_shortcodes', 'nonce' => wp_create_nonce( 'codoc_shortcodes' ), 'codoc_url' => $this->get_codoc_url(), 'codoc_usercode' => get_option(CODOC_USERCODE_OPTION_NAME), 'codoc_plugin_version' => CODOC_PLUGIN_VERSION, 'codoc_sdk_path' => CODOC_SDK_PATH, 'codoc_account_is_pro' => isset($auth_info['account_is_pro']) ? $auth_info['account_is_pro'] : 0, 'codoc_currency_code' => isset($auth_info['currency_code']) ? $auth_info['currency_code'] : 0, 'codoc_currency_decimal_places' => isset($auth_info['currency_decimal_places']) ? $auth_info['currency_decimal_places'] : 0, 'codoc_block_defaults' => $block_defaults, ) ); // ここでtinymceのプラグイン追加 //wp_enqueue_style( 'codoc-admin-style', plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) ); //add_editor_style( plugins_url( 'codoc/src_mce/codoc-admin.css', __DIR__ ) ); wp_enqueue_style( 'codoc-admin-style', $this->get_codoc_url() . CODOC_SDK_PATH . '.tinymce.css?c=' . date('Ymd') ); add_editor_style( $this->get_codoc_url() . CODOC_SDK_PATH . '.tinymce.css' ); add_filter( 'mce_external_plugins', function( $plugin_array ) { //$plugin_array['codoc'] = plugins_url( 'codoc/src_mce/codoc-editor.js', __DIR__ ); $plugin_array['codoc'] = $this->get_codoc_url() . CODOC_SDK_PATH . '.tinymce.js?c=' . date('Ymd'); return $plugin_array; } ); add_filter( 'mce_buttons', function( $buttons ) { array_push( $buttons, "|", "codoc" ); return $buttons; } ); // 非SSL環境の場合、なぜかhttps -> httpsになってしまうので対策 // コメントタグが除去されることがあるらしいのでvalid_elementsに必要なタグを追加 (EXPERIMENTAL) add_filter( 'tiny_mce_before_init', function($settings) { $settings['external_plugins'] = preg_replace('/"codoc":"http:/','"codoc":"https:',$settings['external_plugins']); foreach (['valid_elements','extended_valid_elements'] as $valid_elements) { if (isset($settings[$valid_elements])) { $settings[$valid_elements] = $settings[$valid_elements] . ',div[*],p[*],img[*],--[*]'; } } $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); if (isset($CODOC_SETTINGS["debug_params"])) { $params_decoded = json_decode($CODOC_SETTINGS["debug_params"],true); if (isset($params_decoded["mce_valid_elements"])) { $settings['valid_elements'] = $params_decoded["mce_valid_elements"]; $settings['extended_valid_elements'] = $params_decoded["mce_valid_elements"]; } } return $settings; },1000000); } } } ); } function update_codoc_authinfo($user) { global $CODOC_SETTINGS; global $CODOC_AUTHINFO; if (property_exists($user,'connect_code') and $user->connect_code) { $CODOC_SETTINGS = get_option(CODOC_SETTINGS_OPTION_NAME); $CODOC_SETTINGS['codoc_connect_code'] = $user->connect_code; $CODOC_SETTINGS['codoc_connect_registration_mode'] = $user->connect_has_permission_dedicated_account ? 'dedicated' : ''; update_option(CODOC_SETTINGS_OPTION_NAME,$CODOC_SETTINGS); } return update_option(CODOC_AUTHINFO_OPTION_NAME,[ 'email' => $user->email, 'name' => $user->name, 'profile_image_url' => $user->profile_image_url, 'cover_image_url' => $user->cover_image_url, 'connect_code' => property_exists($user,'connect_code') ? $user->connect_code : '', 'connect_image_url' => property_exists($user,'connect_image_url') ? $user->connect_image_url : '', 'account_is_pro' => property_exists($user,'account_is_pro') ? $user->account_is_pro : '', 'created_at' => property_exists($user,'created_at') ? $user->created_at : 0, 'country' => property_exists($user,'country') ? $user->country : '', 'currency_code' => property_exists($user,'currency_code') ? $user->currency_code : '', 'currency_decimal_places' => property_exists($user,'currency_decimal_places') ? $user->currency_decimal_places : '', ]); $CODOC_AUTHINFO = get_option(CODOC_AUTHINFO_OPTION_NAME); return $CODOC_AUTHINFO; } // 保存用コンテンツにフィルターを実施する public function get_filtered_content($post_emulated) { // 記事ページであることをエミュレートしてフィルター実行 $post_backuped = null; if (isset($GLOBALS['post'])) { $post_backuped = $GLOBALS['post']; } $GLOBALS['post'] = $post_emulated; $wp_query_backuped = null; if (isset($GLOBALS['wp_query'])) { $wp_query_backuped = $GLOBALS['wp_query']; $wp_query = $GLOBALS['wp_query']; $wp_query->is_single = true; $wp_query->is_singular = true; # in_the_loop は記事ページでは通常有効っぽいので true指定 ex: wp_ulike $wp_query->in_the_loop = true; # これも追加しておく $wp_query->is_main_query = true; $wp_query->post = $post_emulated; $wp_query->queried_object = $post_emulated; $wp_query->queried_object_id = $post_emulated->ID; $GLOBALS['wp_query'] = $wp_query; } // $this->the_content でオリジナルを返してもらうため $this->do_not_filter_the_content = true; $content = preg_replace( '/ (\/)?wp:codoc\/codoc-block /',' \\1wptmp:codoc/codoc-block ', $post_emulated->post_content ); // post_metaに内容を保存し、無料パートにショートコードの退避をおこなう $codoc_settings = get_option(CODOC_SETTINGS_OPTION_NAME); if (isset($codoc_settings['shortcode_evacuation']) and $codoc_settings['shortcode_evacuation']) { $splited = preg_split('/\/wptmp:codoc\/codoc-block/s',$content); if (isset($splited[0]) and isset($splited[1])) { // すべてのショートコードを $match_all にいれる preg_match_all('/\[[^\[\]]+?\](.+\[\/[^\[\]]+?\])?/',$splited[1],$match_all); // ショートコードをURLエンコードしてdivタグの中にいれておく(後でmetaの中のショートコードと付け合せ) $replaced = preg_replace_callback('/\[[^\[\]]+?\](.+\[\/[^\[\]]+?\])?/',function($matches) { return sprintf ('', urlencode($matches[0])); },$splited[1]); // 0番目に配列で入っているのでそこを退避対象の配列とする $evacuations = $match_all[0]; // ショートコードの中身をタグに退避 $content = $splited[0] . '/wptmp:codoc/codoc-block' . $replaced; // 無料パートでショートコードを実行できるようにする update_post_meta($post_emulated->ID,'codoc_shortcode_evacuations',join('**codoc**',$evacuations)); } else { update_post_meta($post_emulated->id,'codoc_shortcode_evacuations',""); } } #$content = do_shortcode( $content ); $content_filtered = apply_filters( 'the_content', $content); $this->do_not_filter_the_content = false; $GLOBALS['post'] = $post_backuped; if ($wp_query_backuped) { $GLOBALS['wp_query'] = $wp_query_backuped; } $content_filtered = preg_replace( '/ (\/)?wptmp:codoc\/codoc-block /',' \\1wp:codoc/codoc-block ', $content_filtered ); return $content_filtered; } public function save_post($post_ID,$post,$update) { if (preg_match('/^(auto-draft|inherit)$/',$post->post_status)) { return; } $entryCode = get_post_meta($post_ID,'codoc_entry_code',true); $postId = get_post_meta($post_ID,'codoc_saved_post_id',true); // 保存されているIDと違う場合は破棄(duplicate pageなどでmeta情報をコピーされた可能性がある) if ($postId and $postId != $post_ID) { $entryCode = ''; } $codoc_settings = get_option(CODOC_SETTINGS_OPTION_NAME); $post_content = (isset($codoc_settings['do_not_filter_the_content']) and $codoc_settings['do_not_filter_the_content']) ? $post->post_content : $this->get_filtered_content($post); // codoc タグ(span/div または Gutenberg ブロック)が含まれていれば API側と統一した文字数検証を行う $has_codoc_tag = preg_match('/<(?:span|div)[^>]+data-id="codoc-tag"/', $post_content) || preg_match('/wp:codoc\/codoc-block/', $post_content); if ($has_codoc_tag) { // codoc タグ位置で free / paywalled を分割 $gutenberg_split = '/(?:<(?:div|p)(?:[^>]+|)>|)<\!-- +wp:codoc\/codoc-block .*<\!-- +\/wp:codoc\/codoc-block +-->(?:<\/(?:div|p)>|)/s'; $tag_split = '/<(?:span|div)[^>]+data-id="codoc-tag"(?:[^>]+|)>(?:.+|)<\/(?:span|div)>/'; $end_tag_regex = '/<(?:div|p)>::CODOC_WP_END_PAYWALL::<\/(?:div|p)>/'; $for_split = preg_split($end_tag_regex, $post_content); $for_split = $for_split[0]; if (preg_match('/wp:codoc\/codoc-block/', $for_split)) { $splited = preg_split($gutenberg_split, $for_split); } else { $splited = preg_split($tag_split, $for_split); } $body_free = isset($splited[0]) ? $splited[0] : ''; $body_paywalled = isset($splited[1]) ? $splited[1] : ''; $errors = $this->util->validate_entry_lengths([ 'title' => $post->post_title, 'body_free' => $body_free, 'body_paywalled' => $body_paywalled, 'binded_url' => get_permalink($post_ID), ]); if ($errors) { set_transient('codoc_entry_validation_errors', $errors, MINUTE_IN_SECONDS * 5); // 同期はスキップ return true; } } $res = $this->util->sync_entry([ "post_title" => $post->post_title, "post_content" => $post_content, // password が設定されてる場合は限定公開にする "post_status" => $post->post_status == 'publish' ? ($post->post_password ? 2 : 1) : 0, "post_permalink" => get_permalink($post_ID), "codoc_entry_code" => $entryCode, "codoc_settings" => $codoc_settings, ],[ "usercode" => get_option(CODOC_USERCODE_OPTION_NAME), "token" => get_option(CODOC_TOKEN_OPTION_NAME), ]); $prudent_update_post_meta_entry_code = null; if (isset($codoc_settings["debug_params"])) { $params_decoded = json_decode($codoc_settings["debug_params"],true); if (isset($params_decoded["prudent_update_post_meta_entry_code"])) { $prudent_update_post_meta_entry_code = $params_decoded["prudent_update_post_meta_entry_code"]; } } if ($prudent_update_post_meta_entry_code == 2) { error_log('CODOC:: ' . sprintf ("%s : %s : %s : %s", $post_ID, (is_object($res) ? "1" : 0),$res->status,$entryCode)); } if (is_object($res) and $res->status and !$entryCode) { // 20230222 https://stackoverflow.com/questions/26640785/update-post-meta-not-work-only-when-save-data-not-for-update if ($prudent_update_post_meta_entry_code) { add_post_meta($post_ID,'codoc_entry_code',$res->entry->code); add_post_meta($post_ID,'codoc_saved_post_id',$post_ID); } else { update_post_meta($post_ID,'codoc_entry_code',$res->entry->code); update_post_meta($post_ID,'codoc_saved_post_id',$post_ID); } } return true; } function updated_post_meta( $meta_ID, $post_ID, $meta_key ) { // スルーされてる場合は他のメタ情報更新のタイミングにサムネイルをアップロード $has_to_resend = get_post_meta($post_ID,'codoc_post_thumbnail_invoking_entry_code',true); if ($has_to_resend != 1 and $meta_key != '_thumbnail_id') { return; } if ( has_post_thumbnail($post_ID) ) { // 新規投稿の場合、タイミングによってはcodocEntryCodeが取得できないので一旦スルーする if (!get_post_meta($post_ID,'codoc_entry_code',true)) { update_post_meta($post_ID,'codoc_post_thumbnail_invoking_entry_code',1); return; } else { update_post_meta($post_ID,'codoc_post_thumbnail_invoking_entry_code',0); } $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']); return $this->util->post_thumbnail([ "file_path" => $file_path, "boundary" => wp_generate_password(24), "codoc_entry_code" => get_post_meta($post_ID,'codoc_entry_code',true), ],[ "usercode" => get_option(CODOC_USERCODE_OPTION_NAME), "token" => get_option(CODOC_TOKEN_OPTION_NAME), ]); } } function deleted_post_meta( $meta_ids, $post_ID, $meta_key,$meta_value ) { if ($meta_key != '_thumbnail_id') { return; } return $this->util->reset_thumbnail( ["codoc_entry_code" => get_post_meta($post_ID,'codoc_entry_code',true)], [ "usercode" => get_option(CODOC_USERCODE_OPTION_NAME), "token" => get_option(CODOC_TOKEN_OPTION_NAME), ] ); } // 退避されてるかどうかをmetaを使って確認し、無料エリアの一番最後にショートコードを追加 function the_content_shortcode_evacuations( $post_content ) { if ($this->do_not_filter_the_content) { return $post_content; } $post = get_post(); if (!$post) { return $post_content; } $evacuations_meta = get_post_meta($post->ID,'codoc_shortcode_evacuations',true); $evacuations = preg_split('/\*\*codoc\*\*/',$evacuations_meta); foreach ($evacuations as $evacuation) { $post_content = sprintf('', urlencode($evacuation),$evacuation) . $post_content; } return $post_content; } function the_content( $post_content ) { if ( is_single() && in_the_loop() && is_main_query() ) { } // get_filtered_content から do_not_filter_the_contentを有効にされるパターン // オプションの設定値の意味合い(他のフィルタを無視)とは違うため注意 if ($this->do_not_filter_the_content) { return $post_content; } $post = get_post(); // 20211215 null になる場合がある if (!$post) { return $post_content; } # is_amp で実装しているテンプレート用 $is_amp_endpoint = (function_exists('is_amp_endpoint') && is_amp_endpoint()) ? true : ((function_exists('is_amp') && is_amp()) ? true : false); return $this->util->filter_content([ "post_content" => $post_content, "preview" => is_preview(), "codoc_entry_code" => get_post_meta($post->ID,'codoc_entry_code',true), "codoc_settings" => get_option(CODOC_SETTINGS_OPTION_NAME), "is_amp_endpoint" => $is_amp_endpoint, "post_permalink" => get_permalink($post->ID), "codoc_support_entry_code" => get_option(CODOC_SUPPORT_ENTRYCODE_OPTION_NAME), ]); } function excerpt_allowed_blocks ($allowed_blocks) { if (is_array($allowed_blocks)) { array_push($allowed_blocks,'codoc/codoc-block'); } return $allowed_blocks; } function allowed_block_types_all ($allowed_block_types, $block_editor_context) { // テーマ等がブロックを制限していない場合(true = 全ブロック許可)はそのまま返す if ($allowed_block_types === true) { return $allowed_block_types; } // 配列で制限されている場合、codoc ブロックを追加 if (is_array($allowed_block_types) && !in_array('codoc/codoc-block', $allowed_block_types)) { $allowed_block_types[] = 'codoc/codoc-block'; } return $allowed_block_types; } function show_validation_notices() { $errors = get_transient('codoc_entry_validation_errors'); if (!$errors || !is_array($errors)) { return; } delete_transient('codoc_entry_validation_errors'); $header = __('codoc could not sync this entry due to length limits:', 'codoc'); echo '' . esc_html($header) . '
" . esc_html($value) . "
" . esc_html($tadv_message_for_install) . "
" . esc_html($tadv_message_for_options) . "