<?php

use Acms\Services\Facades\LocalStorage;
use Acms\Services\Facades\Common;
use Acms\Services\Facades\Logger;
use Acms\Services\Facades\Application as App;
use Acms\Services\ConfigSet\Export;
use Acms\Services\ConfigSet\Repository;
use Acms\Services\ConfigSet\Authorization;

/**
 * コンフィグセット単体のエクスポート（CMS-7831）。
 *
 * フォームのエクスポート（ACMS_POST_Form_Export）と同じ作法で、
 * ACMS_POST_Config_Export（download/putYaml/$yaml/$destPath）を再利用する。
 */
class ACMS_POST_Config_Set_Export extends ACMS_POST_Config_Export
{
    /**
     * @inheritDoc
     */
    public function post()
    {
        @set_time_limit(0);

        if (!$this->checkAuth()) {
            return $this->Post;
        }

        try {
            $configSetId = (int) $this->Get->get('setid', 0);
            if ($configSetId < 1) {
                return $this->Post;
            }

            $repository = App::make('config_set.repository');
            assert($repository instanceof Repository);
            $exportService = App::make('config_set.export');
            assert($exportService instanceof Export);

            // 現在のブログに属するコンフィグセットのみエクスポートを許可する
            $configSet = $repository->findRawById($configSetId);
            if ($configSet === null || (int) $configSet['config_set_blog_id'] !== BID) {
                $this->addError('コンフィグセットが見つかりません。');
                return $this->Post;
            }

            $this->yaml = $exportService->toYaml($configSetId);
            $this->destPath = CACHE_DIR . 'config_set.yaml';

            LocalStorage::remove($this->destPath);
            $this->putYaml();

            Logger::info('「' . $configSet['config_set_name'] . '」コンフィグセットをエクスポートしました');

            $this->download();
        } catch (\Exception $e) {
            $this->addError($e->getMessage());
            LocalStorage::remove($this->destPath);

            Logger::notice('コンフィグセットのエクスポートに失敗しました。' . $e->getMessage(), Common::exceptionArray($e));
        }

        return $this->Post;
    }

    /**
     * download yaml data
     *
     * @return void
     */
    protected function download()
    {
        if (!LocalStorage::exists($this->destPath)) {
            throw new RuntimeException('Can not read a yaml to a file.');
        }
        $file = 'config_set' . date('_Ymd_Hi') . '.yaml';
        $downloader = App::make('response.downloader');
        // handle() は @return never。assert で型を絞らないと「送出後に処理が続く」と解析される
        assert($downloader instanceof \Acms\Services\Response\FileDownloader);
        $downloader->handle($this->destPath, $file, false, true);
    }

    /**
     * check auth
     *
     * @inheritDoc
     */
    protected function checkAuth()
    {
        $authorization = App::make('config_set.authorization');
        assert($authorization instanceof Authorization);

        return $authorization->canManage((int) SUID, BID);
    }
}
