<?php
namespace Cms\CoreBundle\Util;
use App\Controller\AbstractController;
use Cms\CoreBundle\Model\Interfaces\Lockable\LockableInterface;
use Cms\CoreBundle\Model\Scenes\DashboardScenes\AjaxScene;
use Cms\CoreBundle\Model\Scenes\DashboardScenes\DocumentScene;
use Cms\CoreBundle\Service\Locksmith;
use Cms\CoreBundle\Service\SceneRenderer;
use Cms\LogBundle\Service\LoggingService;
use ReflectionClass;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Class Controller
* @package Cms\CoreBundle\Util\Controller
*/
abstract class Controller extends AbstractController
{
/**
* @param LockableInterface $entity
* @param string|null $link
* @return Response|null
*/
protected function trapLocked(LockableInterface $entity, ?string $link = null): ?Response
{
$obtained = $this->getLocksmith()->obtainLock($entity);
if ($obtained !== true) {
$scene = new DocumentScene(
'@CmsCore/error.html.twig',
array(
'title' => 'Resource is Locked',
'body' => sprintf(
'<p>The user <strong>%s</strong> has locked this resource for modification. Please contact a system administrator for help if you believe this is an error.</p>',
$entity->getLockedBy()->getEmail()
),
'link' => ( ! empty($link)) ? $link : '/_dashboard',
)
);
$content = $this->getSceneRenderer()->render($scene);
return new Response(
$content,
500,
array(
'Content-Type' => 'text/html',
)
);
}
return null;
}
/**
* @param Request|null $request
* @return bool
*/
protected function handleSubmission(Request $request = null): bool
{
// if no request, get the current one
if ($request === null) {
// TODO: do we want the current or the master?
$request = $this->getRequest();
}
// determine if it was submitted and if it was valid
return ($request->isMethod(Request::METHOD_POST));
}
/**
* @param Request|null $request
* @return bool
*/
protected function handleBulk(Request $request = null): bool
{
// if no request, get the current one
if ($request === null) {
// TODO: do we want the current or the master?
$request = $this->getRequest();
}
// see if we have a process field given
return ($request->request->get('process', false) == true);
}
/**
* @param Request|null $request
* @return bool
*/
protected function handleSecureDelete(Request $request = null): bool
{
// if no request, get the current one
if ($request === null) {
// TODO: do we want the current or the master?
$request = $this->getRequest();
}
// determine if it was submitted and if it was valid
if ($request->isMethod(Request::METHOD_POST)) {
// there should be a "secure" field
$secure = $request->request->get('secure');
// check for value
if ($secure !== null && strtoupper(trim($secure)) === 'DELETE') {
// good input
return true;
}
}
// not good
return false;
}
/**
* @return array
*/
protected static function routing(): array
{
$refl = new ReflectionClass(static::class);
$routes = [];
foreach ($refl->getConstants() as $key => $value) {
if (preg_match('/^ROUTES__(.+)/', $key, $matches) === 1) {
$routes[strtolower($matches[1])] = $value;
}
}
return $routes;
}
/**
* @param string|array|null $template
* @param array $parameters
* @return DocumentScene
*/
public function view($template = null, array $parameters = []): DocumentScene
{
// handle standard naming conventions
if (is_array($template)) {
$parameters = $template;
$template = null;
}
// get the route constants on our controller
if (isset($parameters['routes']) === false) {
$parameters['routes'] = [];
}
$refl = new ReflectionClass($this);
foreach ($refl->getConstants() as $key => $value) {
if (preg_match('/^ROUTES__.+/', $key) === 1) {
$key = strtolower(preg_replace('/^ROUTES__(.+)$/', '$1', $key));
$parameters['routes'][$key] = $value;
}
}
// track stuff
[$cls, $func] = explode(
'::',
$this->getRequest()->attributes->get('_controller')
);
$func = preg_replace('/Action$/', '', $func);
if ($func === null || $cls === null) {
throw new \LogicException();
}
// fill in view based on standards if not given
if ($template === null || $template === '') {
$template = $func;
}
// add stuff if not given
if (preg_match('/^(Cms|Platform|Products)\\\\(.+?)Bundle\\\\Controller\\\\(.+?)Controller$/', $cls, $cpieces) !== 1) {
throw new \LogicException();
}
// TODO: this logic may need further modification due to the change of Twig naming patterns...
if ($template === $func) {
$template = str_replace('\\', '/', $cpieces[3]).'/'.$template;
$template = '@'.$cpieces[1].str_replace(['\\', '/'], ['', ''], $cpieces[2]).'/'.$template;
}
// TODO: this logic may need further modification due to the change of Twig naming patterns...
// assume html and twig if nothing is given
if (substr_count($template, '.') === 0) {
$template .= '.html';
}
if (substr_count($template, '.') === 1) {
$template .= '.twig';
}
// create the view with the view layer
return new DocumentScene(
$template,
$parameters
);
}
/**
* @param string|array|null $template
* @param array $parameters
* @return AjaxScene
* @throws \Exception
*/
public function viewAjax($template = null, array $parameters = []): AjaxScene
{
// handle standard naming conventions
if (is_array($template)) {
$parameters = $template;
$template = null;
}
// get the route constants on our controller
if (isset($parameters['routes']) === false) {
$parameters['routes'] = [];
}
$refl = new ReflectionClass($this);
foreach ($refl->getConstants() as $key => $value) {
if (preg_match('/^ROUTES__.+/', $key) === 1) {
$key = strtolower(preg_replace('/^ROUTES__(.+)$/', '$1', $key));
$parameters['routes'][$key] = $value;
}
}
// track stuff
[$cls, $func] = explode(
'::',
$this->getRequest()->attributes->get('_controller')
);
$func = preg_replace('/Action$/', '', $func);
if ($func === null || $cls === null) {
throw new \LogicException();
}
// fill in view based on standards if not given
if ($template === null || $template === '') {
$template = $func;
}
// add stuff if not given
if (preg_match('/^(Cms|Platform|Products)\\\\(.+?)Bundle\\\\Controller\\\\(.+?)Controller$/', $cls, $cpieces) !== 1) {
throw new \LogicException();
}
// TODO: this logic may need further modification due to the change of Twig naming patterns...
if ($template === $func) {
$template = str_replace('\\', '/', $cpieces[3]).'/'.$template;
$template = '@'.$cpieces[1].str_replace(['\\', '/'], ['', ''], $cpieces[2]).'/'.$template;
}
// TODO: this logic may need further modification due to the change of Twig naming patterns...
// assume html and twig if nothing is given
if (substr_count($template, '.') === 0) {
$template .= '.html';
}
if (substr_count($template, '.') === 1) {
$template .= '.twig';
}
// create the view with the view layer
return new AjaxScene(
$template,
$parameters
);
}
/**
* {@inheritdoc}
*/
public function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
{
if (isset($parameters['return'])) {
return $this->redirect($parameters['return'], $status);
}
return parent::redirectToRoute($route, $parameters, $status);
}
/**
* @param string $route
* @param array $parameters
* @param int $status
* @return RedirectResponse
*/
public function redirectToRouteOrOverride(string $route, array $parameters = [], int $status = 302): RedirectResponse
{
$request = $this->getRequest();
if ($request->query->has('redirectTo')) {
return $this->redirect($request->query->get('redirectTo'), $status);
}
return $this->redirectToRoute($route, $parameters, $status);
}
/**
* @return Locksmith|object
*/
protected function getLocksmith(): Locksmith
{
return $this->get(__METHOD__);
}
/**
* @return SceneRenderer|object
*/
protected function getSceneRenderer(): SceneRenderer
{
return $this->get(__METHOD__);
}
/**
* @return LoggingService|object
*/
protected function getActivityLogger(): LoggingService
{
return $this->get(__METHOD__);
}
}