「WordPress」の版間の差分

提供:GNU social JP Wiki
(Delete)
 
(同じ利用者による、間の30版が非表示)
4行目: 4行目:


WordPressの外観や挙動はPHPのプログラムを書いてカスタマイズできる。また、プラグイン機構を持ち、世界中の開発者によるプラグインを導入することで簡単にウェブサイトを拡張できる。
WordPressの外観や挙動はPHPのプログラムを書いてカスタマイズできる。また、プラグイン機構を持ち、世界中の開発者によるプラグインを導入することで簡単にウェブサイトを拡張できる。
* [https://developer.wordpress.org/coding-standards/wordpress-coding-standards/ WordPress Coding Standards – Coding Standards Handbook | Developer.WordPress.org]
* [https://developer.wordpress.org/ WordPress Developer Resources | Official WordPress Developer Resources | Developer.WordPress.org]


== Install ==
== Install ==
20行目: 23行目:


* [https://web.gnusocial.jp/post/2023/10/13/8867/ 報道: WordPressの公式ホスティングサービスWordPress.comのActivityPub対応]
* [https://web.gnusocial.jp/post/2023/10/13/8867/ 報道: WordPressの公式ホスティングサービスWordPress.comのActivityPub対応]
[https://ja.wordpress.org/plugins/activitypub/ ActivityPub – WordPress プラグイン | WordPress.org 日本語]
example.comというドメインで運営している場合、デフォルトでサイト全体を表す、example.com@example.comユーザーが追加される。
このユーザーは、サイトに登録済みの全ユーザーの更新を含む。


== Function ==
== Function ==
=== Account ===
==== ユーザー名の改名 ====
[https://www.wpbeginner.com/ja/wp-tutorials/how-to-change-your-wordpress-username/ WordPressユーザー名の正しい変更方法(3つの方法)]
管理画面からは直接変更できない。いくつか方法がある。
一番シンプルなのが、新規ユーザー作成後の削除。
==== Delete ====
[https://sbwinc.co.jp/wordpress-user-delete/ ワードプレスでユーザー削除する際の注意点「ミスると記事が消滅します」 | 株式会社ステップバイワーク]
アカウントの削除時には注意が必要。
削除時に以下の選択肢が表示される。
# Delete all content.
# Attribute all content to:
1を選ぶと本当に全部消える。2を選ぶのが無難。


=== Comment ===
=== Comment ===
32行目: 61行目:
このあたりの関数で定義されている。フィルターを挟むことで変更できる模様。
このあたりの関数で定義されている。フィルターを挟むことで変更できる模様。


== Language ==
=== PV ===
WordPressでPV数を表示させる方法がいくつかある。
 
* [https://nuko-blog.net/wordpress-populararticle-plugin/ 【WordPress】WordPressで人気記事を表示させるプラグイン5選! | 現役マーケターが教える未来のマーケターのためのマーケティングブログ | nukoblog]
* WP-PostViewsプラグイン
* WordPress Popular Postsプラグイン
* Post Views Counter: ([https://t-hr.net/p236/ 記事のアクセス数がわかるプラグインのPost Views Counter | たひろブログ])
 
WP-PostViewsプラグインのほうが柔軟性がある? ([https://kanae-design.the-day-mie.com/609/ WordPressで記事ランキングを設置するならWP-PostViewsが最適なのでは? | kanae-design-works]、[https://tech.kurojica.com/archives/11048/ 「WP-PostViews」と「WordPress Popular Posts」の違い | クロジカ])。
 
WordPressの分析プラグインはDBにアクセ格納するから重くなるらしい
 
* [https://www.tam-tam.co.jp/tipsnote/cms/post15202.html Google Analytics APIを使ってWordPressの記事をランキング表示させる方法 | Tips Note by TAM]
* [https://road-bike.net/archives/41056 WordPressのアクセスカウンターを変更しようとしたら思いの外苦労しました | ロードバイク好きの独り言]
* [https://blog.upshare.co.jp/2017/07/3660/ Jetpack(WordPress.com)の統計情報を使ってカスタマイズし放題な人気記事ランキングを表示する - 株式会社アップシェア ブログ]
* [https://wp-simplicity.com/suport/topic/%E3%81%86%E3%81%A1%E3%81%AFjetpack%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%A7pv%E8%A1%A8%E7%A4%BA%E3%81%AB%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%81%BE%E3%81%97%E3%81%9F/ うちはJetpackの機能でPV表示に切り替えました]
 
Jetpackの統計情報から閲覧数を取得表示することができる。これが一番手っ取り早い気がする。<syntaxhighlight lang="php">
<p>
<?php // 全体、月別、週別、日別のPV表示
  global $post;
  $views_all = 0;
  $views_monthly = 0;
  $views_weekly = 0;
  $views_daily = 0;
  //Jetpack利用時
  if (is_jetpack_stats_module_active()) {
    $jetpack_views = stats_get_csv( 'postviews', array('days' => -1, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_all = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 30, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_monthly = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 7, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_weekly = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 1, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_daily = $jetpack_views[0]['views'];
    }
  }
  echo '<span class="daily">日:<span class="pv-count">', $views_daily, '</span></span>';
  echo '<span class="weekly">週:<span class="pv-count">', $views_weekly, '</span></span>';
  echo '<span class="monthly">月:<span class="pv-count">', $views_monthly, '</span></span>';
  echo '<span class="all">全体:<span class="pv-count">', $views_all, '</span></span>';
?>
</p>
 
</syntaxhighlight>上記コードをウィジェットに貼り付けたらうまくいった。
 
=== Language ===
WordPressで多言語対応サイトも構築できる。
WordPressで多言語対応サイトも構築できる。


44行目: 126行目:
英語で情報発信できると、かなりの数のユーザーにアプローチできる。単に機械翻訳にするだけでも検討する価値はあるだろう。
英語で情報発信できると、かなりの数のユーザーにアプローチできる。単に機械翻訳にするだけでも検討する価値はあるだろう。


== 広告ブロッカー対策 ==
=== 広告ブロッカー対策 ===
出典: [https://dajya-ranger.com/wordpress/defend-site-content-for-wordpress/ 【WordPress編】広告ブロッカーからサイトコンテンツと収益を守る! | SEの良心]。
出典: [https://dajya-ranger.com/wordpress/defend-site-content-for-wordpress/ 【WordPress編】広告ブロッカーからサイトコンテンツと収益を守る! | SEの良心]。


50行目: 132行目:


「[https://web.gnusocial.jp/post/2024/01/03/9746/ プラグイン: WordPressの広告ブロッカー対策CHP Ads Block Detector | GNU social JP Web]」の通り、簡単にできた。
「[https://web.gnusocial.jp/post/2024/01/03/9746/ プラグイン: WordPressの広告ブロッカー対策CHP Ads Block Detector | GNU social JP Web]」の通り、簡単にできた。
=== Widget内でのPHP実行 ===
「[https://fox-wp.com/wordpress-widget-php-code-run/ WordPressのウィジェットでPHPコードを実行する方法 – FOXWP]」<syntaxhighlight lang="php">
function widget_text_exec_php( $widget_text ) {
    if( strpos( $widget_text, '<' . '?' ) !== false ) {
        ob_start();
        eval( '?>' . $widget_text );
        $widget_text = ob_get_contents();
        ob_end_clean();
    }
    return $widget_text;
}
add_filter( 'widget_text', 'widget_text_exec_php', 99 );
</syntaxhighlight>上記コードをfunction.phpに配置すると、テキストウィジェット内でPHPコード<?php ?>を実行できる模様。
=== Linkage ===
WordPressの記事・投稿を他のSNSに自動投稿する方法がいくつかある。
* [https://www.itti.jp/web-direction/5-best-plugins-to-automatically-post-articles-to-sns/ WordPress 記事をSNSへ自動投稿するベストなプラグイン5選 | 新宿のホームページ制作会社 ITTI(イッティ)]
* Jetpack Social connection: Jetpackの機能の一つ。Mastodon/Facebook Page/Instagram Businessアカウントが対象。FacebookとInstagramは個人アカウントはそもそも自動投稿できない。30日で30回までしか自動投稿できない。少々回数制限が厳しいかもしれない。他のプラグインを検討したほうがよさそう。
* GNU social Auto post: GNU socialへの自動投稿。
* NextScripts: Social Network Auto-Poster: Instagramだけ有料。
* Blog2Social: Instagramは有料。
* Nelio Content: 「[https://tcd-theme.com/2021/12/nelio-content.html Nelio Contentの使い方:Instagramと連携させる方法 | ワードプレステーマTCD]」。Bufferというサービスのアカウント経由でInstagramも可能。Buffer+Nelio Contentの組み合わせがベストに近い。制限の入ったX/Twitterも対応できそう。ただし、投稿画面で [Customize Timeline] の選択が必要。1クリックで3SNSに投稿連携できるなら、気になるものの許容できる手間。
=== There has been a critical error on this website. Please check your site admin email inbox for instructions. ===
プラグインを無効にしようと
[https://wordpress.org/documentation/article/faq-troubleshooting/#how-to-deactivate-all-plugins-when-not-able-to-access-the-administrative-menus How to deactivate all plugins when not able to access the administrative menus?]
=== Reference ===
Ref: [https://developer.wordpress.org/reference/ Reference | Developer.WordPress.org].
=== WPCode ===
Shortcodeの定義はくせがある。
[Insert Method]=[Shortcode] を選ぶと [wpcode id="10405"] のようなショートコードが定義される。これを [wpcode id="10405"][/wpcode]のようなブロックで使う。
Code Previewには、関数の本文を指定して、表示する場合echoなどで出力させる。
無料版だとshortcodeの名前を指定できない。
Auto Insertで自分で定義したらどうだろう?それで問題ない。
=== Media ===
WordPressはメディアをデフォルトで年付きベースのディレクトリーに保存する。これを変更するのは少々やっかい。
いくつかプラグインがあるのだが、FileBirdというプラグインががあって、デフォルトのアップロードディレクトリーはそのままで、内部的にディレクトリー的なものでカテゴリー分けできる。
これで管理するのが無難。
=== Permalink ===
==== 著者のパーマリンク ====
[https://wordpress.stackexchange.com/questions/77228/different-permalink-for-posts-and-authors Different permalink for posts and authors - WordPress Development Stack Exchange]
WordPressでは、authorのパーマリンクは、postの下に配置される。
<nowiki>http://domain.com/p/u/USERNAME</nowiki>
<nowiki>http://domain.com/p/POSTID</nowiki>
これがよろしくない。ユーザープロフィールのパーマリンクもこれになるから。
「[https://github.com/chrisguitarguy/WPSE-Plugins/blob/master/custom-author-base.php WPSE-Plugins/custom-author-base.php at master · chrisguitarguy/WPSE-Plugins · GitHub]」のプラグインで対応できる模様。
うーん。こちらのパーマリンクはうまく動作しなかった。
代わりに、「[https://wordpress.stackexchange.com/questions/82004/how-to-custom-change-author-base-without-this-front permalinks - How to custom change author base without $this->front? - WordPress Development Stack Exchange]」の以下のコードが動作した。
add_action('init', 'wpse82004_init');
function wpse82004_init()
{
    global $wp_rewrite;
    $wp_rewrite->author_base = 'user';
    $wp_rewrite->author_structure = '/' . $wp_rewrite->author_base . '/%author%';
}
ハードコードだが、うまく機能していて、変更することはないので、これでもいい。
==== パーマリンクの形式 ====
/post/投稿ID/の形式がシンプルでいい。
以前は/post/年/月/日/投稿ID/にしていたけど、長くなる。日付がパーマリンクにあると覚えやすいというのはあるのだけど。
長くなるし、日付があることで、情報が古いというイメージがあったり、いろいろある。記事を更新した場合も、ソートしたりするときに問題が。
年月日アーカイブはWordPressの機能でできるから、/post/投稿ID/が良いだろう。
== Plugin ==
Ref: [https://developer.wordpress.org/plugins/ Plugin Handbook | Developer.WordPress.org].
WordPresの拡張性のコア機能。
=== List ===
新しくWebサイトを始めるにあたって使いたいプラグインがある。
* ActivityPub
* FileBird
* Site Kit by Google
* WPCode Lite
==== 配布形式 ====
[https://plusers.jp/blog/wordpress-create-plugin すぐできる!WordPressの自作プラグインの作り方の基本を解説 | Plusers]
/wp-content/pluginsにファイルを直接アップロードする。か、ディレクトリーをzipに圧縮すれば、WordPressのプラグイン画面からアップロードできる。
=== Hook ===
Ref: [https://developer.wordpress.org/plugins/hooks/ Hooks – Plugin Handbook | Developer.WordPress.org].
フックはあるコードから別のコードに干渉するための仕組み。プラグインやテーマへの干渉のコア機能。拡張も可能。ActionとFilterの2種類がある。コールバックと一般的に呼ばれる関数を定義して引っ掛けて処理に干渉する。
* Action: WordPressの操作操作に、データの追加や変更を行う。内部的にデータを処理するので、何も返さない。
* Filter: WordPressコア機能の実行時にデータを変更する。データを受け取ってそれを次に渡す。
基本はFilterだと思う。Actionの用途がいまいちわからない。
==== Filter ====
Ref
* [https://developer.wordpress.org/plugins/hooks/filters/ Filters – Plugin Handbook | Developer.WordPress.org]
* [https://developer.wordpress.org/reference/functions/remove_filter/ remove_filter() – Function | Developer.WordPress.org]
add_filter/remove_filter
=== shortcode ===
Ref:
* [https://codex.wordpress.org/Shortcode Shortcode « WordPress Codex]
* [https://codex.wordpress.org/Shortcode_API Shortcode API « WordPress Codex]
* [https://www.webdesignleaves.com/pr/wp/wp_shortcode.html WordPress ショートコードの作成]
WordPressにはショートコードというのがある。角括弧 [shortcode][/shortcode] のような形式。本来ならHTML/JavaScriptしか使えない投稿本文に、PHP側の処理を仕込める。
新規作成する場合、書式がだいたい決まっている。<syntaxhighlight lang="php">
    function callback_function($atts, $content = null, $tag ) {
      extract(shortcode_atts(array(
        //属性
        'パラメータ1' => 'デフォルトの値1',
        'パラメータ2' => 'デフォルトの値2',
        ・・・
      ), $atts));
      //ショートコードの処理(動作)の記述
      return $value;
    }
    add_shortcode('my_shortcode', 'callback_function');
</syntaxhighlight>こえrでmy_shortcodeというショートコードが使用可能になる。
==== shortcode_atts ====
* [https://developer.wordpress.org/reference/functions/shortcode_atts/ shortcode_atts() – Function | Developer.WordPress.org]
* [https://www.webdesignleaves.com/pr/wp/wp_shortcode.html WordPress ショートコードの作成]
shortcode_atts( array $pairs, array $atts, string $shortcode = ” ): array
ユーザーが指定した属性と、使用可能な属性のデフォルト値を結合する。使用不能な属性を無視してくれる。
* $pairs: 使用可能な属性とそのデフォルト値。
* $atts: ショートコードでユーザーが指定した属性。
* $shortcode: ショートコードの名前。これを指定するとshortcode_atts_$shortcode フィルターで外部から属性をフィルターできる。通常は使わない。
== Paid Memberships Pro ==
== Paid Memberships Pro ==
=== About ===
PMPro。有料会員サービスを実現するプラグイン。
PMPro。有料会員サービスを実現するプラグイン。


=== Single ===
* [https://www.paidmembershipspro.com/documentation/advanced/ Advanced Developer Topics: Security, Caching, Redirection & More]
単体記事の販売には工夫が必要。
* [https://www.paidmembershipspro.com/hooks-filters/ Paid Membership Pro Action and Filter Hooks]
* [https://github.com/strangerstudios/paid-memberships-pro/tree/master/includes paid-memberships-pro/includes at master · strangerstudios/paid-memberships-pro]


* [https://www.paidmembershipspro.com/paid-newsletters/ Sell Paid Newsletters on WordPress]
ソースコード内のincludes配下の関数は自分でも使用可能。
* [https://www.paidmembershipspro.com/sell-single-courses-learndash-paid-memberships-pro/ Sell Single Courses using LearnDash and PMPro]
 
* [https://wordpress.org/plugins/pmpro-woocommerce/ Paid Memberships Pro Integration with WooCommerce – WordPress plugin | WordPress.org]
=== Free ===
* [https://flyplugins.com/paid-memberships-pro-courses/ Paid Memberships Pro for Selling Courses]
PMProは基本的に無料で使える模様 ([https://www.paidmembershipspro.com/free/ PMPro: Free WordPress Membership Plugin])。サポートを販売している扱いの模様。ログアウトしていないと表示されない。


WooCommerceと連携したり、PMProの有料プラグインを使うとか。他にも方法を以前調査したの後日追記する。
「[https://github.com/strangerstudios Stranger Studios]」がGitHubのリポジトリー。ここに全部のアドオンがある。ここからzipファイル類をダウンロードすれば使える。ただし、一部のプラグインは開発者の経験が必要なため、ライセンスキーの購入をsupportとして販売している。開発経験が一切ない人にはGitHubからのインストールもけっこう面倒くさいからそれでうまくGPLの条件を満たしているのだと思われる。


理想としては、単品販売と、会員を両立したい。2個以上買うなら会員のほうがいいみたいな。
実行自体はライセンスの有無によらず可能。ただし、ライセンスの有無でStripeの決済手数料が変わる。


=== Style ===
「[https://profiles.wordpress.org/paidmembershipspro/ Paid Memberships Pro (@paidmembershipspro) – WordPress user profile | WordPress.org]」でも公開しているが、これは全部ではない。サードパーティープラグインとの連携用が大半。
「[https://www.paidmembershipspro.com/customizing-the-message-for-non-members-on-membership-protected-content/ Custom Message for Non-Members on Protected Content]」でペイウォールの表示内容・スタイルを制御できる。


=== 金額変更 ===
=== 金額変更 ===
81行目: 324行目:


既存会員に対しては、更新ではなく、期限を設けて強制的に一度退会させるのがいい。
既存会員に対しては、更新ではなく、期限を設けて強制的に一度退会させるのがいい。
=== Restriction ===
==== membership short code ====
Ref:
* [https://www.paidmembershipspro.com/forums/topic/hide-bottom-register-form-when-it-has-membership-code-block/#post-545667 Hide bottom register form when it has membership code block]
* [https://www.paidmembershipspro.com/about-excerpts-and-using-the-read-more-tag-for-posts-and-pages/#h-level-up-your-excerpts-by-using-the-membership-shortcode-or-block Using the "Read More" Block and Excerpts for Pages and Posts]
* [https://www.paidmembershipspro.com/documentation/content-controls/with-shortcodes/ Restrict Content With a Shortcode]
* Source: [https://github.com/strangerstudios/paid-memberships-pro/blob/dev/shortcodes/membership.php paid-memberships-pro/shortcodes/membership.php at dev · strangerstudios/paid-memberships-pro]
PMProの基本的なコンテンツ制限の概念がある。
基本は投稿全体を非表示で、excerptで冒頭部分を一部表示これが基本。membershipショートコードはこの逆で、基本全表示で一部だけ非表示。
そもそも仕組みが違う。
だから、カテゴリーで管理していて、一部だけ非表示にしたかったら、末尾にmoreブロックを配置して、membeshipショートコードも使う必要がある。二重に使わないといけない。けっこう面倒くさい。
「[https://www.paidmembershipspro.com/customizing-the-message-for-non-members-on-membership-protected-content/ Custom Message for Non-Members on Protected Content]」がメッセージの変更方法。ただ、制限のロジックを変更できるわけではない。別のフィルターだと思う。
ソースコードを参考に自分で実装するしかないだろう。
==== message ====
「[https://www.paidmembershipspro.com/customizing-the-message-for-non-members-on-membership-protected-content/ Custom Message for Non-Members on Protected Content]」に基本的な表示内容やスタイルの設定方法がある。
<nowiki><div class="pmpro_content_message"></nowiki>
//custom message here
<nowiki></div></nowiki>
表示部分は上記要素になるのでこのクラスでスタイルをあてる。<syntaxhighlight lang="css">
.pmpro_content_message {
background: #F1F1F1;
margin: 0 auto;
max-width: 700px;
padding: 15px;
}
</syntaxhighlight>他に以下のフィルターが該当するメッセージ表示。
* add_filter( 'pmpro_non_member_text_filter', 'my_pmpro_non_member_text_filter', 5 );
* add_filter( 'pmpro_not_logged_in_text_filter', 'my_pmpro_not_logged_in_text_filter', 5 );
例えば、会員限定の文字数表示などをしたければ、自前でやるしかない。基本は自分で上記フィルターで上書きするのがよい。
例<syntaxhighlight lang="php">
function my_pmpro_non_member_text_filter( $text ) {
global $post, $post_membership_levels_names;
$count = mb_strlen( $post->post_content, 'UTF-8' ) - mb_strlen( get_the_excerpt(), 'UTF-8' );
$access = pmpro_has_membership_access( $post->ID, null, true );
$text = "<p>残り{$count}文字。続きは" . implode( '/', $access[2] ) . '会員限定。</p><p>Free=0/Bronze=220/Silver=1100/Gold=2200円。</p>'
. '<p><a href="https://web.gnusocial.jp/member/level/">会員登録</a>/'
. '<a href="//web.gnusocial.jp/member/login/">ログイン</a> (<a href="//web.gnusocial.jp/about/member/">About Member</a>)。</p>';
return $text;
}
add_filter( 'pmpro_non_member_text_filter', 'my_pmpro_non_member_text_filter', 5 );
add_filter( 'pmpro_not_logged_in_text_filter', 'my_pmpro_non_member_text_filter', 5 );
</syntaxhighlight>
==== Style ====
「[https://www.paidmembershipspro.com/customizing-the-message-for-non-members-on-membership-protected-content/ Custom Message for Non-Members on Protected Content]」でペイウォールの表示内容・スタイルを制御できる。
ペイウォール (.pmpro_content_message) のスタイルは会員登録の誘発に重要。
* [https://note.com/ririkodiary/n/n74cb67fecd7f 自分だけの強みを見つけて一生働く選択を〜ミドルエイジの生き方を見つめ直す〜|暮らしのつづり帖/梨田莉利子]
* [https://yoikoarinoshinya.hateblo.jp/entry/wakate-geinin 僕の若手時代の悪行。 - 有野晋哉(よゐこ)個人ブログ]
有名サービスの例は上記。登録・購入ボタンを大きく押しやすくしている。a要素の他button要素でも実装されている。ここはいろいろ考えてもいいかもしれない。
==== Category ====
membershipショートコードやAddon Packagesではカテゴリーやタグでの会員限定に対応していない。これがちょっと困る。既存のカテゴリー、タグでの会員対応の把握方法を確認する。
includes/contents.phpのpmpro_has_membership_accessのコードが参考になる。<syntaxhighlight lang="php">
if(isset($mypost->post_type) && $mypost->post_type == "post")
{
// Get the categories for this post.
$post_terms = wp_get_post_categories( $mypost->ID );
// Get the tags for this post.
$post_terms = array_merge( $post_terms, wp_get_post_tags( $mypost->ID, array('fields' => 'ids' ) ) );
if( ! $post_terms )
{
//just check for entries in the memberships_pages table
$sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
}
else
{
//are any of the post categories associated with membership levels? also check the memberships_pages table
$sqlQuery = "(SELECT m.id, m.name FROM $wpdb->pmpro_memberships_categories mc LEFT JOIN $wpdb->pmpro_membership_levels m ON mc.membership_id = m.id WHERE mc.category_id IN(" . implode(",", array_map( 'intval', $post_terms ) ) . ") AND m.id IS NOT NULL) UNION (SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "')";
}
}
else
{
//are any membership levels associated with this page?
$sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
}
    $post_membership_levels = $wpdb->get_results($sqlQuery);
</syntaxhighlight>普通にSQLで取得している。このへんのコードを流用すれば対応できる気はする。ただ、ちょっと面倒くさい。
=== Analytics ===
PMProの流入元の記事を分析・特定する方法がある。
* [https://www.paidmembershipspro.com/membership-site-conversions-in-google-analytics-4/ How to Set Up GA4 Membership Site Conversion Events]
* [https://www.paidmembershipspro.com/add-ons/google-analytics/ Google Analytics Integration Add On Plugin]
GA4を使った一般的なサイト分析になる。有料プラグインでもできる。
=== Sell ===
==== Single ====
* [https://www.paidmembershipspro.com/add-ons/pmpro-purchase-access-to-a-single-page/ Addon Packages Add On Plugin for PMPro]
* [https://www.paidmembershipspro.com/add-ons/pmpro-woocommerce/ WooCommerce Integration Add On Plugin]
* [https://wordpress.org/plugins/pmpro-woocommerce/ Paid Memberships Pro Integration with WooCommerce – WordPress plugin | WordPress.org]
* [https://www.paidmembershipspro.com/paid-newsletters/ Sell Paid Newsletters on WordPress]単体記事の販売には工夫が必要。
WooCommerceと連携したり、PMProの有料プラグインを使うとか。他にも方法を以前調査したの後日追記する。
理想としては、単品販売と、会員を両立したい。2個以上買うなら会員のほうがいいみたいな。
単品販売の方法。有料アドオン、LearnDash、後はWooCommerce連携など。
Addon Packagesがいい。PMProのAddon Packagesは、まずあるメンバーシップレベルのユーザーに購入権利を与えて、そこから購入する形。
あくまで単品販売で、定期販売はできない。記事別に金額の入力欄が表示されてそれで単品販売する形。悪くない。こちらの理想に近い。単品販売することにした記事は買うしかない。あるメンバーレベルなら買わなくても見れるというようにはできなさそう。いや。1レベルだけ全アクセス可能はできる。
==== Course ====
*[https://www.paidmembershipspro.com/multiple-membership-levels-per-user-pmpro-workarounds/ Multiple Membership Levels Per User with PMPro (The Workarounds)]
*[https://wordpress.org/plugins/paid-memberships-pro-for-wp-courseware/ Paid Memberships Pro Addon for WP Courseware – WordPress plugin | WordPress.org]
*[https://www.paidmembershipspro.com/add-ons/pmpro-courses-lms-integration/ Courses for Membership Add On Plugin]
*[https://www.paidmembershipspro.com/add-ons/learndash-integration/ LearnDash Add On Plugin for Paid Memberships Pro]
*[https://flyplugins.com/paid-memberships-pro-courses/ Paid Memberships Pro for Selling Courses]
LearnCashはちょっといまいち。外部のプラグインとの連携。この機能自体はPMProのあるレベルが、LernDashのあるコースにアクセス可能にするだけだから、あまり意味ない。PMProだけでも似たようなことはできる。
単独販売の本質は、1ユーザーに複数のレベル・会員の所属。これはレッスンなどで、上位・下位の関係がない場合にあり得るケース。上位・下位がある場合は、1ユーザーは1レベルになる。
方法がいくつかある。
# Multiple Membership Per user Addon: 1ユーザーが複数のレベルに参加できるプラグインがある。がベータ版で他のプラグインと互換がなかったりする。ちょっと危ない。
# Addon Package: これが無難。
# フィールド: メインレベル加入時にオプションフィールドをつけて金額を変える。
# Multisite: サイトの内容次第だが、いっそ別サイトにするというのもある。
Addon Packageが無難。Addon PackageとWP coursewareと連携したりもできるらしい。
==== Addon Packages ====
===== About =====
* [https://www.paidmembershipspro.com/add-ons/pmpro-purchase-access-to-a-single-page/ Addon Packages Add On Plugin for PMPro]
* [https://github.com/strangerstudios/pmpro-addon-packages strangerstudios/pmpro-addon-packages: Charge for access to specific pages or other post types in WordPress. Requires the Paid Memberships Pro plugin.]
記事の単品販売用にAddon Packagesがあるのでこれを試す。このプラグインは将来的にPMPro本体に取り込まれるもので、一時的な解決用という位置づけ。
===== Usage =====
インストールしたらpost/page画面に金額設定画面が表示されるので、ここで金額をいれて、[Require Membership] も指定すると単品販売できる。
カテゴリーでのレベル指定は無効。一番レベル低いFreeなどを1個指定すれば、自動的に全部に適用される。レベルの指定が若干使いにくい。カテゴリーで指定できれば楽だった。やむを得ない。PMPro 3で取り込まれたりしないかな。
しないでしょうね。コンテンツの部分非表示と同じで、ページ単位で会員レベルを指定する必要があるのが作りとしていまいち。だがこれに従うしかないか。基本は変えない運用にすればいいのか。
===== Configuration =====
* define( '<code>PMPROAP_EXP_DAYS</code>', 0 );: 有効期限の設定デフォルト0 (無期限)。基本はデフォルトでOK。
* apply_filters( 'pmproap_all_access_levels', array(), $user_id, $post_id );: 単品購入を無視してアクセスできる神レベル的なものを指定できる。
* apply_filters( 'pmproap_text_level_id', $text_level_id, $post_id, $user_id, $post_levels );: 未ログインユーザー向けの新規購入時に必要なレベルID。
* apply_filters( 'pmproap_supported_post_types', array( 'page', 'post' ) );
* do_action( 'pmproap_action_add_to_package', $user_id, $post_id );
* do_action( 'pmproap_action_remove_from_package', $user_id, $post_id );
pmproap_all_access_levels を使うと、単品購入を無視してアクセスできる神レベル的なものを指定できる。
例えば、最上位だけ除外するとか。金額でレベル指定できればなおよかったがしかたない。<syntaxhighlight lang="php">
/*
Set levels as "all access levels" so members of these levels will be able to view all Addon Packages.
Requires Paid Memberships Pro and the pmpro-addon-packages plugin.
*/
function my_pmproap_all_access_levels($levels, $user_id, $post_id)
{
//I'm just adding the level, but I could do some calculation based on the user and post id to programatically give access to content
$levels = array(16);
return $levels;
}
add_filter("pmproap_all_access_levels", "my_pmproap_all_access_levels", 10, 3);
</syntaxhighlight>
===== Message =====
pmpro_non_member_text_filter/pmpro_not_logged_in_text_filterを[https://github.com/strangerstudios/pmpro-addon-packages/blob/dev/pmpro-addon-packages.php#L266 pmproap_pmpro_text_filter]で上書きしている。この実装を参考に、自分で元のフィルターを上書きすれば、表示文を変更できる。
<nowiki><div class="pmpro_content_message"><p>This content requires that you purchase additional access. The price is ¥220 or free for our Gold members.</p></nowiki><nowiki><p><a href="https://web.gnusocial.jp/member/checkout/?level=1&amp;amp;ap=10307">Purchase this Content (¥220)</a></nowiki> <nowiki><a href="https://web.gnusocial.jp/member/level/">Choose a Membership Level</a></nowiki><nowiki></p></nowiki><nowiki></div></nowiki>
Addon Package有無の両方の考慮が必要でちょっと複雑になる。
===== Shortcode =====
[pmpro_addon_packages] のショートコードを使うと、単品販売の記事一覧を出力できる。
===== Addon Pakacage用改造 =====
既存のAddon Packageがブロックに未対応、ページのレベル指定が必要な点が気に入らないので改造する。
* 金額があればAPとみなす。
*
作業手順
* my_pmproap_membership_content_filter でコンテンツの制限のロジックにAP (金額があれば制限・制限文表示) を組み込む。
* 表示文。
* paywallショートコード追加。
pmpro_non_member_text_filterなどで表示させる表示文のロジックをどうするか。
ショートコードと基本ロジックは同じだが、非表示部分の文字数の扱いがある。引数の$notloggiedintextは管理画面の設定したメッセージ。
共通関数を作って、それを流用して、引数で文字数を受け取るようにするか。
[[Category:Distributed]]

2024年9月23日 (月) 23:02時点における最新版

About

WordPressは世界の多くのウェブサイトで使用されているCMSだ。PHPで記述されている。

WordPressの外観や挙動はPHPのプログラムを書いてカスタマイズできる。また、プラグイン機構を持ち、世界中の開発者によるプラグインを導入することで簡単にウェブサイトを拡張できる。

Install

WordPress.comなどのホスティングサービスを使用することもできるが、レンタルサーバーやVPSに設置することが好ましい。

ActivityPub

WordPressはActivityPubを実装している。WordPressへの投稿時に分散SNSにも投稿される、分散SNSからWordPressの投稿にコメントできるなどの機能がある。

WordPressの公式ホスティングサービスであるWordPress.comもActivityPubに対応している。分散SNSの中でも巨大なサーバーと言え、無視できない存在だ。

ActivityPub – WordPress プラグイン | WordPress.org 日本語

example.comというドメインで運営している場合、デフォルトでサイト全体を表す、example.com@example.comユーザーが追加される。

このユーザーは、サイトに登録済みの全ユーザーの更新を含む。

Function

Account

ユーザー名の改名

WordPressユーザー名の正しい変更方法(3つの方法)

管理画面からは直接変更できない。いくつか方法がある。

一番シンプルなのが、新規ユーザー作成後の削除。

Delete

ワードプレスでユーザー削除する際の注意点「ミスると記事が消滅します」 | 株式会社ステップバイワーク

アカウントの削除時には注意が必要。

削除時に以下の選択肢が表示される。

  1. Delete all content.
  2. Attribute all content to:

1を選ぶと本当に全部消える。2を選ぶのが無難。

Comment

Ref:

このあたりの関数で定義されている。フィルターを挟むことで変更できる模様。

PV

WordPressでPV数を表示させる方法がいくつかある。

WP-PostViewsプラグインのほうが柔軟性がある? (WordPressで記事ランキングを設置するならWP-PostViewsが最適なのでは? | kanae-design-works「WP-PostViews」と「WordPress Popular Posts」の違い | クロジカ)。

WordPressの分析プラグインはDBにアクセ格納するから重くなるらしい

Jetpackの統計情報から閲覧数を取得表示することができる。これが一番手っ取り早い気がする。

<p>
<?php // 全体、月別、週別、日別のPV表示
  global $post;
  $views_all = 0;
  $views_monthly = 0;
  $views_weekly = 0;
  $views_daily = 0;
  //Jetpack利用時
  if (is_jetpack_stats_module_active()) {
    $jetpack_views = stats_get_csv( 'postviews', array('days' => -1, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_all = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 30, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_monthly = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 7, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_weekly = $jetpack_views[0]['views'];
    }
    $jetpack_views = stats_get_csv( 'postviews', array('days' => 1, 'limit' => 1, 'post_id' => $post->ID ));
    if (isset($jetpack_views[0]['views'])) {
      $views_daily = $jetpack_views[0]['views'];
    }
  }
  echo '<span class="daily">日:<span class="pv-count">', $views_daily, '</span></span>';
  echo '<span class="weekly">週:<span class="pv-count">', $views_weekly, '</span></span>';
  echo '<span class="monthly">月:<span class="pv-count">', $views_monthly, '</span></span>';
  echo '<span class="all">全体:<span class="pv-count">', $views_all, '</span></span>';
?>
</p>

上記コードをウィジェットに貼り付けたらうまくいった。

Language

WordPressで多言語対応サイトも構築できる。

情報源:

いろいろ方式があるが、サブディレクトリー形式が手軽な感じがする。

英語で情報発信できると、かなりの数のユーザーにアプローチできる。単に機械翻訳にするだけでも検討する価値はあるだろう。

広告ブロッカー対策

出典: 【WordPress編】広告ブロッカーからサイトコンテンツと収益を守る! | SEの良心

[CHP Ads Block Detector] というプラグインで実現できるらしい。

プラグイン: WordPressの広告ブロッカー対策CHP Ads Block Detector | GNU social JP Web」の通り、簡単にできた。

Widget内でのPHP実行

WordPressのウィジェットでPHPコードを実行する方法 – FOXWP

function widget_text_exec_php( $widget_text ) {
    if( strpos( $widget_text, '<' . '?' ) !== false ) {
        ob_start();
        eval( '?>' . $widget_text );
        $widget_text = ob_get_contents();
        ob_end_clean();
    }
    return $widget_text;
}
add_filter( 'widget_text', 'widget_text_exec_php', 99 );

上記コードをfunction.phpに配置すると、テキストウィジェット内でPHPコード<?php ?>を実行できる模様。

Linkage

WordPressの記事・投稿を他のSNSに自動投稿する方法がいくつかある。

There has been a critical error on this website. Please check your site admin email inbox for instructions.

プラグインを無効にしようと

How to deactivate all plugins when not able to access the administrative menus?


Reference

Ref: Reference | Developer.WordPress.org.

WPCode

Shortcodeの定義はくせがある。

[Insert Method]=[Shortcode] を選ぶと [wpcode id="10405"] のようなショートコードが定義される。これを [wpcode id="10405"][/wpcode]のようなブロックで使う。

Code Previewには、関数の本文を指定して、表示する場合echoなどで出力させる。

無料版だとshortcodeの名前を指定できない。

Auto Insertで自分で定義したらどうだろう?それで問題ない。

Media

WordPressはメディアをデフォルトで年付きベースのディレクトリーに保存する。これを変更するのは少々やっかい。

いくつかプラグインがあるのだが、FileBirdというプラグインががあって、デフォルトのアップロードディレクトリーはそのままで、内部的にディレクトリー的なものでカテゴリー分けできる。

これで管理するのが無難。

Permalink

著者のパーマリンク

Different permalink for posts and authors - WordPress Development Stack Exchange

WordPressでは、authorのパーマリンクは、postの下に配置される。

http://domain.com/p/u/USERNAME
http://domain.com/p/POSTID

これがよろしくない。ユーザープロフィールのパーマリンクもこれになるから。

WPSE-Plugins/custom-author-base.php at master · chrisguitarguy/WPSE-Plugins · GitHub」のプラグインで対応できる模様。

うーん。こちらのパーマリンクはうまく動作しなかった。

代わりに、「permalinks - How to custom change author base without $this->front? - WordPress Development Stack Exchange」の以下のコードが動作した。

add_action('init', 'wpse82004_init');
function wpse82004_init()
{
    global $wp_rewrite;
    $wp_rewrite->author_base = 'user';
    $wp_rewrite->author_structure = '/' . $wp_rewrite->author_base . '/%author%';
}

ハードコードだが、うまく機能していて、変更することはないので、これでもいい。

パーマリンクの形式

/post/投稿ID/の形式がシンプルでいい。

以前は/post/年/月/日/投稿ID/にしていたけど、長くなる。日付がパーマリンクにあると覚えやすいというのはあるのだけど。

長くなるし、日付があることで、情報が古いというイメージがあったり、いろいろある。記事を更新した場合も、ソートしたりするときに問題が。

年月日アーカイブはWordPressの機能でできるから、/post/投稿ID/が良いだろう。

Plugin

Ref: Plugin Handbook | Developer.WordPress.org.

WordPresの拡張性のコア機能。

List

新しくWebサイトを始めるにあたって使いたいプラグインがある。

  • ActivityPub
  • FileBird
  • Site Kit by Google
  • WPCode Lite

配布形式

すぐできる!WordPressの自作プラグインの作り方の基本を解説 | Plusers

/wp-content/pluginsにファイルを直接アップロードする。か、ディレクトリーをzipに圧縮すれば、WordPressのプラグイン画面からアップロードできる。

Hook

Ref: Hooks – Plugin Handbook | Developer.WordPress.org.

フックはあるコードから別のコードに干渉するための仕組み。プラグインやテーマへの干渉のコア機能。拡張も可能。ActionとFilterの2種類がある。コールバックと一般的に呼ばれる関数を定義して引っ掛けて処理に干渉する。

  • Action: WordPressの操作操作に、データの追加や変更を行う。内部的にデータを処理するので、何も返さない。
  • Filter: WordPressコア機能の実行時にデータを変更する。データを受け取ってそれを次に渡す。

基本はFilterだと思う。Actionの用途がいまいちわからない。

Filter

Ref

add_filter/remove_filter

shortcode

Ref:

WordPressにはショートコードというのがある。角括弧 [shortcode][/shortcode] のような形式。本来ならHTML/JavaScriptしか使えない投稿本文に、PHP側の処理を仕込める。

新規作成する場合、書式がだいたい決まっている。

    function callback_function($atts, $content = null, $tag ) {
      extract(shortcode_atts(array(
        //属性
        'パラメータ1' => 'デフォルトの値1',
        'パラメータ2' => 'デフォルトの値2',
        ・・・
      ), $atts));
      //ショートコードの処理(動作)の記述
      return $value;
    }
    add_shortcode('my_shortcode', 'callback_function');

こえrでmy_shortcodeというショートコードが使用可能になる。

shortcode_atts

shortcode_atts( array $pairs, array $atts, string $shortcode = ” ): array

ユーザーが指定した属性と、使用可能な属性のデフォルト値を結合する。使用不能な属性を無視してくれる。

  • $pairs: 使用可能な属性とそのデフォルト値。
  • $atts: ショートコードでユーザーが指定した属性。
  • $shortcode: ショートコードの名前。これを指定するとshortcode_atts_$shortcode フィルターで外部から属性をフィルターできる。通常は使わない。



About

PMPro。有料会員サービスを実現するプラグイン。

ソースコード内のincludes配下の関数は自分でも使用可能。

Free

PMProは基本的に無料で使える模様 (PMPro: Free WordPress Membership Plugin)。サポートを販売している扱いの模様。ログアウトしていないと表示されない。

Stranger Studios」がGitHubのリポジトリー。ここに全部のアドオンがある。ここからzipファイル類をダウンロードすれば使える。ただし、一部のプラグインは開発者の経験が必要なため、ライセンスキーの購入をsupportとして販売している。開発経験が一切ない人にはGitHubからのインストールもけっこう面倒くさいからそれでうまくGPLの条件を満たしているのだと思われる。

実行自体はライセンスの有無によらず可能。ただし、ライセンスの有無でStripeの決済手数料が変わる。

Paid Memberships Pro (@paidmembershipspro) – WordPress user profile | WordPress.org」でも公開しているが、これは全部ではない。サードパーティープラグインとの連携用が大半。

金額変更

定期購読で販売していて、登録後に金額を変更したいことがある。

これは基本的にできない。定期購読は決済サービス側で登録時の金額で固定されるため。

金額を変更したければ、一度キャンセルして、再度チェックアウト・購入してもらうしかない。

既存会員に対しては、更新ではなく、期限を設けて強制的に一度退会させるのがいい。

Restriction

membership short code

Ref:

PMProの基本的なコンテンツ制限の概念がある。

基本は投稿全体を非表示で、excerptで冒頭部分を一部表示これが基本。membershipショートコードはこの逆で、基本全表示で一部だけ非表示。

そもそも仕組みが違う。

だから、カテゴリーで管理していて、一部だけ非表示にしたかったら、末尾にmoreブロックを配置して、membeshipショートコードも使う必要がある。二重に使わないといけない。けっこう面倒くさい。

Custom Message for Non-Members on Protected Content」がメッセージの変更方法。ただ、制限のロジックを変更できるわけではない。別のフィルターだと思う。

ソースコードを参考に自分で実装するしかないだろう。

message

Custom Message for Non-Members on Protected Content」に基本的な表示内容やスタイルの設定方法がある。

<div class="pmpro_content_message">
//custom message here
</div>

表示部分は上記要素になるのでこのクラスでスタイルをあてる。

.pmpro_content_message {
	background: #F1F1F1;
	margin: 0 auto;
	max-width: 700px;
	padding: 15px;
}

他に以下のフィルターが該当するメッセージ表示。

  • add_filter( 'pmpro_non_member_text_filter', 'my_pmpro_non_member_text_filter', 5 );
  • add_filter( 'pmpro_not_logged_in_text_filter', 'my_pmpro_not_logged_in_text_filter', 5 );

例えば、会員限定の文字数表示などをしたければ、自前でやるしかない。基本は自分で上記フィルターで上書きするのがよい。

function my_pmpro_non_member_text_filter( $text ) {
	global $post, $post_membership_levels_names;
	$count = mb_strlen( $post->post_content, 'UTF-8' ) - mb_strlen( get_the_excerpt(), 'UTF-8' );
	$access = pmpro_has_membership_access( $post->ID, null, true );
	$text = "<p>残り{$count}文字。続きは" . implode( '/', $access[2] ) . '会員限定。</p><p>Free=0/Bronze=220/Silver=1100/Gold=2200円。</p>'
		. '<p><a href="https://web.gnusocial.jp/member/level/">会員登録</a>/'
		. '<a href="//web.gnusocial.jp/member/login/">ログイン</a> (<a href="//web.gnusocial.jp/about/member/">About Member</a>)。</p>';
	return $text;
}
add_filter( 'pmpro_non_member_text_filter', 'my_pmpro_non_member_text_filter', 5 );
add_filter( 'pmpro_not_logged_in_text_filter', 'my_pmpro_non_member_text_filter', 5 );

Style

Custom Message for Non-Members on Protected Content」でペイウォールの表示内容・スタイルを制御できる。

ペイウォール (.pmpro_content_message) のスタイルは会員登録の誘発に重要。

有名サービスの例は上記。登録・購入ボタンを大きく押しやすくしている。a要素の他button要素でも実装されている。ここはいろいろ考えてもいいかもしれない。

Category

membershipショートコードやAddon Packagesではカテゴリーやタグでの会員限定に対応していない。これがちょっと困る。既存のカテゴリー、タグでの会員対応の把握方法を確認する。

includes/contents.phpのpmpro_has_membership_accessのコードが参考になる。

	if(isset($mypost->post_type) && $mypost->post_type == "post")
	{
		// Get the categories for this post.
		$post_terms = wp_get_post_categories( $mypost->ID );

		// Get the tags for this post.
		$post_terms = array_merge( $post_terms, wp_get_post_tags( $mypost->ID, array('fields' => 'ids' ) ) );

		if( ! $post_terms )
		{
			//just check for entries in the memberships_pages table
			$sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
		}
		else
		{
			//are any of the post categories associated with membership levels? also check the memberships_pages table
			$sqlQuery = "(SELECT m.id, m.name FROM $wpdb->pmpro_memberships_categories mc LEFT JOIN $wpdb->pmpro_membership_levels m ON mc.membership_id = m.id WHERE mc.category_id IN(" . implode(",", array_map( 'intval', $post_terms ) ) . ") AND m.id IS NOT NULL) UNION (SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "')";
		}
	}
	else
	{
		//are any membership levels associated with this page?
		$sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
	}

    $post_membership_levels = $wpdb->get_results($sqlQuery);

普通にSQLで取得している。このへんのコードを流用すれば対応できる気はする。ただ、ちょっと面倒くさい。

Analytics

PMProの流入元の記事を分析・特定する方法がある。

GA4を使った一般的なサイト分析になる。有料プラグインでもできる。

Sell

Single

WooCommerceと連携したり、PMProの有料プラグインを使うとか。他にも方法を以前調査したの後日追記する。

理想としては、単品販売と、会員を両立したい。2個以上買うなら会員のほうがいいみたいな。

単品販売の方法。有料アドオン、LearnDash、後はWooCommerce連携など。

Addon Packagesがいい。PMProのAddon Packagesは、まずあるメンバーシップレベルのユーザーに購入権利を与えて、そこから購入する形。

あくまで単品販売で、定期販売はできない。記事別に金額の入力欄が表示されてそれで単品販売する形。悪くない。こちらの理想に近い。単品販売することにした記事は買うしかない。あるメンバーレベルなら買わなくても見れるというようにはできなさそう。いや。1レベルだけ全アクセス可能はできる。

Course

LearnCashはちょっといまいち。外部のプラグインとの連携。この機能自体はPMProのあるレベルが、LernDashのあるコースにアクセス可能にするだけだから、あまり意味ない。PMProだけでも似たようなことはできる。

単独販売の本質は、1ユーザーに複数のレベル・会員の所属。これはレッスンなどで、上位・下位の関係がない場合にあり得るケース。上位・下位がある場合は、1ユーザーは1レベルになる。

方法がいくつかある。

  1. Multiple Membership Per user Addon: 1ユーザーが複数のレベルに参加できるプラグインがある。がベータ版で他のプラグインと互換がなかったりする。ちょっと危ない。
  2. Addon Package: これが無難。
  3. フィールド: メインレベル加入時にオプションフィールドをつけて金額を変える。
  4. Multisite: サイトの内容次第だが、いっそ別サイトにするというのもある。

Addon Packageが無難。Addon PackageとWP coursewareと連携したりもできるらしい。

Addon Packages

About

記事の単品販売用にAddon Packagesがあるのでこれを試す。このプラグインは将来的にPMPro本体に取り込まれるもので、一時的な解決用という位置づけ。

Usage

インストールしたらpost/page画面に金額設定画面が表示されるので、ここで金額をいれて、[Require Membership] も指定すると単品販売できる。

カテゴリーでのレベル指定は無効。一番レベル低いFreeなどを1個指定すれば、自動的に全部に適用される。レベルの指定が若干使いにくい。カテゴリーで指定できれば楽だった。やむを得ない。PMPro 3で取り込まれたりしないかな。

しないでしょうね。コンテンツの部分非表示と同じで、ページ単位で会員レベルを指定する必要があるのが作りとしていまいち。だがこれに従うしかないか。基本は変えない運用にすればいいのか。

Configuration
  • define( 'PMPROAP_EXP_DAYS', 0 );: 有効期限の設定デフォルト0 (無期限)。基本はデフォルトでOK。
  • apply_filters( 'pmproap_all_access_levels', array(), $user_id, $post_id );: 単品購入を無視してアクセスできる神レベル的なものを指定できる。
  • apply_filters( 'pmproap_text_level_id', $text_level_id, $post_id, $user_id, $post_levels );: 未ログインユーザー向けの新規購入時に必要なレベルID。
  • apply_filters( 'pmproap_supported_post_types', array( 'page', 'post' ) );
  • do_action( 'pmproap_action_add_to_package', $user_id, $post_id );
  • do_action( 'pmproap_action_remove_from_package', $user_id, $post_id );

pmproap_all_access_levels を使うと、単品購入を無視してアクセスできる神レベル的なものを指定できる。

例えば、最上位だけ除外するとか。金額でレベル指定できればなおよかったがしかたない。

/*
	Set levels as "all access levels" so members of these levels will be able to view all Addon Packages.
	Requires Paid Memberships Pro and the pmpro-addon-packages plugin.
*/
function my_pmproap_all_access_levels($levels, $user_id, $post_id)
{
	//I'm just adding the level, but I could do some calculation based on the user and post id to programatically give access to content
	$levels = array(16);	
	return $levels;
}
add_filter("pmproap_all_access_levels", "my_pmproap_all_access_levels", 10, 3);
Message

pmpro_non_member_text_filter/pmpro_not_logged_in_text_filterをpmproap_pmpro_text_filterで上書きしている。この実装を参考に、自分で元のフィルターを上書きすれば、表示文を変更できる。

<div class="pmpro_content_message"><p>This content requires that you purchase additional access. The price is ¥220 or free for our Gold members.</p><p><a href="https://web.gnusocial.jp/member/checkout/?level=1&amp;ap=10307">Purchase this Content (¥220)</a> <a href="https://web.gnusocial.jp/member/level/">Choose a Membership Level</a></p></div>

Addon Package有無の両方の考慮が必要でちょっと複雑になる。

Shortcode

[pmpro_addon_packages] のショートコードを使うと、単品販売の記事一覧を出力できる。

Addon Pakacage用改造

既存のAddon Packageがブロックに未対応、ページのレベル指定が必要な点が気に入らないので改造する。

  • 金額があればAPとみなす。

作業手順

  • my_pmproap_membership_content_filter でコンテンツの制限のロジックにAP (金額があれば制限・制限文表示) を組み込む。
  • 表示文。
  • paywallショートコード追加。

pmpro_non_member_text_filterなどで表示させる表示文のロジックをどうするか。

ショートコードと基本ロジックは同じだが、非表示部分の文字数の扱いがある。引数の$notloggiedintextは管理画面の設定したメッセージ。

共通関数を作って、それを流用して、引数で文字数を受け取るようにするか。