Skip to content

Instantly share code, notes, and snippets.

@geoidesic
Created August 3, 2020 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geoidesic/de5c046448e146426bdb34090aa80c2d to your computer and use it in GitHub Desktop.
Save geoidesic/de5c046448e146426bdb34090aa80c2d to your computer and use it in GitHub Desktop.
Refactor attempt of the CrudJsonApiControllerTrait as a CRUD Action class extension (note the `print_r` which mysteriously doesn't yield the request body)
<?php
declare(strict_types=1);
namespace App\Crud\Action;
use Cake\Http\Response;
use Crud\Error\Exception\ValidationException;
use Crud\Event\Subject;
use Crud\Traits\FindMethodTrait;
use Crud\Traits\RedirectTrait;
use Crud\Traits\SaveMethodTrait;
use Crud\Traits\SerializeTrait;
use Crud\Traits\ViewTrait;
use Crud\Traits\ViewVarTrait;
use Crud\Action\BaseAction;
/**
* Handles 'Edit' Crud actions
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
*/
class RelationshipsAction extends BaseAction
{
use FindMethodTrait;
use RedirectTrait;
use SaveMethodTrait;
use SerializeTrait;
use ViewTrait;
use ViewVarTrait;
/**
* Default settings for 'edit' actions
*
* `enabled` Is this crud action enabled or disabled
*
* `findMethod` The default `Model::find()` method for reading data
*
* `view` A map of the controller action and the view to render
* If `NULL` (the default) the controller action name will be used
*
* `relatedModels` is a map of the controller action and the whether it should fetch associations lists
* to be used in select boxes. An array as value means it is enabled and represent the list
* of model associations to be fetched
*
* `saveOptions` Options array used for $options argument of patchEntity() and save method.
* If you configure a key with your action name, it will override the default settings.
*
* @var array
*/
protected $_defaultConfig = [
'enabled' => true,
'scope' => 'entity',
'findMethod' => 'all',
'saveMethod' => 'save',
'view' => null,
'relatedModels' => true,
'saveOptions' => [],
'messages' => [
'success' => [
'text' => 'Successfully updated {name}',
],
'error' => [
'text' => 'Could not update {name}',
],
],
'redirect' => [
'post_add' => [
'reader' => 'request.data',
'key' => '_add',
'url' => ['action' => 'add'],
],
'post_edit' => [
'reader' => 'request.data',
'key' => '_edit',
'url' => ['action' => 'edit', ['subject.key', 'id']],
],
],
'api' => [
'methods' => ['put', 'post', 'patch'],
'success' => [
'code' => 200,
],
'error' => [
'exception' => [
'type' => 'validate',
'class' => ValidationException::class,
],
],
],
'serialize' => [],
];
/**
* HTTP GET handler
*
* @param string|null $id Record id
* @return void
* @throws \Cake\Http\Exception\NotFoundException If record not found
*/
protected function _get(?string $id = null): void
{
$subject = $this->_subject();
$subject->set(['id' => $id]);
$subject->set(['entity' => $this->_findRecord($id, $subject)]);
$this->_trigger('beforeRender', $subject);
}
/**
* HTTP PUT handler
*
* @param string|null $id Record id
* @return \Cake\Http\Response|null
*/
protected function _put(?string $id = null)
{
$subject = $this->_subject();
$subject->set(['id' => $id]);
$entity = $this->_table()->patchEntity(
$this->_findRecord($id, $subject),
$this->_request()->getData(),
$this->saveOptions()
);
$this->_trigger('beforeSave', $subject);
if (call_user_func([$this->_table(), $this->saveMethod()], $entity, $this->saveOptions())) {
return $this->_success($subject);
}
$this->_error($subject);
}
/**
* HTTP POST handler
*
* Thin proxy for _put
*
* @param string|null $id Record id
* @return \Cake\Http\Response|null
*/
protected function _post(?string $id = null)
{
return $this->_put($id);
}
/**
* HTTP PATCH handler
*
* @param string|null $id Record id
* @return \Cake\Http\Response|null
*/
protected function _patch()
{
$subject = $this->_subject();
$request = $this->_request();
$id = $request->getParam('id');
$foreignTableName = $request->getParam('foreignTableName');
print_r($data);
$subject->set(['id' => $id]);
$entity = $this->_table()->patchEntity(
$this->_findRecord($id, $subject),
$this->_request()->getData(),
$this->saveOptions()
);
if (empty((array)$data['data'])) {
$entity->$foreignTableName = [];
} else {
$entity->$foreignTableName = [];
foreach ($data['data'] as $key => $recordAttributes) {
// get the related record
$foreignTable = $this->getTableLocator()->get(Inflector::camelize($foreignTableName));
$foreignKey = $foreignTableName . '.id';
$query = $foreignTable->findAllById($recordAttributes['id']);
$foreignRecord = $query->first();
// push it onto the relationsships array if it exists
if (!empty($foreignRecord)) {
array_push($entity->$foreignTableName, $foreignRecord);
}
}
}
$this->_trigger('beforeSave', $subject);
if (call_user_func([$this->_table(), $this->saveMethod()], $entity, $this->saveOptions())) {
return $this->_success($subject);
}
$this->_error($subject);
}
/**
* Success callback
*
* @param \Crud\Event\Subject $subject Event subject
* @return \Cake\Http\Response|null
*/
protected function _success(Subject $subject): ?Response
{
$subject->set(['success' => true, 'created' => false]);
// $this->_trigger('afterSave', $subject);
$this->setFlash('success', $subject);
return $this->_redirect($subject, ['action' => 'index']);
}
/**
* Error callback
*
* @param \Crud\Event\Subject $subject Event subject
* @return void
*/
protected function _error(Subject $subject): void
{
$subject->set(['success' => false, 'created' => false]);
$this->_trigger('afterSave', $subject);
$this->setFlash('error', $subject);
$this->_trigger('beforeRender', $subject);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment