getForm(); $object = $form->getObject(); return $object->exists() ? $this->taskUpdate($request) : $this->taskCreate($request); } /** * Create object. * * Task fails if object exists. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskCreate(ServerRequestInterface $request): ResponseInterface { $this->checkAuthorization('create'); $form = $this->getForm(); $callable = function (array $data, array $files, FlexObject $object) { if (method_exists($object, 'storeOriginal')) { $object->storeOriginal(); } $object->update($data, $files); if (\is_callable([$object, 'check'])) { $object->check($this->user); } $object->save(); }; $form->setSubmitMethod($callable); $form->handleRequest($request); if (!$form->isValid()) { $error = $form->getError(); if ($error) { $this->setMessage($error, 'error'); } $errors = $form->getErrors(); foreach ($errors as $field) { foreach ($field as $error) { $this->setMessage($error, 'error'); } } $data = $form->getData(); if (null !== $data) { $object = $form->getObject(); $flash = $form->getFlash(); $flash->setObject($object); $flash->setData($data->toArray()); $flash->save(); } return $this->createDisplayResponse(); } // FIXME: make it conditional $grav = $this->grav; $grav->fireEvent('gitsync'); $this->object = $form->getObject(); $event = new Event( [ 'controller' => $this, 'object' => $this->object, 'response' => null, 'message' => null, ] ); $this->grav->fireEvent("flex.{$this->type}.task.create.after", $event); $this->setMessage($event['message'] ?? $this->translate('PLUGIN_FLEX_OBJECTS.STATE.CREATED_SUCCESSFULLY'), 'info'); if ($event['response']) { return $event['response']; } $redirect = $request->getAttribute('redirect', (string)$request->getUri()); return $this->createRedirectResponse($redirect, 303); } /** * Update object. * * Task fails if object does not exist. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskUpdate(ServerRequestInterface $request): ResponseInterface { $this->checkAuthorization('update'); $form = $this->getForm(); $callable = function (array $data, array $files, FlexObject $object) { if (method_exists($object, 'storeOriginal')) { $object->storeOriginal(); } $object->update($data, $files); if (\is_callable([$object, 'check'])) { $object->check($this->user); } $object->save(); }; $form->setSubmitMethod($callable); $form->handleRequest($request); if (!$form->isValid()) { $error = $form->getError(); if ($error) { $this->setMessage($error, 'error'); } $errors = $form->getErrors(); foreach ($errors as $field) { foreach ($field as $error) { $this->setMessage($error, 'error'); } } $data = $form->getData(); if (null !== $data) { $object = $form->getObject(); $flash = $form->getFlash(); $flash->setObject($object); $flash->setData($data->toArray()); $flash->save(); } return $this->createDisplayResponse(); } // FIXME: make it conditional $grav = $this->grav; $grav->fireEvent('gitsync'); $this->object = $form->getObject(); $event = new Event( [ 'controller' => $this, 'object' => $this->object, 'response' => null, 'message' => null, ] ); $this->grav->fireEvent("flex.{$this->type}.task.update.after", $event); $this->setMessage($event['message'] ?? $this->translate('PLUGIN_FLEX_OBJECTS.STATE.UPDATED_SUCCESSFULLY'), 'info'); if ($event['response']) { return $event['response']; } $redirect = $request->getAttribute('redirect', (string)$request->getUri()->getPath()); return $this->createRedirectResponse($redirect, 303); } /** * Delete object. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskDelete(ServerRequestInterface $request): ResponseInterface { $this->checkAuthorization('delete'); $object = $this->getObject(); if (!$object) { throw new RuntimeException('Not Found', 404); } $object->delete(); // FIXME: make it conditional $grav = $this->grav; $grav->fireEvent('gitsync'); $event = new Event( [ 'controller' => $this, 'object' => $object, 'response' => null, 'message' => null, ] ); $this->grav->fireEvent("flex.{$this->type}.task.delete.after", $event); $this->setMessage($this->translate($event['message'] ?? 'PLUGIN_FLEX_OBJECTS.STATE.DELETED_SUCCESSFULLY'), 'info'); if ($event['response']) { return $event['response']; } $redirect = $request->getAttribute('redirect', (string)$request->getUri()->getPath()); return $this->createRedirectResponse($redirect, 303); } /** * Reset form to original values. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskReset(ServerRequestInterface $request): ResponseInterface { $this->checkAuthorization('save'); $flash = $this->getForm()->getFlash(); $flash->delete(); $redirect = $request->getAttribute('redirect', (string)$request->getUri()->getPath()); return $this->createRedirectResponse($redirect, 303); } /** * Preview object. * * Takes a form input and converts it to visible presentation of the object. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskPreview(ServerRequestInterface $request): ResponseInterface { $this->checkAuthorization('save'); /** @var FlexForm $form */ $form = $this->getForm('edit'); $form->setRequest($request); if (!$form->validate()) { $error = $form->getError(); if ($error) { $this->setMessage($error, 'error'); } $errors = $form->getErrors(); foreach ($errors as $field) { foreach ($field as $error) { $this->setMessage($error, 'error'); } } return $this->createRedirectResponse((string)$request->getUri(), 303); } $this->object = $form->updateObject(); return $this->actionDisplayPreview(); } /** * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskMediaList(ServerRequestInterface $request): ResponseInterface { $directory = $this->getDirectory(); if (!$directory) { throw new RuntimeException('Not Found', 404); } return $this->forwardMediaTask('action', 'media.list'); } /** * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskMediaUpload(ServerRequestInterface $request): ResponseInterface { $directory = $this->getDirectory(); if (!$directory) { throw new RuntimeException('Not Found', 404); } return $this->forwardMediaTask('task', 'media.upload'); } /** * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskMediaDelete(ServerRequestInterface $request): ResponseInterface { $directory = $this->getDirectory(); if (!$directory) { throw new RuntimeException('Not Found', 404); } return $this->forwardMediaTask('task', 'media.delete'); } /** * @param ServerRequestInterface $request * @return ResponseInterface */ public function taskGetFilesInFolder(ServerRequestInterface $request): ResponseInterface { $directory = $this->getDirectory(); if (!$directory) { throw new RuntimeException('Not Found', 404); } return $this->forwardMediaTask('action', 'media.picker'); } /** * @param ServerRequestInterface $request * @return ResponseInterface * @deprecated Do not use */ public function taskFilesUpload(ServerRequestInterface $request): ResponseInterface { /** @var Route $route */ $route = $this->grav['route']; if ($route->getParam('task') === 'media.upload') { return $this->taskMediaUpload($request); } throw new RuntimeException('Task filesUpload should not be called, please update form plugin!', 400); } /** * @param ServerRequestInterface $request * @return ResponseInterface * @deprecated Do not use */ public function taskRemoveMedia(ServerRequestInterface $request): ResponseInterface { /** @var Route $route */ $route = $this->grav['route']; if ($route->getParam('task') === 'media.delete') { return $this->taskMediaDelete($request); } throw new RuntimeException('Task removeMedia should not be called, please update form plugin!', 400); } /** * Display object preview. * * @return ResponseInterface */ public function actionDisplayPreview(): ResponseInterface { $this->checkAuthorization('save'); $this->checkAuthorization('read'); $object = $this->getObject(); if (!$object) { throw new RuntimeException('No object found!', 404); } $grav = Grav::instance(); $grav['twig']->init(); $grav['theme']; $content = [ 'code' => 200, 'id' => $object->getKey(), 'exists' => $object->exists(), 'html' => (string)$object->render('preview', ['nocache' => []]) ]; $accept = $this->getAccept(['application/json', 'text/html']); if ($accept === 'text/html') { return $this->createHtmlResponse($content['html']); } if ($accept === 'application/json') { return $this->createJsonResponse($content); } throw new RuntimeException('Not found', 404); } /** * @param string $action * @return void * @throws RuntimeException */ public function checkAuthorization(string $action): void { $object = $this->getObject(); if (!$object) { throw new RuntimeException('Not Found', 404); } if ($object instanceof FlexAuthorizeInterface) { if (!$object->isAuthorized($action, null, $this->user)) { throw new RuntimeException('Forbidden', 403); } } } /** * @param string[] $actions * @return void * @throws RuntimeException */ public function checkAuthorizations(array $actions): void { $object = $this->getObject(); if (!$object) { throw new RuntimeException('Not Found', 404); } if ($object instanceof FlexAuthorizeInterface) { $test = false; foreach ($actions as $action) { $test |= $object->isAuthorized($action, null, $this->user); } if (!$test) { throw new RuntimeException('Forbidden', 403); } } } /** * @param string $type * @param string $name * @return ResponseInterface */ protected function forwardMediaTask(string $type, string $name): ResponseInterface { /** @var Route $route */ $route = $this->grav['route']->withGravParam('task', null)->withGravParam($type, $name); $object = $this->getObject(); /** @var ServerRequest $request */ $request = $this->grav['request']; $request = $request ->withAttribute($type, $name) ->withAttribute('type', $this->type) ->withAttribute('key', $this->key) ->withAttribute('storage_key', $object && $object->exists() ? $object->getStorageKey() : null) ->withAttribute('route', $route) ->withAttribute('forwarded', true) ->withAttribute('object', $object); $controller = new MediaController(); if ($this->user) { $controller->setUser($this->user); } return $controller->handle($request); } }