357 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
| <?php
 | |
| 
 | |
| declare(strict_types=1);
 | |
| 
 | |
| namespace Grav\Plugin\FlexObjects\Controllers;
 | |
| 
 | |
| use Grav\Common\Config\Config;
 | |
| use Grav\Common\Grav;
 | |
| use Grav\Common\Inflector;
 | |
| use Grav\Common\Language\Language;
 | |
| use Grav\Common\Session;
 | |
| use Grav\Common\Uri;
 | |
| use Grav\Common\User\Interfaces\UserInterface;
 | |
| use Grav\Common\Utils;
 | |
| use Grav\Framework\Controller\Traits\ControllerResponseTrait;
 | |
| use Grav\Framework\Flex\FlexDirectory;
 | |
| use Grav\Framework\Flex\FlexForm;
 | |
| use Grav\Framework\Flex\FlexFormFlash;
 | |
| use Grav\Framework\Flex\Interfaces\FlexFormInterface;
 | |
| use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
 | |
| use Grav\Framework\Psr7\Response;
 | |
| use Grav\Framework\RequestHandler\Exception\NotFoundException;
 | |
| use Grav\Framework\RequestHandler\Exception\PageExpiredException;
 | |
| use Grav\Framework\Route\Route;
 | |
| use Grav\Plugin\FlexObjects\Flex;
 | |
| use Psr\Http\Message\ResponseInterface;
 | |
| use Psr\Http\Message\ServerRequestInterface;
 | |
| use Psr\Http\Server\RequestHandlerInterface;
 | |
| use RocketTheme\Toolbox\Event\Event;
 | |
| use RocketTheme\Toolbox\Session\Message;
 | |
| use function in_array;
 | |
| use function is_callable;
 | |
| 
 | |
| /**
 | |
|  * Class AbstractController
 | |
|  * @package Grav\Plugin\FlexObjects\Controllers
 | |
|  */
 | |
| abstract class AbstractController implements RequestHandlerInterface
 | |
