LoginSignup
1
0

laravelでwordpressライクなエディタ tinymce

Posted at

やりたい事

こんな感じのwordpressライクなエディタを搭載したい。

image.png

blade

これでツールバー付きのメニューバーができる。
ドラック&ドロップで画像を登録できます。

blade
{{ Form::textarea('hoge', null) }}

//....

<script src="/js/tinymce/tinymce.min.js"></script> 

<script>
    tinymce.init({
        selector: 'textarea',
        language: 'ja',
        icons: 'thin',
        statusbar: false,
        menubar: false,
        plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount code',
        // ツールバーは好みにカスタマイズ
        // toolbar: 'blocks fontsize bold italic underline strikethrough forecolor removeformat | alignleft aligncenter alignright alignjustify | emoticons link image table | numlist bullist | code',
        toolbar: 'fontsize bold underline strikethrough forecolor removeformat alignleft aligncenter alignright table emoticons link image code',
        block_formats: 'Paragraph=p; Header 1=h3; Header 2=h4; Header 3=h5',
        color_map: [
            '#BFEDD2', 'Light Green',
            '#FBEEB8', 'Light Yellow',
            '#F8CAC6', 'Light Red',
            '#ECCAFA', 'Light Purple',
            '#C2E0F4', 'Light Blue',
            
            '#2DC26B', 'Green',
            '#F1C40F', 'Yellow',
            '#E03E2D', 'Red',
            '#B96AD9', 'Purple',
            '#3598DB', 'Blue',
            
            '#169179', 'Dark Turquoise',
            '#E67E23', 'Orange',
            '#BA372A', 'Dark Red',
            '#843FA1', 'Dark Purple',
            '#236FA1', 'Dark Blue',
            
            '#ECF0F1', 'Light Gray',
            '#CED4D9', 'Medium Gray',
            '#95A5A6', 'Gray',
            '#7E8C8D', 'Dark Gray',
            '#34495E', 'Navy Blue',
            
            '#000000', 'Black',
            '#ffffff', 'White',
        ],

        image_title: true,
        relative_urls: false,
        automatic_uploads: true,
        // 画像が貼り付けられるとアクセスするリンク
        images_upload_url: '/tinymce?_token={{csrf_token()}}&folder=fugu&id={{$id}}', 
        file_picker_types: 'image',
        file_picker_callback: function(cb, value, meta) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');
            input.onchange = function() {
                var file = this.files[0];

                var reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = function () {
                    var id = 'blobid' + (new Date()).getTime();
                    var blobCache =  tinymce.activeEditor.editorUpload.blobCache;
                    var base64 = reader.result.split(',')[1];
                    var blobInfo = blobCache.create(id, file, base64);
                    blobCache.add(blobInfo);
                    cb(blobInfo.blobUri(), { title: file.name });
                };
            };
            input.click();
        }
    });
</script>

Services追加

ドラック&ドロップされた画像がajaxで送られてくるので受け取ってstrageに保存する。
tinymceで削除された画像をstrageから消す。

app/Services/ImageService.php
<?php

namespace App\Services;

use App\Http\Requests\ProfileUpdateRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
use Illuminate\Support\Facades\Storage;

class ImageService
{
    //tinymceから送られた画像を保存
    public static function tinymce(Request $request) 
    {
        $folder = $request->input()['folder'].'/'.$request->input()['id'];
        $file = $request->file('file');
        $extension = $file->getClientOriginalExtension();

        $fileName = 'tiro_tool_'.time().'.'.$extension;
        $directoryPath = storage_path('app/public/' . $folder);
        // フォルダが存在しない場合は作成
        if (!file_exists($directoryPath)) {
            mkdir($directoryPath, 0777, true);
        }
        chmod($directoryPath, 0777);
        $file->storeAs('public/'.$folder.'/', $fileName);
        return response()->json(['location'=>'/storage/'.$folder.'/'.$fileName]);
    }

    //tinymceで使われていない画像を削除
    public static function tinymceClear($folder, $instance) 
    {
        $folder .= '/'.$instance->id.'/';
        if ($folder[0] !== '/') $folder = '/' . $folder;
        $useingList = [];
        $folderNeedle = 'public'.$folder;
        $urlNeedle = '/storage'.$folder;
        $nameNeedle = 'tiro_tool_';
        //テーブルのカラム一覧を取得
        $columns = $instance->getConnection()->getSchemaBuilder()->getColumnListing($instance->getTable());
        foreach($columns as $c){
            $text = $instance->$c;
            $arr = explode($urlNeedle, $text);
            foreach($arr as $a){
                if(strpos($a, $nameNeedle)===0){
                    $useingList[] = (explode('"', $a))[0];
                }
            }
        }
        $files = Storage::files('public'.$folder);
        foreach ($files as $file) {
            $fileName = str_replace($folderNeedle, '', $file);
            if(!in_array($fileName, $useingList)){
                Storage::delete($file);
            }
        }
    }
}

ルーティング

web.php
use App\Services\ImageService;

Route::post('/tinymce', [ImageService::class, 'tinymce']);
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0