<?php 
/** 
 * Pimcore 
 * 
 * This source file is available under two different licenses: 
 * - GNU General Public License version 3 (GPLv3) 
 * - Pimcore Enterprise License (PEL) 
 * Full copyright and license information is available in 
 * LICENSE.md which is distributed with this source code. 
 * 
 * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org) 
 * @license    http://www.pimcore.org/license     GPLv3 and PEL 
 */ 
 
namespace Pimcore\Controller; 
 
use Pimcore\Controller\Traits\TemplateControllerTrait; 
use Pimcore\Http\Request\Resolver\DocumentResolver; 
use Pimcore\Http\Request\Resolver\EditmodeResolver; 
use Pimcore\Http\Request\Resolver\ResponseHeaderResolver; 
use Pimcore\Http\Request\Resolver\ViewModelResolver; 
use Pimcore\Model\Document; 
use Pimcore\Templating\Model\ViewModel; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; 
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 
 
/** 
 * @property ViewModel $view 
 * @property Document|Document\PageSnippet $document 
 * @property bool $editmode 
 */ 
abstract class FrontendController extends Controller implements EventedControllerInterface, TemplateControllerInterface 
{ 
    use TemplateControllerTrait; 
 
    /** 
     * Expose view, document and editmode as properties and proxy them to request attributes through 
     * their resolvers. 
     * 
     * @inheritDoc 
     */ 
    public function __get($name) 
    { 
        if ('view' === $name) { 
            return $this->get(ViewModelResolver::class)->getViewModel(); 
        } 
 
        if ('document' === $name) { 
            return $this->get(DocumentResolver::class)->getDocument(); 
        } 
 
        if ('editmode' === $name) { 
            return $this->get(EditmodeResolver::class)->isEditmode(); 
        } 
 
        throw new \RuntimeException(sprintf('Trying to read undefined property "%s"', $name)); 
    } 
 
    /** 
     * @inheritDoc 
     */ 
    public function __set($name, $value) 
    { 
        $requestAttributes = ['view', 'document', 'editmode']; 
        if (in_array($name, $requestAttributes)) { 
            throw new \RuntimeException(sprintf( 
                'Property "%s" is a request attribute and can\'t be set on the controller instance', 
                $name 
            )); 
        } 
 
        throw new \RuntimeException(sprintf('Trying to set unknown property "%s"', $name)); 
    } 
 
    /** 
     * @inheritDoc 
     */ 
    public function onKernelController(FilterControllerEvent $event) 
    { 
        // enable view auto-rendering 
        $this->setViewAutoRender($event->getRequest(), true, 'php'); 
    } 
 
    /** 
     * @inheritDoc 
     */ 
    public function onKernelResponse(FilterResponseEvent $event) 
    { 
    } 
 
    /** 
     * Enable view autorendering for the current request 
     * 
     * @param Request $request 
     * @param string $engine 
     */ 
    protected function enableViewAutoRender(Request $request = null, $engine = 'php') 
    { 
        if (null === $request) { 
            $request = $this->get('request_stack')->getCurrentRequest(); 
        } 
 
        $this->setViewAutoRender($request, true, $engine); 
    } 
 
    /** 
     * Disable view autorendering for the current request 
     * 
     * @param Request $request 
     */ 
    protected function disableViewAutoRender(Request $request = null) 
    { 
        if (null === $request) { 
            $request = $this->get('request_stack')->getCurrentRequest(); 
        } 
 
        $this->setViewAutoRender($request, false); 
    } 
 
    /** 
     * We don't have a response object at this point, but we can add headers here which will be 
     * set by the ResponseHeaderListener which reads and adds this headers in the kernel.response event. 
     * 
     * @param string $key 
     * @param array|string $values 
     * @param bool $replace 
     * @param Request|null $request 
     */ 
    protected function addResponseHeader(string $key, $values, bool $replace = false, Request $request = null) 
    { 
        if (null === $request) { 
            $request = $this->get('request_stack')->getCurrentRequest(); 
        } 
 
        $this->get(ResponseHeaderResolver::class)->addResponseHeader($request, $key, $values, $replace); 
    } 
 
    /** 
     * Loads a document editable 
     * 
     * e.g. `$this->getDocumentTag('input', 'foobar')` 
     * 
     * @param string $type 
     * @param string $inputName 
     * @param array $options 
     * @param Document\PageSnippet|null $document 
     * 
     * @return null|Document\Tag 
     */ 
    public function getDocumentTag($type, $inputName, array $options = [], Document\PageSnippet $document = null) 
    { 
        if (null === $document) { 
            $document = $this->document; 
        } 
 
        $tagRenderer = $this->container->get('pimcore.templating.tag_renderer'); 
 
        return $tagRenderer->getTag($document, $type, $inputName, $options); 
    } 
 
    /** 
     * @param string $view 
     * @param array $parameters 
     * @param Response|null $response 
     * 
     * @return \Symfony\Component\HttpFoundation\Response 
     */ 
    public function renderTemplate($view, array $parameters = [], Response $response = null) 
    { 
        $viewModel = $this->get(ViewModelResolver::class)->getViewModel(); 
        $parameters = array_merge($viewModel->getAllParameters(), $parameters); 
 
        return $this->render($view, $parameters, $response); 
    } 
}