Last active
March 17, 2019 13:42
-
-
Save Anubarak/baf80b6ed1db88e0f82b85771b4701e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* ElementCreate Action: this class handles Updating and Creating Craft elements, | |
* | |
* API for Craft CMS 3.x | |
* | |
* Created with PhpStorm. | |
* | |
* @link https://github.com/Anubarak/ | |
* @copyright Copyright (c) 2019 Robin Schambach | |
*/ | |
namespace modules\api\base\base; | |
use Craft; | |
use craft\base\ElementInterface; | |
use craft\base\Model; | |
use craft\helpers\Json; | |
use craft\web\Response; | |
use yii\helpers\ArrayHelper; | |
use yii\helpers\Url; | |
use yii\rest\Action; | |
use yii\web\ServerErrorHttpException; | |
class ElementCreateAction extends Action | |
{ | |
/** | |
* @var string the scenario to be assigned to the new model before it is validated and saved. | |
*/ | |
public $scenario = Model::SCENARIO_DEFAULT; | |
/** | |
* @var string the name of the view action. This property is need to create the URL when the model is successfully | |
* created. | |
*/ | |
public $viewAction = 'view'; | |
/** | |
* Creates a new model. | |
* @throws \Throwable | |
* @throws \craft\errors\ElementNotFoundException | |
* @throws \yii\base\Exception | |
* @throws \yii\web\ServerErrorHttpException | |
* @return \craft\base\ElementInterface the model newly created | |
*/ | |
public function run(): ElementInterface | |
{ | |
if ($this->checkAccess) { | |
call_user_func($this->checkAccess, $this->id); | |
} | |
// just for vue/axios, you'll normaly just use $data = Craft::$app->getRequest()->getBodyParams(); | |
$data = Json::decode(Craft::$app->getRequest()->getRawBody()); | |
if(empty($data)){ | |
$data = Craft::$app->getRequest()->getBodyParams(); | |
} | |
$id = $data['id'] ?? null; | |
if ($id !== null) { | |
$class = $this->modelClass; // modelClass is defined in the Controller | |
$model = Craft::$app->getElements()->getElementById((int)$id, $class); | |
} else { | |
/** @var \craft\base\Element $model */ | |
$model = new $this->modelClass( | |
[ | |
'scenario' => $this->scenario, | |
] | |
); | |
} | |
// set all write-able attributes | |
$safeAttributes = []; | |
foreach ($data as $key => $value){ | |
if($model->canSetProperty($key)){ | |
$safeAttributes[$key] = $value; | |
} | |
} | |
$model->setAttributes($safeAttributes); | |
// Save/Set all the custom fields | |
if($model::hasContent()){ | |
$layout = $model->getFieldLayout(); | |
if($layout !== null){ | |
$fields = $layout->getFields(); | |
$handles = ArrayHelper::getColumn($fields, 'handle'); | |
foreach ($handles as $handle){ | |
if(isset($data[$handle])){ | |
$model->setFieldValue($handle, $data[$handle]); | |
} | |
} | |
} | |
} | |
if (Craft::$app->getElements()->saveElement($model)) { | |
$response = Craft::$app->getResponse(); | |
$response->setStatusCode(201); | |
$id = $model->getId(); | |
$response->getHeaders()->set('Location', Url::toRoute([$this->viewAction, 'id' => $id], true)); | |
} elseif (!$model->hasErrors()) { | |
throw new ServerErrorHttpException('Failed to create the object for unknown reason.'); | |
} | |
return $model; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This class is my "main" REST Controller, every other REST Controller extends this class | |
* it's purpose is to create a layer between Yii2 REST API that are all handled via ActiveControllers | |
* and Craft Elements | |
* | |
* API for Craft CMS 3.x | |
* | |
* Created with PhpStorm. | |
* | |
* @link https://github.com/Anubarak/ | |
* @copyright Copyright (c) 2019 Robin Schambach | |
*/ | |
namespace modules\api\base\base; | |
use Craft; | |
use craft\web\Response; | |
use modules\api\base\helpers\CorsHelper; | |
use modules\myspa\MYSPA; | |
use yii\rest\ActiveController as Controller; | |
/** | |
* Class ActiveController | |
* @package modules\api\base\base | |
* @since 12.02.2019 | |
* | |
* @property array $serializeFields | |
* @property array $baseCriteria | |
*/ | |
class ActiveController extends Controller | |
{ | |
/** | |
* @var array List of allowed verbs for this Controller | |
*/ | |
public $verbs = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']; | |
/** | |
* @var string|array the configuration for creating the serializer that formats the response data. | |
*/ | |
public $serializer = ElementSerializer::class; | |
/** | |
* @var array | |
*/ | |
public $serializeOptions = []; | |
public function actions() | |
{ | |
$actions = parent::actions(); | |
// overwrite all default actions via custom Actions, so every craft element type can use it | |
$actions['create'] = [ | |
'class' => ElementCreateAction::class, // <--- overwrite all actions for Craft Elements, see the prev file | |
'modelClass' => $this->modelClass, | |
'checkAccess' => [$this, 'checkAccess'], | |
'scenario' => $this->createScenario, | |
]; | |
$actions['update'] = [ | |
'class' => ElementUpdateAction::class, | |
'modelClass' => $this->modelClass, | |
'checkAccess' => [$this, 'checkAccess'], | |
'scenario' => $this->createScenario, | |
]; | |
$actions['delete'] = [ | |
'class' => ElementDeleteAction::class, | |
'modelClass' => $this->modelClass, | |
'checkAccess' => [$this, 'checkAccess'], | |
]; | |
$actions['view'] = [ | |
'class' => ElementViewAction::class, | |
'modelClass' => $this->modelClass, | |
'checkAccess' => [$this, 'checkAccess'], | |
]; | |
$actions['index'] = [ | |
'class' => ElementIndexAction::class, | |
'modelClass' => $this->modelClass, | |
'baseCriteria' => $this->getBaseCriteria(), | |
'checkAccess' => [$this, 'checkAccess'], | |
]; | |
$actions['options'] = [ | |
'class' => ElementOptionsAction::class, | |
'modelClass' => $this->modelClass, | |
'checkAccess' => [$this, 'checkAccess'], | |
]; | |
return $actions; | |
} | |
/** | |
* behaviors | |
* | |
* @throws \yii\base\Exception | |
* @return array | |
* | |
* @author Robin Schambach | |
*/ | |
public function behaviors(): array | |
{ | |
$behaviors = parent::behaviors(); | |
// custom behavior to handle CORS requests | |
$behaviors[] = CorsHelper::getBehavior(); | |
return $behaviors; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* OrdersController To handle Orders via REST API, you can as well do the very same for | |
* Products | |
* | |
* API for Craft CMS 3.x | |
* | |
* Created with PhpStorm. | |
* | |
* @link https://github.com/Anubarak/ | |
* @copyright Copyright (c) 2019 Robin Schambach | |
*/ | |
namespace modules\api\v1\controllers; | |
use Craft; | |
use craft\commerce\elements\Order; | |
use craft\web\Response; | |
use modules\api\base\base\ActiveController; | |
use modules\api\base\base\FractalSerializer; | |
use modules\api\base\filters\AccessRule; | |
use modules\api\v1\transformers\OrderTransformer; | |
use modules\myspa\services\Stores; | |
use yii\filters\AccessControl; | |
class OrdersController extends ActiveController | |
{ | |
// modelclass is craft\commerce\elements\Order; | |
public $modelClass = Order::class; | |
// I'm using fractal instead of the Yii2 Serializer because it's more easier, but I guess | |
// since you don't provide data and only want to receive it you won't need that | |
public $serializer = [ | |
'class' => FractalSerializer::class, | |
'transformer' => OrderTransformer::class | |
]; | |
public function behaviors(): array | |
{ | |
$behaviors = parent::behaviors(); | |
// include an access controller, You can take a look at Yii2 for other access Control methods, | |
// For example this blocks certain requests for authorized users | |
// see here for other methods https://www.yiiframework.com/doc/guide/2.0/en/rest-authentication | |
$behaviors['access'] = [ | |
'class' => AccessControl::class, | |
'ruleConfig' => ['class' => AccessRule::class], | |
'only' => ['create', 'index', 'options', 'delete'], | |
'rules' => [ | |
[ | |
'allow' => true, | |
'actions' => ['index'], | |
'roles' => ['myspa-desk-orders'], | |
], | |
[ | |
'allow' => true, | |
'actions' => ['create', 'update'], | |
'roles' => ['myspa-desk-orders-save'], | |
], | |
[ | |
'allow' => true, | |
'actions' => ['delete'], | |
'roles' => ['myspa-desk-orders-delete'], | |
], | |
], | |
]; | |
return $behaviors; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment