Enable multiple endpoints/routes while extending Magento Rest API - php

I want two endpoints for my custom api which are
Create custom rules in a magento cart (URL= magento.com/coupondemo/generate)
Create coupon codes for a particular rule (URL= magento.com//coupondemo/rules/:rule_id/codes)
I've followed this tutorial to and coupon codes in Magento and I have code that can create a rule in Magento too. However, I've no clue how to create the two endpoints in my custom rest api as I am only able to create one.
I have the following routes in api2.xml
<routes>
<route_collection>
<route>/coupondemo/generate</route>
<action_type>entity</action_type>
</route_collection>
<route_collection>
<route>/coupondemo/rules/:rule_id/codes</route>
<action_type>collection</action_type>
</route_collection>
</routes>
my v1.php's skeleton is as follows
<?php
/* Coupon AutoGen REST API
*
* #category CouponDemo
* #package CouponDemo_AutoGen
* #author Chuck Hudson (used with permission). For more recipes, see Chuck's book http://shop.oreilly.com/product/0636920023968.do
*/
class CouponDemo_AutoGen_Model_Api2_Coupon_Rest_Admin_V1 extends CouponDemo_AutoGen_Model_Api2_Coupon
{
/**
* Generate one or more coupon codes using the Generate Coupons rule defined in Magento.
* Expected parameters are:
* {
* 'qty': int, - number of coupon codes to instruct Magento to generate
* 'length': int, - length of each generated coupon code
* 'format': string, - alphanum (for alphanumeric codes), alpha (for alphabetical codes), and num (for numeric codes)
* }
*
* #param array $couponData
* #return string|void
*/
protected function _create($couponData)
{
}
protected function _retrieveCollection()
{
}
protected function _retrieve($couponDatas)
{
}
}
The problem is that both the routes call the _create methods in my v1.php. I want to have the first route call a custom method with an array as a parameter. So how can I do that?
I tried using this route
<!-- Call For V1.php _retrieve() -->
<route_entity_count>
<route>/coupondemo/generate</route>
<action_type>entity</action_type>
</route_entity_count>
which calls the _retrieve method but it doesn't allow the parameter to be passed in.
How should I handle the first route then?

Related

API Platform: Change description of an endpoint

I have created a custom endpoint using API Platform. Here is the annotation I have used:
/**
* We only want the POST option for now.
*
* #ApiResource(
* itemOperations={},
* collectionOperations={"post"={
* "method"="POST",
* "controller"=PairingController::class,
* "path"="/devices/pairing",
* "defaults"={"_api_receive"=false}
* }},
* )
*
*
*/
class Pairing
{
...
The controller I am calling executes some custom logic. I am happy with how things are working so far. But the documentation generated by API Platform is now inaccurate. It says:
/devices/pairing Creates a Pairing resource.
... which is no longer true, since my controller does not generate a pairing. (It calls out to a different API instead, asking that API to do some stuff.)
So here's my question: How do I change my annotation to allow me to write a custom piece of documentation for this endpoint?
You can use the swagger_context key to change any Swagger field, including description (the one you are looking for): https://api-platform.com/docs/core/swagger/#changing-operations-in-the-swagger-documentation
It didn't works for me, here is how I did it with openapi_context:
"openapi_context"={
"summary"="test",
},

How and where to create Yii2 Access Rules using mdmsoft/yii2-admin

Hi developers I am new to YII , I have installed the YII2 framework and want a RBAC I have installed mdmsoft/yii2-admin module , but I do not know how to create RULE class, where to create it and then how to use. When I create a role in admin section it say , enter a Class Name. I don't know how to create and use the RULE feature of YII. I have attached the screen shot.
If you are using an Advanced template here are the steps;
Create a directory under frontend and rename it rbac
Create a file under this new directory, say, AuthorRule.php. Here is a sample file given in the official docs;
namespace app\rbac;
use yii\rbac\Rule;
use app\models\Post;
/**
* Checks if authorID matches user passed via params
*/
class AuthorRule extends Rule
{
public $name = 'isAuthor';
/**
* #param string|int $user the user ID.
* #param Item $item the role or permission that this rule is associated with
* #param array $params parameters passed to ManagerInterface::checkAccess().
* #return bool a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['post']) ? $params['post']->createdBy == $user : false;
}
}
Next step is to navigate to http://localhost/path/to/index.php?r=admin/rule and create a new rule with class name \app\rbac\AuthorRule
Finally you can add the new rule to roles and permissions depending on your needs.
You can read the official docs for more information on rules; the official docs.

How can I get restler to accept multiple routes to a method, but only document one of them?

I'm in the process of fixing up an API, and I'd like to deprecate some old routes. I'm basically moving the endpoints around, but want to encourage new consumers to use the new routes. However, I need to support the old routes for a short period during this transition. Below is an example of something that I want. I would like the new url documented and the old one either marked as deprecated or removed from the documentation entirely. Is there an easy way to do this, or am I stuck during the transition?
/**
* Adds a new Item
*
* This creates a new item
*
* #url POST /:id/patch {#deprecated}
* #url PATCH /:id
*/
Move deprecated routes to a new method which internally calls the old method for functionality mark it as deprecated through description with the help of HTML if needed. Here is an example
/**
* Adds a new Item
*
* This creates a new item
*
* #url PATCH /{id}
*/
function patchItem($id)
{
//actual process here
}
/**
* Adds a new Item [DEPRECATED]
*
* This creates a new item
*
* #url POST /{id}/patch
*/
function deprecatedPatchItem($id)
{
return $this->patchItem($id);
}
Once you decided to remove the deprecated simply delete the new method

Losing the ".json" in the API Explorer documentation

First let me say that the new API Explorer in Restler is great. Very happy about its addition. Now, in typical fashion, let me complain about something that isn't working for me ...
The fact that Restler can return results in multiple formats is a very nice feature but I'm currently not using it (choosing to only use JSON as my return format). In the API Explorer I'd like all references to .json to not show up as this just complicates the look of the service architecture.
Here's a quick example:
class Users {
/**
* Preferences
*
* Preferences returns a dictionary of name-value pairs that provide input to applications that want to make user-specific decisions
*
* #url GET /{user_id}/preferences
**/
function preferences ($user_id , $which = 'all') {
return "$which preferences for {$user_id}";
}
/**
* GET Sensors
*
* Get a list of all sensors associated with a user.
*
* #url GET /{user_id}/sensor
**/
function sensor ($user_id) {
return "sensor";
}
/**
* GET Sensors by Type
*
* #param $user_id The user who's sensors you are interested in
* #param $type The type of sensor you want listed.
*
* #url GET /{user_id}/sensor/{type}
**/
function sensor_by_type ($user_id, $type) {
return "specific sensor";
}
/**
* ADD a Sensor
*
* #param $user_id The user who you'll be adding the sensor to
*
* #url POST /sensor
**/
function postSensor() {
return "post sensor";
}
}
In this example the API Explorer looks like this:
The basic problem I'd like to remove is remove all ".json" references as the calling structure without the optional .json works perfectly fine.
Also, for those that DO want the .json showing up there's a secondary problem of WHERE does this post-item modifier show up? In the example above you have .json attaching to the "users" element in the GET's and to the "sensor" element in the PUT. This has nothing to do with the HTTP operation but rather it seems to choose the element which immediately precedes the first variable which may not be intuitive to the user and actually isn't a requirement in Restler (at least its my impression that you can attache .json anywhere in the chain and get the desired effect).
We are using safer defaults that will work for everyone, but made it completely configurable.
if you prefer .json to be added at the end, add the following to index.php (gateway)
use Luracast\Restler\Resources;
Resources::$placeFormatExtensionBeforeDynamicParts = false;
If you prefer not to add .json extension, add the following to index.php
use Luracast\Restler\Resources;
Resources::$useFormatAsExtension = false;

API Explorer not using URL parameters

I have created a RESTful API that has an optional parameter passed in as a URL variable. It seems to work correctly when executing from the browser directly but when trying it in the API Explorer it lists the parameter but ignores it when executing it. I have no idea where to start to look in solving this. Any help would be greatly appreciated.
The class definition is as follows:
class actions {
/**
* LIST available Actions
*
* List all the actions that a user (or app) can choose from. The response list
* will include [name],[slug/id], and [description] attributes. If you want a more complete set of
* meta attributes for the actions then you can specify "meta=all" in the request url. For full spec of
* response please review LG_actions_list.json.
*
* #url GET /available
*
* #param $meta {#from url} Optional parameter to control the amount of meta-data passed back. Values are "none","normal", and "all"
**/
public function available ($meta="normal")
{
return "list actions (meta level set to $meta)";
}
}
In this case I can type "all" as the value of $meta in the API explorer but the response is still "list actions (meta level set to normal)".
UPDATE:
In order to clarify this behaviour I am adding the API Explorers output and the output I get when I call the service directly:
In comparison, when actually using the API I get the correct results. Typing this into Chrome:
http://[domain]/api/actions/available?meta=foobar
I get the desired output of:
"list actions (meta level set to foobar)"
There are few problems with what you are doing with the above code
Optional Parameters are better left to query string
When you add a manual route using #url no auto routes will be added for that method
Do the following to make it work.
Changed the method name to get to map it to root of the class
Turned off smart auto routing
Now in the explorer there will be two operations listed
actions.json
actions.json/{meta}
.
class actions {
/**
* LIST available Actions
*
* List all the actions that a user (or app) can choose from. The response list
* will include [name],[slug/id], and [description] attributes. If you want a more complete set of
* meta attributes for the actions then you can specify "meta=all" in the request url. For full spec of
* response please review LG_actions_list.json.
*
* #smart-auto-routing false
* #param $meta Optional parameter to control the amount of meta-data passed back. Values are "none","normal", and "all"
**/
public function get ($meta="normal")
{
return "list actions (meta level set to $meta)";
}
}

Categories