記事への画像の貼り付け-drupal8

記事への画像の貼り付け方法を検討

記事を書くために使用するWYSIWYGエディタのボタンから画像貼り付け用のツールを起動するのが一般的です。
drupalだとIMCEが有名だと思います。
画像貼り付け用のツールを機能で細分化すると以下になると思います。
すべてが揃ってなくても問題はありません。

ロード機能(選択)

まずサーバ上に写真などの画像ファイルを利用するには、その画像をサーバ上に配置することから始まります。
PCやスマホなどで撮影した写真はそれらのデバイスのローカルストレージ上にあるので、記事に貼り付ける場合には、操作しているPCやスマホの中にあるファイル一覧を表示し画像を選択できる機能が必要です。さらに、選択した画像ファイルをサーバ上にアップロードする機能も必要です。
また、すでにサーバ上にある画像を再利用する場合は、サーバ上の既存の画像ファイルの一覧から選択できる機能が必要です。
この機能の裏側には、サーバ上に画像ファイルを保存する場所が必要であるということです。
効率よく探し出すには検索機能が必要ですし、保存場所を任意に作成または設定できたほうが利便性が向上すると思います。

編集機能

記事に貼り付ける時に気を付けるのがどう見せるかです。
より効果的にするためにリサイズやクロップなどの画像編集機能があると便利です。
画像スタイルに事前に準備しておくとよいでしょう。
また、クロップのような場合はその都度手作業でやった方がよい場合もありますのでそういったツールを使うとよいと思います。

挿入(コード生成機能)

これまでの操作で画像ファイルの場所、見せ方が決まっています。
あとは、それにあったHTMLソースコードを生成して希望の場所に貼り付けるだけです。
この生成されたコードが記事の本文に挿入されるため、通常はあとからプログラムで一括で変更したりはできません。
たとえば、最初はcolorboxを使って表示するようなソースコードを貼り付けていたけどもレスポンシブ画像スタイルに変更したという場合、過去の記事の画像も変えたいなら本文に貼り付けたコードを1つ1つ貼り替えないといけません。
また、生成されるコードはTokenが使われるツールもあるので次のフィルター機能で注意が必要です。

フィルター機能

記事の本文を入力しているエリアはテキストボックスと同じです。
テキストボックスには入力フィルターが機能します。
セキュリティの観点から利用できるHTMLタグを制限するものでしたが、今では、いろいろなフィルターが存在しています。
この機能はフィルターというとイメージしにくいので自動変換機能というとわかりやすいと思います。
先の作業でTokenを使ったコードが生成されている場合は、個別フィルターを有効にする必要があるケースがありますし、フィルターを使う場合は処理される順番も重要です。
せっかくコードを生成していても、このフィルター機能が機能してコードが表示されなかったり最悪は消去される可能性もあります。

再利用

drupal7以降ではViewsモジュールが当たり前になりました。
たとえばdrupal8のフロントページはteaserをViewsで出力しています。
ある記事に挿入した画像ファイルをほかで使わないのであれば気にしなくてよいですが、たとえば、このサイトのように画像が埋め込まれた記事には1枚の画像を表示して・・・ということをしたい場合やサイトのすべての画像をスライドショーで表示したいといった場合、フロントページに最新の画像を貼り付けたい場合などアップロードした画像ファイルを何らかの方法でコントロールする必要があります。その方法が次の2つです。

Field

drupal6の途中から実装されたものだと記憶しています。
Field TypeにはNumber/Text/File/Image/Taxonomy/Videoなど数多くの種類があります。
コアのバージョンによって含まれているTypeが異なります。
Fieldを作成するとそのFieldをデータベースで管理できるようにるため、SQL分を実行して抽出できるので再利用が簡単です。

Entity

drupal8から実装されたものですが、drupal8開発中はdrupal7が現役バリバリの時期といこともありdrupal7の途中からdrupal8と同時に開発されています。
drupal6にはEntityはありませんがdrupal7では開発時期によって対応しているものもあればそうでないものもあります。
drupal8でコアに含まれているはずですが、複雑な状況です。
例えば、Entityモジュールが存在しています。あれ?コアに含まれているはずでは?と考えてしまいます。
 

私の場合、特に考えなければならないのは次の3点でした。

  1. アップロードおよび貼り付けの操作の利便性
  2. 画像貼り付け用コードの完全性
  3. 画像ファイルの安全で確実な管理方法

 

drupal8の状況

drupal8コアのバージョンにより、当サイトが影響を受けていたまたは影響を受けている事項です。
コアに吸収されたモジュールがすべての機能がコアに移ったわけではありません。

Mediaモジュール

例えばコアにあるMediaです。
Media Entityモジュールの成果物がコアのMediaに移されるようになっているようなので、Media EntityとコアのMediaの両方を有効化する必要がありません。これに関連してEntity Browser 1.x系はMedia Entityと一緒に利用するために、Entity Browser 2.x系はコアのMediaと一緒に利用するためにだそうです。Drupal7のときはFieldモジュールで似たようなことがありましたが、drupal8ではEntity関連がそんな感じです。