| {
 | |
|     use ControllerResponseTrait;
 | |
| 
 | |
|     /** @var string */
 | |
|     protected $nonce_action = 'flex-object';
 | |
|     /** @var string */
 | |
|     protected $nonce_name = 'nonce';
 | |
|     /** @var ServerRequestInterface */
 | |
|     protected $request;
 | |
|     /** @var Grav */
 | |
|     protected $grav;
 | |
|     /** @var UserInterface|null */
 | |
|     protected $user;
 | |
|     /** @var string */
 | |
|     protected $type;
 | |
|     /** @var string */
 | |
|     protected $key;
 | |
|     /** @var FlexDirectory */
 | |
|     protected $directory;
 | |
|     /** @var FlexObjectInterface */
 | |
|     protected $object;
 | |
| 
 | |
|     /**
 | |
|      * Handle request.
 | |
|      *
 | |
|      * Fires event: flex.[directory].[task|action].[command]
 | |
|      *
 | |
|      * @param ServerRequestInterface $request
 | |
|      * @return Response
 | |
|      */
 | |
|     public function handle(ServerRequestInterface $request): ResponseInterface
 | |
|     {
 | |
|         $attributes = $request->getAttributes();
 | |
|         $this->request = $request;
 | |
|         $this->grav = $attributes['grav'] ?? Grav::instance();
 | |
|         $this->type =  $attributes['type'] ?? null;
 | |
|         $this->key =  $attributes['key'] ?? null;
 | |
|         if ($this->type) {
 | |
|             $this->directory = $this->getFlex()->getDirectory($this->type);
 | |
|             $this->object = $attributes['object'] ?? null;
 | |
|             if (!$this->object && $this->key && $this->directory) {
 | |
|                 $this->object = $this->directory->getObject($this->key) ?? $this->directory->createObject([], $this->key ?? '');
 | |
|                 if (is_callable([$this->object, 'refresh'])) {
 | |
|                     $this->object->refresh();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /** @var Route $route */
 | |
|         $route = $attributes['route'];
 | |
|         $post = $this->getPost();
 | |
| 
 | |
|         if ($this->isFormSubmit()) {
 | |
|             $form = $this->getForm();
 | |
|             $this->nonce_name = $attributes['nonce_name'] ?? $form->getNonceName();
 | |
|             $this->nonce_action = $attributes['nonce_action'] ?? $form->getNonceAction();
 | |
|         }
 | |
| 
 | |
|         try {
 | |
|             $task = $request->getAttribute('task') ?? $post['task'] ?? $route->getParam('task');
 | |
|             if ($task) {
 | |
|                 if (empty($attributes['forwarded'])) {
 | |
|                     $this->checkNonce($task);
 | |
|                 }
 | |
|                 $type = 'task';
 | |
|                 $command = $task;
 | |
|             } else {
 | |
|                 $type = 'action';
 | |
|                 $command = $request->getAttribute('action') ?? $post['action'] ?? $route->getParam('action') ?? 'display';
 | |
|             }
 | |
|             $command = strtolower($command);
 | |
| 
 | |
|             $event = new Event(
 | |
|                 [
 | |
|                     'controller' => $this,
 | |
|                     'response' => null
 | |
|                 ]
 | |
|             );
 | |
| 
 | |
|             $this->grav->fireEvent("flex.{$this->type}.{$type}.{$command}", $event);
 | |
| 
 | |
|             $response = $event['response'];
 | |
|             if (!$response) {
 | |
|                 /** @var Inflector $inflector */
 | |
|                 $inflector = $this->grav['inflector'];
 | |
|                 $method = $type . $inflector::camelize($command);
 | |
|                 if ($method && method_exists($this, $method)) {
 | |
|                     $response = $this->{$method}($request);
 | |
|                 } else {
 | |
|                     throw new NotFoundException($request);
 | |
|                 }
 | |
|             }
 | |
|         } catch (\Exception $e) {
 | |
|             $response = $this->createErrorResponse($e);
 | |
|         }
 | |
| 
 | |
|         if ($response instanceof Response) {
 | |
|             return $response;
 | |
|         }
 | |
| 
 | |
|         return $this->createJsonResponse($response);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return ServerRequestInterface
 | |
|      */
 | |
|     public function getRequest(): ServerRequestInterface
 | |
|     {
 | |
|         return $this->request;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param string|null $name
 | |
|      * @param mixed $default
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function getPost(string $name = null, $default = null)
 | |
|     {
 | |
|         $body = $this->request->getParsedBody();
 | |
| 
 | |
|         if ($name) {
 | |
|             return $body[$name] ?? $default;
 | |
|         }
 | |
| 
 | |
|         return $body;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isFormSubmit(): bool
 | |
|     {
 | |
|         return (bool)$this->getPost('__form-name__');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param string|null $type
 | |
|      * @return FlexForm
 | |
|      */
 | |
|     public function getForm(string $type = null): FlexFormInterface
 | |
|     {
 | |
|         $object = $this->getObject();
 | |
|         if (!$object) {
 | |
|             throw new \RuntimeException('Not Found', 404);
 | |
|         }
 | |
| 
 | |
|         $formName = $this->getPost('__form-name__');
 | |
|         $uniqueId = $this->getPost('__unique_form_id__') ?: $formName;
 | |
| 
 | |
|         $form = $object->getForm($type ?? 'edit');
 | |
|         if ($uniqueId) {
 | |
|             $form->setUniqueId($uniqueId);
 | |
|         }
 | |
| 
 | |
|         return $form;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param FlexObjectInterface $object
 | |
|      * @param string $type
 | |
|      * @return FlexFormFlash
 | |
|      */
 | |
|     protected function getFormFlash(FlexObjectInterface $object, string $type = '')
 | |
|     {
 | |
|         /** @var Uri $uri */
 | |
|         $uri = $this->grav['uri'];
 | |
|         $url = $uri->url;
 | |
| 
 | |
|         $formName = $this->getPost('__form-name__');
 | |
|         if (!$formName) {
 | |
|             $form = $object->getForm($type);
 | |
|             $formName = $form->getName();
 | |
|             $uniqueId = $form->getUniqueId();
 | |
|         } else {
 | |
|             $uniqueId = $this->getPost('__unique_form_id__') ?: $formName ?: sha1($url);
 | |
|         }
 | |
| 
 | |
|         /** @var Session $session */
 | |
|         $session = $this->grav['session'];
 | |
| 
 | |
|         $config = [
 | |
|             'session_id' => $session->getId(),
 | |
|             'unique_id' => $uniqueId,
 | |
|             'form_name' => $formName,
 | |
|         ];
 | |
|         $flash = new FlexFormFlash($config);
 | |
|         if (!$flash->exists()) {
 | |
|             $flash->setUrl($url)->setUser($this->grav['user']);
 | |
|         }
 | |
| 
 | |
|         return $flash;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return Grav
 | |
|      */
 | |
|     public function getGrav(): Grav
 | |
|     {
 | |
|         return $this->grav;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return Session
 | |
|      */
 | |
|     public function getSession(): Session
 | |
|     {
 | |
|         return $this->grav['session'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return Flex
 | |
|      */
 | |
|     public function getFlex(): Flex
 | |
|     {
 | |
|         return $this->grav['flex_objects'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return string
 | |
|      */
 | |
|     public function getDirectoryType(): string
 | |
|     {
 | |
|         return $this->type;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return string
 | |
|      */
 | |
|     public function getObjectKey(): string
 | |
|     {
 | |
|         return $this->key;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return FlexDirectory|null
 | |
|      */
 | |
|     public function getDirectory(): ?FlexDirectory
 | |
|     {
 | |
|         return $this->directory;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return FlexObjectInterface|null
 | |
|      */
 | |
|     public function getObject(): ?FlexObjectInterface
 | |
|     {
 | |
|         return $this->object;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param string $string
 | |
|      * @return string
 | |
|      */
 | |
|     public function translate(string $string): string
 | |
|     {
 | |
|         /** @var Language $language */
 | |
|         $language = $this->grav['language'];
 | |
| 
 | |
|         return $language->translate($string);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param string $message
 | |
|      * @param string $type
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setMessage(string $message, string $type = 'info'): self
 | |
|     {
 | |
|         /** @var Message $messages */
 | |
|         $messages = $this->grav['messages'];
 | |
|         $messages->add($message, $type);
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param UserInterface $user
 | |
|      * @return void
 | |
|      */
 | |
|     public function setUser(UserInterface $user): void
 | |
|     {
 | |
|         $this->user = $user;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return Config
 | |
|      */
 | |
|     protected function getConfig(): Config
 | |
|     {
 | |
|         return $this->grav['config'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param string $task
 | |
|      * @return void
 | |
|      * @throws PageExpiredException
 | |
|      */
 | |
|     protected function checkNonce(string $task): void
 | |
|     {
 | |
|         $nonce = null;
 | |
| 
 | |
|         if (in_array(strtoupper($this->request->getMethod()), ['POST', 'PUT', 'PATCH', 'DELETE'])) {
 | |
|             $nonce = $this->getPost($this->nonce_name);
 | |
|         }
 | |
| 
 | |
|         if (!$nonce) {
 | |
|             $nonce = $this->grav['uri']->param($this->nonce_name);
 | |
|         }
 | |
| 
 | |
|         if (!$nonce) {
 | |
|             $nonce = $this->grav['uri']->query($this->nonce_name);
 | |
|         }
 | |
| 
 | |
|         if (!$nonce || !Utils::verifyNonce($nonce, $this->nonce_action)) {
 | |
|             throw new PageExpiredException($this->request);
 | |
|         }
 | |
|     }
 | |
| }
 |