TinyMCE – images

Integracja z zapleczem cakephp w celu dołączania obrazków

Zakładamy że lokalizacja zdjęć będzie zależała od 3 parametrów: brand_id, course_id, lesson_id. Struktura katalogu jest następująca:

/var/www/<projekt>/webroot/files/brand/<brand_id>/course/<course_id>/lesson/<lesson_id>/

Ta struktura jest tworzona przez akcję 'add’ cakePHP w czasie tworzenia nowych obiektów, aby była dostępna w momencie  wgrywania zdjęcia. Po stronie JS przekazujemy te parametry w atrybutach data-*

Plik konfiguracyjny /js/tinymce-config.js

let course_id = $('#model').data('course-id');
let lesson_id = $('#model').data('lesson-id');
let brand_id  = $('#model').data('brand-id');
let course_url = '';
let lesson_urs = '';
if(brand_id) {
  brand_id = brand_id ? parseInt(brand_id) : null;
  brand_url = '/brand/' + brand_id;
  if(course_id) {
    course_id = course_id ? parseInt(course_id) : null;
    course_url = '/' + course_id;
    if(lesson_id) {
      lesson_id = course_id ? parseInt(lesson_id) : null;
      lesson_url = '/' + lesson_id;
    }
  }
}
let base_path = '/files/brand/' + brand_id + '/course/' + course_id + '/lesson/' + lesson_id;
let upload_url = '/panel/lessons/uploadFile' + course_url + lesson_url + '.json';
tinymce.init({ 
  selector :'textarea.editor',
  images_upload_url:         upload_url,
  images_upload_base_path:   base_path,
  images_upload_credentials: true,
 
...... pozostałe opcje ...
}

Akcja wgrania pliku dla (course_id=2, lesson_id=1). brand_id – po stronie serwera (zalogowany user).

/panel/lessons/uploadFile/2/31.json

public function uploadFile($course_id=null, $lesson_id=null)
{
  $response = ['message' => 'Nie weszło w pętlę AJAX'];

  if( $this->request->is('json') )
  {
    if( is_uploaded_file( $this->getRequest()->getData('file') ['tmp_name']) )
  {

  $filename = $this->getRequest()->getData('file')['name'];
  $tmp_name = $this->getRequest()->getData('file')['tmp_name'];

  // Sprawdzenie nazwy
  if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $filename)) {
    header("HTTP/1.1 400 Invalid file name.");
    return;
  }

  // Sprawdzenie rozszerzenia
  if (!in_array(strtolower(pathinfo($filename, PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
    header("HTTP/1.1 400 Invalid extension.");
    return;
  }

  if( $course_id && $lesson_id && $filename )
  {
    // Sprawdza czy jest taka lekcja i kurs i należą do marki
    $lesson = $this->Lessons->get($lesson_id, [
      'conditions' => [
      'brand_id' => $this->Auth->user('brand_id'),
      'course_id' => $course_id
      ]
     ]);
    if( $lesson )
    {
      $this->loadComponent('CourseDir');
      $path = $this->CourseDir->composePath($lesson->brand_id, $lesson->course_id, $lesson->id);
      $subdir = $course_id .DS. $lesson_id .DS. $filename;
      if( move_uploaded_file( $tmp_name, $path .DS. $filename ) ) {
        $response = ['location' => $filename];
      } else {
        $response = ['message' => 'Nie udało się wgrać pliku'];
      }
    } else {
      $response = ['message' => 'Błędny id lekcji'];
    }
  }
  // Nie przekazano lekcji i kursu - zapisz do worka ../courses/slidesall/
  // Czy chcemy wrzucać takie niedopasowane do lekcji pliki ?????
  else {
    $path = 'slidesall'.DS. $filename;

    if( move_uploaded_file( $tmp_name, $path ) ) {
      $response = ['location' => $filename];
    } else {
      $response = ['message' => 'Nie udało się wgrać pliku'];
    }
  }
} else {
  // Info do edytora że upload pliku nie powiódł się
  header("HTTP/1.1 500 Server Error");
  }
}
$this->set('response', $response);
$this->set('_serialize', 'response');
}

Komponent obsługujący tworzenie ścieżek: /Controller/Component/CourseDirComponent.php

class CourseDirComponent extends Component
{
    protected $_defaultConfig = [];
    
    public function composePath($brand_id = null, $course_id=null, $lesson_id=null)
    {
        if($brand_id) {
            //'BRAND_DIR' => WWW_ROOT.'files/brand/'
            $path = Folder::addPathElement(BRAND_DIR, [$brand_id]);
            if($course_id) {
                $path = Folder::addPathElement($path, ['course', $course_id]);
                if($lesson_id) {
                    $path = Folder::addPathElement($path, ['lesson', $lesson_id]);
                }
            }
            return $path;
        }
        return false;
    }
    
    public function create($brand_id = null, $course_id=null, $lesson_id=null)
    {
        $path = $this->composePath($brand_id, $course_id, $lesson_id);
        if($path) {
            $dir = new Folder($path);
            if(!$dir->inPath(BRAND_DIR)) {
                $dir->create($path);
            }
            return $path;
        }
        return false;
    }
    
    public function remove($brand_id = null, $course_id=null, $lesson_id=null)
    {
        $path = $this->composePath($brand_id, $course_id, $lesson_id);
        if($path) {
            $dir = new Folder($path);
            if($dir->inPath(BRAND_DIR)) {
                $dir->delete($path);
                return 'Katalog '. $path .' usunięty';
            }
            return 'Nie usunięto katalogu '. $path;
        }
        return false;
    }
}

Użycie komponentu w akcji ADD – dodającej kurs (/courses/add)

public function add()
{
  if ($this->Courses->save($course)) {
    $this->loadComponent('CourseDir');
    $info = $this->CourseDir->create( $course->brand_id, $course->id );
    $this->Flash->success(__('Kurs dodany. '. $info));
    return $this->redirect(['action' => 'index']);
  }
.....
  }
}

 

Dodaj komentarz