Taxonomy Term

drupal-8.5.0でデータベースのテーブル名が「taxonomy_term_hierarchy」から「taxonomy_term__pearent」に変更になったようですがコアにあるAPIが対応できておらず存在しないテーブルを操作しようとしてエラーがでまくります。
この影響でタクソノミーの編集や記事の編集などをしようとすると「Internal Server Error 500」で表示できません。
nginx+php-fpmであればphp-fpmのエラーログに原因の究明に役立つメッセージが出力されています。

drupal-8.6.x-devでは対応済みのようですが、「drush entity update」で同じエラーがでるのですべてのAPIで問題がなくなったわけではないようです。
また、「Taxonomy Term Depth」モジュールにあるように関連モジュールでもエラーが発生します。https://www.drupal.org/pift-ci-job/920585

drupal8といってもすべてのコアバージョンを同じに扱うことができません。
状況などはそれぞれのRoad Mapを参考に何ができていて何ができないかを読み取るしかないようです。

以下は2018年6月22日に更新された、8.6/8.7/8.8以降のRoad Mapです。
https://www.drupal.org/core/roadmap

Media Entity Browser

https://drupal-media.gitbooks.io/drupal8-guide/content/modules/media_entity/intro.html

このリンク先の内容を試してみましたが、drupal-8.6.x-devでエラーが発生しないモジュールの組み合わせが見つからず断念しました。

File Entity Browser

個人での使用を考えると、記事ごとに画像をアップロードして記事に貼り付けるのも悪くないのでしょうが、例えば、編集部のようなところでカメラマンと編集者で役割分担をすることを考えると、使いそうな画像は事前にすべてサーバにアップロードしておいて、使う分を記事に貼り付けていく方法の方がよい場合もあります。
今回は後者の方法になります。
Media Entity Browserのほうでは、Media XXXが影響してうまくいきませんでしたのでそれらを使わないFile Entity Browserはどうなのかという興味から試してみることにしました。

実際に使用するモジュールは「File Entity Browser」です。
どんな感じかのデモ画像がこちらになります。

WYSIWYGエディタのボタンからInsert File Browser画面が表示され、Upload FilesとFiles Listingが可能になります。
前者が操作しているPCからファイルをアップロードして選択する機能で、後者がすでにサーバーにアップロードしているファイルを選択する機能です。どちらも挿入するファイルを選択するためのUIです。
それ以外にも、「admin/content/files」にアクセスすればアップロードされているファイル一覧が参照できるうえに、ファイルのアップロードも可能です。ここでは、アーカイブしたファイルのアップロードにも対応しているようです。
File Entity Browserでできることを細かく見ていくと、以下が疑問点です。

  1. Fieldに登録されるのか?
  2. アップロード先のパスは?
  3. 表示スタイルは?

Fieldに登録されるのか?

実際にWYSIWYGエディタのボタンからUpload Filesでファイルをアップロードしたものと、「admin/content/files」からファイルを追加でファイルをアップロードしてみたものとでデータベーステーブルを直接見てみました。
その結果、「 file_managed 」テーブルに登録されていました。
Fieldに登録されるかというと「No」になると思います。

アップロード先のパスは?

File Field Pathモジュールなどでコンテンツタイプごとにアップロード先のフォルダーを変更できるようにしていました。実際にはimagesフォルダとvideosフォルダしか使っていません。この機能が今でも必要なのかというと「No」です。
動画はアップロードする機会が減ったのでフォルダ分けは不要になったといえます。
画像ファイルはimagesにアップロードするようにしていましたが、いろいろなタイミングで機能がうまく動作しなかったようで、docroot、パブリックファイルシステムパス直下、パブリックファイルシステムパス/imagesに分かれてしまっています。

デフォルトではパブリックファイルシステムパスへフラットにアップロードされます。
「/admin/config/content/entity_browser」からID=browse_filesの設定を編集するもしくは新規作成すれば、ファイルアップロードやサーバ上のファイルを選択できるウィジットを変更または新規作成できます。
とりあえず、アップロード先のロケーションは「public://[date:custom:Y]-[date:custom:m]」に設定してみました。
※デフォルトの設定は変更できず、新規作成した設定はfile browserやその他pluginのjsやcssを読み込まないのでウィジット内の表示がviewsの表示のままで使いにくいです。これを変更できるようにしたのでその内容は別の記事にします。

ファイルを挿入後にアップロード先のパスを変えたい場合、たとえば、今回、デフォルトではパブリックファイルシステムパス直下にアップロードされたものをアップロード先を変更後のロケーションに更新したいケースです。
コンテンツのFile一覧から個別にアップロードしなおしたときに、各記事の内容にまで反映されるのか興味があります。
記事本文をTokenのまま保存しているのか置換後に保存しているのかで結果が異なると思います。

従来のようにファイルタイプでロケーションを変えるのはあまり意味がないように思え、だからといってフラットにすると長い年月を考慮すると同じファイル名で別の内容のファイルをアップロードすることもあるだろうと思い、「年-月」で分けてみることにしました。
この場合のデメリットはデータベース内を直接書き換えてファイルパスを変更するような場合に面倒になります。

表示スタイルは?

画像ファイルの表示スタイルでcolorboxを使っていますが、コアバージョンが変わったことで同じ名称のモジュールでも微妙に差異があり、生成コードが異なります。このため、厳密には従来と同じようにはcolorboxで表示できていません。
また、閲覧者のデバイスを考慮した場合、スマホやタブレットからのアクセスの方が多くなっています。
スマホやタブレットの画面でcolorbox表示が便利かというと「No」だと思います。

年々、画面解像度は高解像度になっていますので、スマホやタブレットの本体を回転させればPCのモニタ並みに表示できるはずです。
フィンガーアクションで拡大縮小も簡単にできるのでパケットサイズだけ気にすればよいかなぁと思っています。
そのため、コアにある「Responsive Image」を使えば複数のサイズに対応できうまくいきそうです。
また、WYSIWYGエディタのボタンからUpload Filesでファイルをアップロードし、挿入画像を選択すれば、画像スタイルを選択できます。
ここで選択できる画像スタイルは、フィールドの表示で選択できるリストと同じ内容です。

考察

デモではWYSIWYGエディタのボタンから起動していましたが、この方法以外にもFieldタイプでEntity Browserを選択すれば同じように起動ができます。このとき、すでに(Image)FileFieldに登録されている内容が消去されてしまうのか?
drupal7からEntityを使っているのでFiledを使ったアップロードしたファイルはEntity管理下にあるように思いますので、Fieldの設定を消去してもdrupalシステムから完全に消去されるわけではないので問題なさそうですが、ノードのImageFieldは空になるでしょうからViewsなどで画像を表示している個所ではEntityを選択した方法への変更が必要そうです。
この変更はテーマテンプレートで対応できそうかと思います。
リンク切れ対応でとにかくサーバ上に画像ファイルを大量にアップロードしなおす必要があり、その操作性が大幅に改善しそうなのはメリットです。

databaseをのぞいてみるとdrupal6ではアップロードしたファイルが「files」テーブルに登録されていたようです。
drupal7およびdrupal8では「file_managed」になっているようです。
※drupal7は7.36くらいから「file_managed」になったはずです。
各ノードのFileFieldでアップロードされたファイルは、「node__フィールド名」と「file_managed」に登録されています。
「node__フィールド名」のentity idで区別され、target idが「file_managed」のfidです。「file_managed」にはURI、ファイル名、MimeTypeや更新日などファイルの詳細な情報が登録されていますがTitle属性やAlt属性は「node__フィールド名」に保存されています。

アップロード時にField数の制限が1になってしまったコンテンツタイプでは、記事自体のFieldには1枚の画像しかなく(「node__フィールド名」のdeltaが0のみ)ですが、「file_managed」には情報が残っておりファイルはURIに指定されている場所(パブリックファイルシステムパス配下)に存在していました。
そのため、再度アップロードしなくてもサーバ上にあるファイルを選択して貼り付けが可能になります。

File Entity Browser動作テスト

以下は、サーバ上にあったファイルの画像です。

 

 ※画像挿入後に文字を入力するためには、赤く表示されるエンターマークをクリックすれば段落を変えてPタグを入れてくれますので、文字入力が可能になります。
フロントページのTeaser表示は、画像Fieldの1枚目の画像があればそれをカスタム画像スタイルで表示するようにしています。
ここに挿入した画像はFieldを使用していないのでフロントページでは表示できていないはずです。
File Entity Browserを使用するのであればフロントページのViewsの変更が必要になりそうです。

 

Image First Formatter

 

ちなみに、複数あるフィールドの画像から1枚だけを表示する機能は「Image First Formatter」を使用しています。
composerでインストールするのであれば、composer.jsonに以下を追加します。

 

"repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        } ,
        {
            "type": "package",
            "package": {
                "name": "leymannx/image_first_formatter",
                "version": "1.1",
                "type": "drupal-module",
                "source": {
                    "url": "https://github.com/leymannx/image_first_formatter.git",
                    "type": "git",
                    "reference": "tags/8.x-1.1"
                }
            }
        }
],

 

以下を実行します。

 

composer require leymannx/image_first_formatter

 

あとはdrushでモジュールをenableにすれば利用できます。
このモジュールによってコンテンツタイプのフィールドの表示管理(managed display)でフォーマットに「Image First」が選択できるようになります。
Teaser表示モードなどで使えば便利です。
このモジュールも「node__フィールド名」が空だと使えなくなります。

 

Drupalバージョン

Drupal 8.x