Skip to content
Snippets Groups Projects
Commit 30fe55e4 authored by Marcus Eibrink-Lunzenauer's avatar Marcus Eibrink-Lunzenauer
Browse files

Add JSONAPI routes.

parent 67bee38a
Branches
No related tags found
No related merge requests found
Showing
with 691 additions and 41 deletions
...@@ -11,6 +11,13 @@ ...@@ -11,6 +11,13 @@
interface FeedbackRange interface FeedbackRange
{ {
/**
* Returns the ID of this range.
*
* @return string|integer The ID of the range.
*/
public function getId();
/** /**
* Returns a human-friendly representation of the FeedbackRange object instance's name. * Returns a human-friendly representation of the FeedbackRange object instance's name.
* *
......
...@@ -239,12 +239,20 @@ class RouteMap ...@@ -239,12 +239,20 @@ class RouteMap
private function addAuthenticatedFeedbackRoutes(RouteCollectorProxy $group): void private function addAuthenticatedFeedbackRoutes(RouteCollectorProxy $group): void
{ {
$group->get('/feedback-elements/{id}', Routes\Feedback\FeedbackElementsShow::class); $group->get('/feedback-elements/{id}', Routes\Feedback\FeedbackElementsShow::class);
$group->get('/feedback-elements/{id}/entries', Routes\Feedback\FeedbackEntriesIndex::class);
$group->get('/courses/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByCourseIndex::class); $group->get('/courses/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByCourseIndex::class);
$group->get('/file-refs/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByFileRefIndex::class); $group->get('/file-refs/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByFileRefIndex::class);
$group->get('/folders/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByFolderIndex::class); $group->get('/folders/{id}/feedback-elements', Routes\Feedback\FeedbackElementsByFolderIndex::class);
$group->post('/feedback-elements', Routes\Feedback\FeedbackElementsCreate::class);
$group->patch('/feedback-elements/{id}', Routes\Feedback\FeedbackElementsUpdate::class);
$group->delete('/feedback-elements/{id}', Routes\Feedback\FeedbackElementsDelete::class);
$group->get('/feedback-elements/{id}/entries', Routes\Feedback\FeedbackEntriesIndex::class);
$group->post('/feedback-entries', Routes\Feedback\FeedbackEntriesCreate::class);
$group->get('/feedback-entries/{id}', Routes\Feedback\FeedbackEntriesShow::class); $group->get('/feedback-entries/{id}', Routes\Feedback\FeedbackEntriesShow::class);
$group->patch('/feedback-entries/{id}', Routes\Feedback\FeedbackEntriesUpdate::class);
$group->delete('/feedback-entries/{id}', Routes\Feedback\FeedbackEntriesDelete::class);
} }
private function addAuthenticatedInstitutesRoutes(RouteCollectorProxy $group): void private function addAuthenticatedInstitutesRoutes(RouteCollectorProxy $group): void
...@@ -299,7 +307,7 @@ class RouteMap ...@@ -299,7 +307,7 @@ class RouteMap
$group->get('/tree-node/{id}', Routes\Tree\TreeShow::class); $group->get('/tree-node/{id}', Routes\Tree\TreeShow::class);
$group->get('/tree-node/{id}/children', Routes\Tree\ChildrenOfTreeNode::class); $group->get('/tree-node/{id}/children', Routes\Tree\ChildrenOfTreeNode::class);
$group->get('/tree-node/{id}/courseinfo', Routes\Tree\CourseInfoOfTreeNode::class); $group->get('/tree-node/{id}/courseinfo', Routes\Tree\CourseinfoOfTreeNode::class);
$group->get('/tree-node/{id}/courses', Routes\Tree\CoursesOfTreeNode::class); $group->get('/tree-node/{id}/courses', Routes\Tree\CoursesOfTreeNode::class);
$group->get('/tree-node/course/pathinfo/{classname}/{id}', Routes\Tree\PathinfoOfTreeNodeCourse::class); $group->get('/tree-node/course/pathinfo/{classname}/{id}', Routes\Tree\PathinfoOfTreeNodeCourse::class);
$group->get('/tree-node/course/details/{id}', Routes\Tree\DetailsOfTreeNodeCourse::class); $group->get('/tree-node/course/details/{id}', Routes\Tree\DetailsOfTreeNodeCourse::class);
......
...@@ -2,45 +2,109 @@ ...@@ -2,45 +2,109 @@
namespace JsonApi\Routes\Feedback; namespace JsonApi\Routes\Feedback;
use Feedback;
use FeedbackElement;
use FeedbackEntry;
use FeedbackRange;
use SimpleORMap;
use User; use User;
/**
* @SuppressWarnings(PHPMD.StaticAccess)
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
*/
class Authority class Authority
{ {
public static function canShowFeedbackElement(User $user, \FeedbackElement $resource) public static function canShowFeedbackElement(User $user, FeedbackElement $resource): bool
{ {
return \Feedback::hasRangeAccess($resource->range_id, $resource->range_type, $user->id); return Feedback::hasRangeAccess($resource->range_id, $resource->range_type, $user->getId());
} }
public static function canIndexFeedbackEntries(User $user, \FeedbackElement $resource) public static function canIndexFeedbackEntries(User $user, FeedbackElement $resource): bool
{ {
return self::canShowFeedbackElement($user, $resource); return self::canShowFeedbackElement($user, $resource);
} }
public static function canSeeResultsOfFeedbackElement(User $user, \FeedbackElement $resource) public static function canSeeResultsOfFeedbackElement(User $user, FeedbackElement $resource): bool
{ {
return self::canIndexFeedbackEntries($user, $resource) && return self::canIndexFeedbackEntries($user, $resource) &&
($resource['results_visible'] || \Feedback::hasAdminPerm($resource['course_id'], $user->id)); ($resource['results_visible'] || \Feedback::hasAdminPerm($resource['course_id'], $user->getId()));
} }
public static function canIndexFeedbackElementsOfCourse(User $user, \Course $course) public static function canIndexFeedbackElementsOfCourse(User $user, \Course $course): bool
{ {
return \Feedback::hasRangeAccess($course->id, \Course::class, $user->id); return \Feedback::hasRangeAccess($course->getId(), \Course::class, $user->getId());
} }
public static function canIndexFeedbackElementsOfFileRef(User $user, \FileRef $fileRef) public static function canIndexFeedbackElementsOfFileRef(User $user, \FileRef $fileRef): bool
{ {
return \Feedback::hasRangeAccess($fileRef->id, \FileRef::class, $user->id); return \Feedback::hasRangeAccess($fileRef->getId(), \FileRef::class, $user->getId());
} }
public static function canIndexFeedbackElementsOfFolder(User $user, \Folder $folder) public static function canIndexFeedbackElementsOfFolder(User $user, \Folder $folder): bool
{ {
return \Feedback::hasRangeAccess($folder->id, \Folder::class, $user->id); return \Feedback::hasRangeAccess($folder->getId(), \Folder::class, $user->getId());
} }
public static function canShowFeedbackEntry(User $user, \FeedbackEntry $resource) public static function canShowFeedbackEntry(User $user, \FeedbackEntry $resource): bool
{ {
$feedbackElement = $resource->feedback; $feedbackElement = $resource->feedback;
return self::canShowFeedbackElement($user, $feedbackElement); return self::canShowFeedbackElement($user, $feedbackElement);
} }
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public static function canCreateFeedbackEntry(User $user, FeedbackElement $element): bool
{
if (!$element->isFeedbackable()) {
return false;
}
// TODO: Wann darf ich Feedback Entries schreiben
return true;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public static function canUpdateFeedbackEntry(User $user, FeedbackEntry $entry): bool
{
if (!$entry->isEditable()) {
return false;
}
// TODO: Wann darf ich Feedback Entries bearbeiten
return true;
}
public static function canDeleteFeedbackEntry(User $user, FeedbackEntry $entry): bool
{
return self::canUpdateFeedbackEntry($user, $entry);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public static function canCreateFeedbackElement(User $user, FeedbackRange $range): bool
{
// TODO: Wann darf ich Feedback Elemente anhängen
// bisher https://gitlab.studip.de/studip/studip/-/blob/main/lib/classes/Feedback.class.php#L76
return true;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public static function canUpdateFeedbackElement(User $user, FeedbackElement $element): bool
{
// TODO: Wann darf ich Feedback Elemente ändern?
return true;
}
public static function canDeleteFeedbackElement(User $user, FeedbackElement $element): bool
{
return self::canUpdateFeedbackElement($user, $element);
}
} }
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackElement;
use FeedbackRange;
use User;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\FeedbackElement as FeedbackElementSchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Create a FeedbackElement.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackElementsCreate extends JsonApiController
{
use RangeTypeAware;
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$this->preparePossibleRangeTypes();
$json = $this->validate($request);
$range = $this->getRangeFromJson($json);
$user = $this->getUser($request);
if (!Authority::canCreateFeedbackElement($user, $range)) {
throw new AuthorizationFailedException();
}
$feedbackElement = $this->create($user, $json);
return $this->getCreatedResponse($feedbackElement);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*
* @param array $json
* @param mixed $data
*
* @return string|void
*/
protected function validateResourceDocument($json, $data)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
if (FeedbackElementSchema::TYPE !== self::arrayGet($json, 'data.type')) {
return 'Invalid `type` of document´s `data`.';
}
if (self::arrayHas($json, 'data.id')) {
return 'New document must not have an `id`.';
}
$required = ['question', 'description', 'mode', 'results-visible', 'is-commentable'];
foreach ($required as $attribute) {
if (!self::arrayHas($json, 'data.attributes.' . $attribute)) {
return 'Missing `' . $attribute . '` attribute.';
}
}
if (!self::arrayHas($json, 'data.relationships.range')) {
return 'Missing `range` relationship.';
}
if (!$this->getRangeFromJson($json)) {
return 'Invalid `range` relationship.';
}
}
private function getRangeFromJson(array $json): ?FeedbackRange
{
$rangeType = self::arrayGet($json, 'data.relationships.range.data.type');
$rangeId = self::arrayGet($json, 'data.relationships.range.data.id');
if (!isset($this->possibleRangeTypes[$rangeType])) {
return null;
}
$rangeClass = $this->possibleRangeTypes[$rangeType];
return $rangeClass::find($rangeId);
}
private function create(User $user, array $json): FeedbackElement
{
$range = $this->getRangeFromJson($json);
$feedback = \FeedbackElement::build([
'range_id' => $range->getId(),
'range_type' => get_class($range),
'user_id' => $user->getId(),
'question' => self::arrayGet($json, 'data.attributes.question'),
'description' => self::arrayGet($json, 'data.attributes.description'),
'mode' => self::arrayGet($json, 'data.attributes.mode'),
'results_visible' => (int) self::arrayGet($json, 'data.attributes.results-visible'),
'commentable' => (int) self::arrayGet($json, 'data.attributes.is-commentable'),
// TODO:
'course_id' => $range->getRangeCourseId(),
]);
$feedback->store();
return $feedback;
}
}
<?php
namespace JsonApi\Routes\Feedback;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
/**
* Deletes a feedback element.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackElementsDelete extends JsonApiController
{
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$resource = \FeedbackElement::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
if (!Authority::canDeleteFeedbackElement($this->getUser($request), $resource)) {
throw new AuthorizationFailedException();
}
$resource->delete();
return $this->getCodeResponse(204);
}
}
...@@ -7,20 +7,33 @@ use Psr\Http\Message\ResponseInterface as Response; ...@@ -7,20 +7,33 @@ use Psr\Http\Message\ResponseInterface as Response;
use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException; use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController; use JsonApi\JsonApiController;
use JsonApi\Schemas\FeedbackElement as FeedbackElementSchema;
/** /**
* Displays a certain feedback element. * Displays a certain feedback element.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/ */
class FeedbackElementsShow extends JsonApiController class FeedbackElementsShow extends JsonApiController
{ {
protected $allowedIncludePaths = ['author', 'course', 'entries', 'range']; protected $allowedIncludePaths = [
FeedbackElementSchema::REL_AUTHOR,
FeedbackElementSchema::REL_COURSE,
FeedbackElementSchema::REL_ENTRIES,
FeedbackElementSchema::REL_RANGE,
];
/** /**
* @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/ */
public function __invoke(Request $request, Response $response, $args) public function __invoke(Request $request, Response $response, $args)
{ {
if (!$resource = \FeedbackElement::find($args['id'])) { $resource = \FeedbackElement::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException(); throw new RecordNotFoundException();
} }
......
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackElement;
use FeedbackRange;
use User;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\FeedbackElement as FeedbackElementSchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Update a FeedbackElement.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackElementsUpdate extends JsonApiController
{
use RangeTypeAware;
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$this->preparePossibleRangeTypes();
$resource = \FeedbackElement::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
$json = $this->validate($request);
$user = $this->getUser($request);
if (!Authority::canUpdateFeedbackElement($user, $resource)) {
throw new AuthorizationFailedException();
}
$feedbackElement = $this->update($resource, $json);
return $this->getContentResponse($feedbackElement);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*
* @param array $json
* @param mixed $data
*
* @return string|void
*/
protected function validateResourceDocument($json, $data)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
if (FeedbackElementSchema::TYPE !== self::arrayGet($json, 'data.type')) {
return 'Invalid `type` of document´s `data`.';
}
if (!self::arrayHas($json, 'data.id')) {
return 'An existing document must have an `id`.';
}
$required = ['question', 'description', 'mode', 'results-visible', 'is-commentable'];
foreach ($required as $attribute) {
if (!self::arrayHas($json, 'data.attributes.' . $attribute)) {
return 'Missing `' . $attribute . '` attribute.';
}
}
}
private function update(FeedbackElement $feedbackElement, array $json): FeedbackElement
{
$strAttrs = ['question', 'description', 'mode'];
foreach ($strAttrs as $attribute) {
if (self::arrayHas($json, 'data.attributes.' . $attribute)) {
$feedbackElement[$attribute] = self::arrayGet($json, 'data.attributes.' . $attribute);
}
}
$boolAttrs = ['results-visible', 'is-commentable'];
foreach ($boolAttrs as $attribute) {
if (self::arrayHas($json, 'data.attributes.' . $attribute)) {
$feedbackElement[$attribute] = self::arrayGet($json, 'data.attributes.' . $attribute) ? 1 : 0;
}
}
$feedbackElement->store();
return $feedbackElement;
}
}
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackElement;
use FeedbackEntry;
use InvalidArgumentException;
use User;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\FeedbackElement as FeedbackElementSchema;
use JsonApi\Schemas\FeedbackEntry as FeedbackEntrySchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Create a FeedbackEntry.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackEntriesCreate extends JsonApiController
{
use RatingHelper;
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$json = $this->validate($request);
$element = $this->getElementFromJson($json);
$user = $this->getUser($request);
if (!Authority::canCreateFeedbackEntry($user, $element)) {
throw new AuthorizationFailedException();
}
$feedbackEntry = $this->create($user, $json);
return $this->getCreatedResponse($feedbackEntry);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*
* @param array $json
* @param mixed $data
*
* @return string|void
*/
protected function validateResourceDocument($json, $data)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
if (FeedbackEntrySchema::TYPE !== self::arrayGet($json, 'data.type')) {
return 'Invalid `type` of document´s `data`.';
}
if (self::arrayHas($json, 'data.id')) {
return 'New document must not have an `id`.';
}
if (!self::arrayHas($json, 'data.relationships.feedback-element')) {
return 'Missing `feedback-element` relationship.';
}
if (!$this->getElementFromJson($json)) {
return 'Invalid `feedback-element` relationship.';
}
$required = ['rating'];
foreach ($required as $attribute) {
if (!self::arrayHas($json, 'data.attributes.' . $attribute)) {
return 'Missing `' . $attribute . '` attribute.';
}
}
}
private function getElementFromJson(array $json): ?FeedbackElement
{
$relationship = FeedbackEntrySchema::REL_FEEDBACK;
if (!$this->validateResourceObject($json, 'data.relationships.' . $relationship, FeedbackElementSchema::TYPE)) {
return null;
}
$resourceId = self::arrayGet($json, 'data.relationships.' . $relationship . '.data.id');
return FeedbackElement::find($resourceId);
}
private function create(User $user, array $json): FeedbackEntry
{
$element = $this->getElementFromJson($json);
$entry = \FeedbackEntry::build([
'feedback_id' => $element->getId(),
'user_id' => $user->getId(),
'rating' => $this->getRating($element, (int) self::arrayGet($json, 'data.attributes.rating')),
]);
if ($element['commentable']) {
$entry['comment'] = self::arrayGet($json, 'data.attributes.comment', '');
}
$entry->store();
return $entry;
}
}
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackEntry;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
/**
* Deletes a feedback entry.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackEntriesDelete extends JsonApiController
{
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$resource = FeedbackEntry::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
if (!Authority::canDeleteFeedbackEntry($this->getUser($request), $resource)) {
throw new AuthorizationFailedException();
}
$resource->delete();
return $this->getCodeResponse(204);
}
}
...@@ -7,19 +7,27 @@ use Psr\Http\Message\ResponseInterface as Response; ...@@ -7,19 +7,27 @@ use Psr\Http\Message\ResponseInterface as Response;
use JsonApi\Errors\AuthorizationFailedException; use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException; use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController; use JsonApi\JsonApiController;
use JsonApi\Schemas\FeedbackEntry as FeedbackEntrySchema;
/** /**
* Displays a certain feedback entry. * Displays a certain feedback entry.
*/ */
class FeedbackEntriesShow extends JsonApiController class FeedbackEntriesShow extends JsonApiController
{ {
protected $allowedIncludePaths = ['author', 'feedback-element']; protected $allowedIncludePaths = [FeedbackEntrySchema::REL_AUTHOR, FeedbackEntrySchema::REL_FEEDBACK];
/** /**
* @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.StaticAccess)
*
* @param array $args
*
* @return Response
*/ */
public function __invoke(Request $request, Response $response, $args) public function __invoke(Request $request, Response $response, $args)
{ {
if (!$resource = \FeedbackEntry::find($args['id'])) { $resource = \FeedbackEntry::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException(); throw new RecordNotFoundException();
} }
......
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackElement;
use FeedbackEntry;
use User;
use JsonApi\Errors\AuthorizationFailedException;
use JsonApi\Errors\RecordNotFoundException;
use JsonApi\JsonApiController;
use JsonApi\Routes\ValidationTrait;
use JsonApi\Schemas\FeedbackElement as FeedbackElementSchema;
use JsonApi\Schemas\FeedbackEntry as FeedbackEntrySchema;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
/**
* Update a FeedbackEntry.
*
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class FeedbackElementsUpdate extends JsonApiController
{
use RatingHelper;
use ValidationTrait;
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $args
*
* @return Response
*/
public function __invoke(Request $request, Response $response, $args)
{
$resource = \FeedbackEntry::find($args['id']);
if (!$resource) {
throw new RecordNotFoundException();
}
$json = $this->validate($request);
$user = $this->getUser($request);
if (!Authority::canUpdateFeedbackEntry($user, $resource)) {
throw new AuthorizationFailedException();
}
$feedbackEntry = $this->update($resource, $json);
return $this->getContentResponse($feedbackEntry);
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameters)
*
* @param array $json
* @param mixed $data
*
* @return string|void
*/
protected function validateResourceDocument($json, $data)
{
if (!self::arrayHas($json, 'data')) {
return 'Missing `data` member at document´s top level.';
}
if (FeedbackEntrySchema::TYPE !== self::arrayGet($json, 'data.type')) {
return 'Invalid `type` of document´s `data`.';
}
if (!self::arrayHas($json, 'data.id')) {
return 'An existing document must have an `id`.';
}
$required = ['rating'];
foreach ($required as $attribute) {
if (!self::arrayHas($json, 'data.attributes.' . $attribute)) {
return 'Missing `' . $attribute . '` attribute.';
}
}
}
private function update(FeedbackEntry $feedbackEntry, array $json): FeedbackEntry
{
$feedbackEntry->rating = $this->getRating(
$feedbackEntry->feedback,
(int) self::arrayGet($json, 'data.attributes.rating')
);
if ($feedbackEntry->feedback->commentable && self::arrayHas($json, 'data.attributes.comment')) {
$feedbackEntry->comment = self::arrayGet($json, 'data.attributes.comment');
}
$feedbackEntry->store();
return $feedbackEntry;
}
}
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackRange;
use SimpleORMap;
trait RangeTypeAware
{
protected $possibleRangeTypes = null;
protected function preparePossibleRangeTypes(): void
{
foreach (app('json-api-integration-schemas') as $class => $schema) {
if (is_subclass_of($class, FeedbackRange::class) && is_subclass_of($class, SimpleORMap::class)) {
$this->possibleRangeTypes[$schema::TYPE] = $class;
}
}
}
}
<?php
namespace JsonApi\Routes\Feedback;
use FeedbackElement;
trait RatingHelper
{
// TODO: Hier passt einiges nicht
private function getRating(FeedbackElement $element, int $rating): int
{
$mode = $element['mode'];
if ($mode === 0) {
return 0;
}
if ($rating === 0) {
return 1;
}
if ($mode === 1) {
return min(5, $rating);
}
if ($mode === 2) {
return min(10, $rating);
}
throw new InvalidArgumentException("Invalid mode {$mode}");
}
}
...@@ -2,24 +2,28 @@ ...@@ -2,24 +2,28 @@
namespace JsonApi\Schemas; namespace JsonApi\Schemas;
use JsonApi\Errors\InternalServerError;
use Neomerx\JsonApi\Contracts\Schema\ContextInterface; use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
use Neomerx\JsonApi\Schema\Link; use Neomerx\JsonApi\Schema\Link;
class FeedbackElement extends SchemaProvider class FeedbackElement extends SchemaProvider
{ {
const TYPE = 'feedback-elements'; public const TYPE = 'feedback-elements';
const REL_AUTHOR = 'author'; public const REL_AUTHOR = 'author';
const REL_COURSE = 'course'; public const REL_COURSE = 'course';
const REL_ENTRIES = 'entries'; public const REL_ENTRIES = 'entries';
const REL_RANGE = 'range'; public const REL_RANGE = 'range';
public function getId($resource): ?string public function getId($resource): ?string
{ {
return (int) $resource->id; return (string) $resource->id;
} }
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getAttributes($resource, ContextInterface $context): iterable public function getAttributes($resource, ContextInterface $context): iterable
{ {
$attributes = [ $attributes = [
...@@ -76,7 +80,7 @@ class FeedbackElement extends SchemaProvider ...@@ -76,7 +80,7 @@ class FeedbackElement extends SchemaProvider
return $relationships; return $relationships;
} }
private function getAuthorRelationship(array $relationships, \FeedbackElement $resource, $includeData): array private function getAuthorRelationship(array $relationships, \FeedbackElement $resource, bool $includeData): array
{ {
$userId = $resource['user_id']; $userId = $resource['user_id'];
$related = $includeData ? \User::find($userId) : \User::build(['id' => $userId], false); $related = $includeData ? \User::find($userId) : \User::build(['id' => $userId], false);
...@@ -90,7 +94,7 @@ class FeedbackElement extends SchemaProvider ...@@ -90,7 +94,7 @@ class FeedbackElement extends SchemaProvider
return $relationships; return $relationships;
} }
private function getCourseRelationship(array $relationships, \FeedbackElement $resource, $includeData): array private function getCourseRelationship(array $relationships, \FeedbackElement $resource, bool $includeData): array
{ {
if ($courseId = $resource['course_id']) { if ($courseId = $resource['course_id']) {
$related = $includeData ? \Course::find($courseId) : \Course::build(['id' => $courseId], false); $related = $includeData ? \Course::find($courseId) : \Course::build(['id' => $courseId], false);
...@@ -119,23 +123,17 @@ class FeedbackElement extends SchemaProvider ...@@ -119,23 +123,17 @@ class FeedbackElement extends SchemaProvider
private function getRangeRelationship(array $relationships, \FeedbackElement $resource, bool $includeData): array private function getRangeRelationship(array $relationships, \FeedbackElement $resource, bool $includeData): array
{ {
$rangeType = $resource['range_type']; $range = $resource->getRange();
$link = null;
try { try {
$link = $this->createLinkToResource($rangeType); $link = $this->createLinkToResource($range);
if (
is_subclass_of($rangeType, \FeedbackRange::class) &&
is_subclass_of($rangeType, \SimpleORMap::class)
) {
if ($range = $rangeType::find($resource['range_id'])) {
$relationships[self::REL_RANGE] = [ $relationships[self::REL_RANGE] = [
self::RELATIONSHIP_LINKS => [Link::RELATED => $link], self::RELATIONSHIP_LINKS => [Link::RELATED => $link],
self::RELATIONSHIP_DATA => $range self::RELATIONSHIP_DATA => $range
]; ];
}
}
} catch (\InvalidArgumentException $e) { } catch (\InvalidArgumentException $e) {
// don't show this relation
} catch (InternalServerError $ise) {
// don't show this relation
} }
return $relationships; return $relationships;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment