Skip to content

Commit

Permalink
add view related action
Browse files Browse the repository at this point in the history
  • Loading branch information
tuyakhov committed Dec 16, 2016
1 parent 7dcb7ef commit 64a5075
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 54 deletions.
51 changes: 0 additions & 51 deletions src/UpdateRelationshipAction.php

This file was deleted.

67 changes: 67 additions & 0 deletions src/actions/UpdateRelationshipAction.php
@@ -0,0 +1,67 @@
<?php
/**
* @author Anton Tuyakhov <atuyakhov@gmail.com>
*/

namespace tuyakhov\jsonapi\actions;

use tuyakhov\jsonapi\ResourceInterface;
use yii\data\ActiveDataProvider;
use yii\db\BaseActiveRecord;
use yii\helpers\ArrayHelper;
use yii\rest\Action;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;

class UpdateRelationshipAction extends Action
{
/**
* @param $id
* @param $name
* @return array|null|ActiveDataProvider|\yii\db\ActiveRecord|\yii\db\ActiveRecordInterface
* @throws BadRequestHttpException
* @throws NotFoundHttpException
*/
public function run($id, $name)
{
/** @var BaseActiveRecord $model */
$model = $this->findModel($id);

if (!$model instanceof ResourceInterface) {
throw new BadRequestHttpException('Impossible to update relationships for resource');
}

if (!$related = $model->getRelation($name, false)) {
throw new NotFoundHttpException('Relationship does not exist');
}
$relatedClass = $related->modelClass;

$data = \Yii::$app->getRequest()->getBodyParams();
$data = ArrayHelper::isIndexed($data) ? $data : [$data];

$ids = [];
foreach ($data as $index => $relationshipObject) {
if (!isset($relationshipObject['id'])) {
continue;
}
$ids[] = $relationshipObject['id'];
}
/** @var BaseActiveRecord $relatedClass */
$relationships = $relatedClass::find()
->andWhere(['in', $relatedClass::primaryKey(), $ids])
->all();

if (!empty($relationships)) {
$model->unlinkAll($name);
$model->setResourceRelationship($name, $relationships);
}

if ($related->multiple) {
return new ActiveDataProvider([
'query' => $related
]);
} else {
return $related->one();
}
}
}
60 changes: 60 additions & 0 deletions src/actions/ViewRelatedAction.php
@@ -0,0 +1,60 @@
<?php
/**
* @author Anton Tuyakhov <atuyakhov@gmail.com>
*/

namespace tuyakhov\jsonapi\actions;


use tuyakhov\jsonapi\ResourceInterface;
use yii\data\ActiveDataProvider;
use yii\db\ActiveQuery;
use yii\rest\Action;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;

class ViewRelatedAction extends Action
{
/**
* Prepares the data provider that should return the requested collection of the models.
* @var callable
*/
public $prepareDataProvider;

/**
* @param $id
* @param $name
* @return ActiveDataProvider|\yii\db\ActiveRecordInterface
* @throws BadRequestHttpException
* @throws NotFoundHttpException
*/
public function run($id, $name)
{
$model = $this->findModel($id);

if (!$model instanceof ResourceInterface) {
throw new BadRequestHttpException('Impossible to fetch related resource');
}

if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}

/** @var ActiveQuery $related */
if (!$related = $model->getRelation($name, false)) {
throw new NotFoundHttpException('Resource does not exist');
}

if ($this->prepareDataProvider !== null) {
return call_user_func($this->prepareDataProvider, $this, $related);
}

if ($related->multiple) {
return new ActiveDataProvider([
'query' => $related
]);
} else {
return $related->one();
}
}
}
4 changes: 1 addition & 3 deletions tests/JsonApiParserTest.php
@@ -1,8 +1,6 @@
<?php
/**
* @link http://www.stombox.com/
* @copyright Copyright (c) 2015 Stombox LLC
* @license http://www.stombox.com/license/
* @author Anton Tuyakhov <atuyakhov@gmail.com>
*/

namespace tuyakhov\jsonapi\tests;
Expand Down
45 changes: 45 additions & 0 deletions tests/actions/ViewRelatedActionTest.php
@@ -0,0 +1,45 @@
<?php
/**
* @author Anton Tuyakhov <atuyakhov@gmail.com>
*/
namespace tuyakhov\jsonapi\tests\actions;

use tuyakhov\jsonapi\tests\TestCase;
use tuyakhov\jsonapi\actions\ViewRelatedAction;
use yii\base\Controller;
use tuyakhov\jsonapi\tests\data\ResourceModel;
use yii\data\ActiveDataProvider;
use \tuyakhov\jsonapi\tests\data\ActiveQuery;
use yii\web\NotFoundHttpException;

class ViewRelatedActionTest extends TestCase
{

public function testSuccess()
{
$model = new ResourceModel();
$action = new ViewRelatedAction('test', new Controller('test', \Yii::$app), [
'modelClass' => ResourceModel::className()
]);
$model->setRelation('multiple', new ActiveQuery(ResourceModel::className(), ['multiple' => true]));
$model->setRelation('single', new ActiveQuery(ResourceModel::className()));
$action->findModel = function ($id, $action) use($model) {
return $model;
};

$this->assertInstanceOf(ActiveDataProvider::className(), $action->run(1, 'multiple'));
$this->assertInstanceOf(ResourceModel::className(), $action->run(1, 'single'));
}

public function testInvalidRelation()
{
$action = new ViewRelatedAction('test', new Controller('test', \Yii::$app), [
'modelClass' => ResourceModel::className()
]);
$action->findModel = function ($id, $action) {
return new ResourceModel();
};
$this->expectException(NotFoundHttpException::class);
$action->run(1, 'invalid');
}
}
15 changes: 15 additions & 0 deletions tests/data/ActiveQuery.php
@@ -0,0 +1,15 @@
<?php
/**
* @author Anton Tuyakhov <atuyakhov@gmail.com>
*/
namespace tuyakhov\jsonapi\tests\data;


class ActiveQuery extends \yii\db\ActiveQuery
{
public function one($db = null)
{
return new $this->modelClass;
}

}
13 changes: 13 additions & 0 deletions tests/data/ResourceModel.php
Expand Up @@ -8,6 +8,7 @@
use tuyakhov\jsonapi\ResourceInterface;
use tuyakhov\jsonapi\ResourceTrait;
use yii\base\Model;
use yii\db\ActiveQuery;

class ResourceModel extends Model implements ResourceInterface
{
Expand All @@ -22,6 +23,8 @@ class ResourceModel extends Model implements ResourceInterface
public $extraField1 = 'testExtra';
public $extraField2 = 42;

private $_related = [];

public function getId()
{
return static::$id;
Expand All @@ -36,4 +39,14 @@ public function extraFields()
{
return static::$extraFields;
}

public function getRelation($name)
{
return isset($this->_related[$name]) ? $this->_related[$name] : null;
}

public function setRelation($name, $value)
{
$this->_related[$name] = $value;
}
}

0 comments on commit 64a5075

Please sign in to comment.