Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created Dynamic Definitions #301

Closed
wants to merge 35 commits into from
Closed

Created Dynamic Definitions #301

wants to merge 35 commits into from

Conversation

kevupton
Copy link
Collaborator

Allowed for the creation of dynamic definitions.

Example definition:

/**
 * @SWG\DynamicDefinition(
 *      definition="Json",
 *      @SWG\Property(
 *          type="boolean",
 *          property="success"
 *      ),
 *      @SWG\Property(
 *          property="data",
 *          ref="{{0}}"
 *      ),
 *      @SWG\Property(
 *          property="errors",
 *          type="object"
 *      ),
 *      @SWG\Property(
 *          property="token",
 *          type="string"
 *      )
 * ),
 */

Note the {{0}} that represents an id of 0 or index of 0 (Allowing of multiple insertions in one definition.

Example Response

 *   @SWG\Response(
 *      response=200,
 *      description="A list all players with leaderboard",
 *      @SWG\Schema(
 *          ref=@SWG\Dynamic(
 *              use="Json",
 *              refs={
 *                  @SWG\Dynamic(
 *                      use="Json",
 *                      refs={"#/definitions/Json2"}
 *                  )
 *              }
 *          )
 * )
 */

Creates the definitions:


"definitions": {
        "Json2": {
            "properties": {
                "success": {
                    "type": "boolean"
                },
                "data": {
                    "type": "string"
                },
                "errors": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "token": {
                    "type": "string"
                }
            }
        },
        "dynamic-definition-0": {
            "properties": {
                "success": {
                    "type": "boolean"
                },
                "data": {
                    "$ref": "#/definitions/Json2"
                },
                "errors": {
                    "type": "object"
                },
                "token": {
                    "type": "string"
                }
            }
        },
        "dynamic-definition-1": {
            "properties": {
                "success": {
                    "type": "boolean"
                },
                "data": {
                    "$ref": "#/definitions/dynamic-definition-0"
                },
                "errors": {
                    "type": "object"
                },
                "token": {
                    "type": "string"
                }
            }
        }
    },

And the response json:

"responses": {
                "200": {
                    "description": "A list all players with leaderboard",
                    "schema": {
                        "$ref": "#/definitions/dynamic-definition-1"
                    }
                }
            }

@bfanger
Copy link
Collaborator

bfanger commented Apr 17, 2016

Very interesting pull request, it adds a highly requested feature (preventing duplication)
The downsides to your current approach is that introduces additional concepts, containers and annotations.

My current idea about solving this issue is to check if a $ref is set and contains non-default values.

Example:

/** 
 * @SWG\Response(
 *   response="succesful",
 *   description="The request was succesful",
 *   @SWG\Schema(
 *     @SWG\Property(
 *       type="boolean",
 *       property="success"
 *     ),
 *     @SWG\Property(
 *       property="data",
 *     )
 *   )
 * )
 */


/** 
 * @SWG\Response(
 *   response="user",
 *   description="The user",
 *   @SWG\Schema(
 *     ref="#/responses/succesful/schema",
 *     @SWG\Property(
 *       property="data",
 *       ref="#/definitions/User"
 *     )
 *   )
 * )
 */

The user response has a schema with a ref, but also a non-default value in the properties, so that could unfold to:

{
    "swagger": "2.0",
    "paths": {},
    "definitions": {},
    "responses": {
        "succesful": {
            "description": "The request was succesful",
            "schema": {
                "properties": {
                    "success": {
                        "type": "boolean"
                    },
                    "data": {}
                }
            }
        },
        "user": {
            "description": "The user",
            "schema": {
                "properties": {
                    "success": {
                        "type": "boolean"
                    },
                    "data": {
                        "$ref": "#/definitions/User"
                    }
                }
            }
        }
    }
}

Injecting the succes property and everything else from "#/responses/succesful/schema" but using another data property .

But I haven't made the time to implement such a system.

@bfanger bfanger force-pushed the master branch 2 times, most recently from 21a9615 to a51f62c Compare April 17, 2016 14:09
@kevupton
Copy link
Collaborator Author

kevupton commented Apr 27, 2016

This is definitely a different approach to how i have done it. But i do like how much cleaner it is. Like you said i did have to create a lot of unnecessary things. Maybe I switch and implement your version instead. :)

@kevupton
Copy link
Collaborator Author

how would it work if you wanted to import parameters from the other response too ? would it be better to use the ref on the response rather than the schema?

@kevupton
Copy link
Collaborator Author

kevupton commented Apr 30, 2016

What I implemented is:

/** 
 * @SWG\Response(
 *   response="succesful",
 *   description="The request was succesful",
 *   @SWG\Schema(
 *     @SWG\Property(
 *       type="boolean",
 *       property="success"
 *     ),
 *     @SWG\Property(
 *       property="data",
 *     )
 *   )
 * )
 */


/** 
 * @SWG\Response(
 *   response="user",
 *   description="The user",
 *   ref="$/responses/succesful",
 *   @SWG\Schema(
 *     @SWG\Property(
 *       property="data",
 *       ref="#/definitions/User"
 *     )
 *   )
 * )
 */
{
    "swagger": "2.0",
    "paths": {},
    "definitions": {},
    "responses": {
        "successful": {
            "description": "The request was successful",
            "schema": {
                "properties": {
                    "success": {
                        "type": "boolean"
                    },
                    "data": {}
                }
            }
        },
        "user": {
            "description": "The user",
            "schema": {
                "properties": {
                    "success": {
                        "type": "boolean"
                    },
                    "data": {
                        "$ref": "#/definitions/User"
                    }
                }
            }
        }
    }
}

I'm not sure how you feel about this approach. So basically it uses the $ import that location, in the ref variable.

This approach will take all the properties in the response that haven't been set in the child, from the parent. This includes parameters.

This can import for all definitions, parameters and responses. Just have to use $ instead of # when referencing the name.

@kevupton
Copy link
Collaborator Author

@bfanger Please let me know if you plan on doing anything with this. :3 If not I may just go ahead and create another package for this. I have tested and it still seems to work quite nicely.

bfanger pushed a commit that referenced this pull request Dec 1, 2016
bfanger pushed a commit that referenced this pull request Dec 1, 2016
@bfanger
Copy link
Collaborator

bfanger commented Dec 1, 2016

Thanks for this useful feature, I haven't had a project in which i could use swagger-php and test-drive this feature.
At least not since april ;)

I've squashed the 35 commits into a single commit and merged it into master as bfb75b2.

I'd like it if additional fixes and improvements wouldn't take this long to be merged, @zircote Could you add @kevupton as contributor?

@zircote
Copy link
Owner

zircote commented Dec 1, 2016 via email

@NorthMcCormick
Copy link

Do we have an ETA on this? It would be a huge help, such a stellar PR

bfanger added a commit that referenced this pull request Dec 16, 2016
 - Dynamic Definitions / partial support #301
 - By default only scan *.php files #350
 - Removed silence operator @, improves compatiblity custom errorhandlers #331
 - Additional datetime classes & interfaces #338
 - Fixed case of UNDEFINED constants namespaces, improves hhvm compatibility #319
 - Misc improvements to the docs
@bfanger
Copy link
Collaborator

bfanger commented Dec 16, 2016

@NorthMcCormick Today!

@MasonFI
Copy link

MasonFI commented Jun 6, 2017

Is this the right place to report bug (or maybe its me)?

When creating base response like this:

@SWG\Response(
    response="BaseResponse",
    description="Base response",
    @SWG\Schema(
        ref="#/definitions/Response"
    )
)

And "extending" my response aftewrads like this:

@SWG\Response(
    response="200",
    description="Single event",
    ref="$/responses/BaseResponse",
    @SWG\Schema(
        @SWG\Property(
        property="event",
        ref="#/definitions/Event"
        )
    )
)

Running codegen produces warning:

A PHP Error was encountered

Severity:    Warning
Message:     Invalid argument supplied for foreach()
Filename:    /var/www/api.eventos2.local/codeigniter/vendor/zircote/swagger-php/src/Processors/HandleReferences.php
Line Number: 298

And generated yaml is this for this:

"200": {
    "description": "Single event",
    "schema": {
        "properties": {
            "event": {
                "$ref": "#/definitions/Event"
            }
        },
        "$ref": "#/definitions/Response"
    }
},
...
"responses": {
        "BaseResponse": {
            "description": "Base response",
            "schema": {
                "$ref": "#/definitions/Response"
            }
        }
    }

As a result, no "event" property is added to BaseResponse. If I remove the reference, everything works great. If I create BaseResponse without reference, it also works ok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants