Строим блог на Areto фреймворк

Контроллер фотографий

Класс PhotoController определяет контроллер модели фото.

module/admin/controllers/PhotoController.js

const Base = require('../component/CrudController');
module.exports = class PhotoController extends Base {

  static getConstants () {
    return {
      METHODS: {
        'assign-main': ['post']
      }
    };
  }
};
module.exports.init(module);
const Article = require('../model/Article');
const File = require('../model/File');
const Photo = require('../model/Photo');
Создание фото

Метод actionCreate создает модель фотографии. Массив асинхронных методов async.series получает данные для списка выбора статьи Article.findToSelect, к которой может быть привязано фото.

module/admin/controllers/PhotoController.js

async actionCreate () {
  let model = new Photo;
  model.scenario = 'create';
  if (this.isPost() && model.load(this.getBodyParams()).save()) {
    return this.backToRef();
  }
  await this.render('create', {
    articles: await Article.findToSelect().all(),
    model
  });
}
Просмотр загруженного фото

Метод actionView вызывает родительский метод для загрузки необходимых отношений.

module/admin/controllers/PhotoController.js

async actionView () {
  await super.actionView({
    with: ['article']
  });
}
Редактирование фото

Метод actionUpload сохраняет загруженный файл на сервер. Если файл проходит проверку, то из него создается модель фотографии, не привязанная к статье.

module/admin/controllers/PhotoController.js

async actionUpload () {
  let file = new File;
  if (!await file.upload(this)) {
    return this.sendText(this.translate(file.getFirstError()), 400);
  }
  let photo = new Photo;
  photo.set('file', file.getId());
  await photo.validate(['file'])
    ? this.sendText(file.getId())
    : this.sendText(this.translate(photo.getFirstError()), 400);
}

Метод actionAssignMain устанавливает фото как главное в статье. Сохранение статьи осуществляется через метод forceSave, который не производит валидацию модели. Если у фотографии нет связанной статьи, то устанавливается flash-сообщение об ощибке (одноразовое сообщение в пользовательской сессии) и идет переадресация на страницу просмотра фото.

module/admin/controllers/PhotoController.js

async actionAssignMain () {
  let model = await this.getModel({
    with: ['article']
  });
  let article = model.get('article');
  if (!article) {
    this.setFlash('danger', 'Article not found');
    return this.redirect(['view', model]);
  }
  article.set('mainPhotoId', model.getId());
  await article.forceSave();
  this.redirect(['article/view', article]);
}