JsDoc export const with nested object but assigned properties - es6-modules

I have some modules, where I export Objects (as const) that contain several objects and those objects contain certain properties or functions.
For better readability I decided against direct nested structure ({ foo: {} }) in favour of assigning the objects (someObj.foo = {}).
I try to document them with JsDoc (using better-docs template) but the problem here is, that the nested properties are only generated when defined on the top-level Object:
/**
* Representation of users in the database.
*
* #module
* #property {object} schema the db schema
* #property {object} schema.username username schema
* #property {function} schema.username.type type of the username schema
*/
export const Users = {}
Users.schema = {
username: {
type: String,
},
}
Result:
However, I'd rather want to document the properties in-place for maximum readability and understanding:
/**
* Representation of users in the database.
*
* #module
* #type {object}
*/
export const Users = {}
/**
* the db schema
* #type {object}
*/
Users.schema = {
/**
* username schema
* #type {object}
*/
username: {
/**
* type of the username schema
* #type {function}
*/
type: String,
},
}
Result:
Using #memberOf has also no further effect.
How can I resolve this without the need to document everything in the top-level object?

Related

CakePHP and DefaultPasswordHasher syntax error

I have no clue why but for the line
use Cake\Auth\DefaultPasswordHasher;
I'm getting an error
Error: syntax error, unexpected '?'
and full code of user.php
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;
/**
* User Entity
*
* #property int $id
* #property string $email
* #property string $password
* #property \Cake\I18n\Time $created
* #property \Cake\I18n\Time $modified
*
* #property \App\Model\Entity\Bookmark[] $bookmarks
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* #var array
*/
protected $_accessible = [
'*' => true,
'id' => false
];
/**
* Fields that are excluded from JSON versions of the entity.
*
* #var array
*/
protected $_hidden = [
'password'
];
protected function _setPassword($value){
$hasher = new DefaultPasswordHasher();
return $hasher->hash($value);
}
}
Any thoughts? I'm using latest CakePHP
Please try with this one. Please update your CakePHP project with composer, it will update all dependency if you miss something.
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
class User extends Entity
{
// Make all fields mass assignable except for primary key field "id".
protected $_accessible = [
'*' => true,
'id' => false
];
// ...
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
// ...
}
Also please read this doc here. Hope it should be help you to solve this issue.
use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;
/**
* User Entity
*
* #property int $id
* #property string $email
* #property string $password
* #property string $role
* #property \Cake\I18n\Time $created
* #property \Cake\I18n\Time $modified
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* #var array
*/
protected $_accessible = [
'*' => true,
'id' => false
];
/**
* Fields that are excluded from JSON versions of the entity.
*
* #var array
*/
protected $_hidden = [
'password'
];
protected function _setPassword($password) {
return (new DefaultPasswordHasher)->hash($password);
}
}

Symfony REST DTO validation and inject in Model like paramconverter

I want to create a request filter for post actions in a json rest api that takes the request's body and fill the DTO, validate it and inject it in the controller action like paramconverter.
How can I do that?
I have a DTO like this:
class ExampleDTO
{
/**
* #var string
*
* #NotNull(message="El campo nombre es requerido")
* #Type(name="string", message="El campo nombre tiene un tipo incorrecto")
*/
private $nombre;
/**
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* #param string $nombre
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
}
}
Now I want to transform the json to this DTO and inject it into controller.
Actually ParamConverter works with route params (like as {id} in "/myapp.com/post/{id}"), not with request body.
If you use FOSRestBundle, Request Body Converter Listener (http://symfony.com/doc/current/bundles/FOSRestBundle/request_body_converter_listener.html) is available.
Simple example from FOSRestBundle docs:
/**
* #ParamConverter("dto", converter="fos_rest.request_body", options={"validator"={"groups"={"foo", "bar"}}})
*/
public function putAction(ExampleDTO $exampleDTO, ConstraintViolationListInterface $validationErrors)
{
if (count($validationErrors) > 0) {
// Handle validation errors
}
// ...
}
Also you should adjust your app confiuration for this approach this way:
# app/config/config.yml
sensio_framework_extra:
request: { converters: true }
# app/config/config.yml
fos_rest:
body_converter:
enabled: true

Datatransformer and json validation in symfony2 form

I'm building a Rest API and I receive a json_encoded string from the clients.
I want this string to be decoded before saving my entity, because it's going into a jsonb field in PostgreSQL.
The behavior I want is :
Validate that the string is valid json, if not, add a violation in the form via a custom validator
Automatically decode the string and set the json object in the entity property
I've tried two different strategies
In the entity setMetadata($value) method, if $value is a string, I decode it
I created a DataTransformer that json_decode the value received in the form
But both these solutions don't work because the custom validator I created is called after, and it calls directly $lesson->getMetadata(). Since the value has already been decoded (either in the setMetadata() method or in the DataTransformer, the validator receive either a json object or null. So I can't add a violation to the form, since I have no way to know if the value received was actually null, or if the string was malformed.
Here is the lesson entity:
class Lesson extends BaseContent
{
[…]
/**
* #var jsonb
*
* #ORM\Column(name="metadata", type="jsonb", nullable=true)
* #KreactiveAssert\Json
*/
private $metadata;
[…]
}
Here is the custom validator:
class JsonValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if ($value && !json_decode($value)) {
$this->context->addViolation($constraint->message, array('%string%' => $value));
}
}
}
And here is the DataTransformer:
class StringToJsonTransformer implements DataTransformerInterface
{
/**
* Transform a json object to a string
* #param Json|null $json
* #return String
*/
public function transform($json)
{
if (null === $json) {
return "";
}
return json_encode($json);
}
/**
* Transform a string to a json object
* #param String $string
* #return Object
*/
public function reverseTransform($string)
{
if (!$string) {
return null;
}
throw new TransformationFailedException('error transforming');
return json_decode($string);
}
}
Is there any way I can validate the input data in the form, and then set the metadata as a json object?
I've found this (I don't know how come I didn't find it earlier):
Combine constraints and data transformers
I'm going to make an ugly workaround as suggested, even though I don't like that solution.
<?php
class StringToJsonTransformer implements DataTransformerInterface
{
/**
* Transform a string to a json object
* #param String $string
* #return Object
*/
public function reverseTransform($string)
{
if (!$string) {
return null;
}
/*
* UGLY WORKAROUND
* we return -1 if the json_decode fail
* so the validator can add a violation in the form telling
* the json string was not valid
* If we don't do this, the validator will receive either
* null or a json object. In case of null, there is no way to
* tell if the client sent null, or if the decoding failed
*/
$value = json_decode($string);
return $value ? $value : -1;
}
}
I'm still not sure if I'm going to return -1 or something else. In the custom validator, I get an error if I try to compare a jsonObject with -1 (which is normal).

How to declare a EventSubscriber in config.yml using bazinga_geocoder.geocoder service?

I am planning to make a reverse geocoding based on the BazingaGeocoderBundle. A simple way to do that is write this simple code in the controller:
$result = $this->container
->get('bazinga_geocoder.geocoder')
->using('google_maps')
->reverse(48.79084170157100,2.42479377175290);
return $this->render("MinnAdsBundle:Motors:test.html.twig",
array('result'=>var_dump($result)));
Until here, things are going well.
My objective is to make the code nicer & resuable. So, I used this article to write my own GeocoderEventSubscriber as describer below:
<?php
namespace Minn\AdsBundle\Doctrine\Event;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Event\LifecycleEventArgs;
//use Geocoder\Provider\ProviderInterface;
use Bazinga\Bundle\GeocoderBundle\Geocoder\LoggableGeocoder;
/**
* Subscribes to Doctrine prePersist and preUpdate to update an
* the address components of a MotorsAds entity
*
* #author majallouli
*/
class MotorsAdsGeocoderEventSubscriber implements EventSubscriber {
protected $geocoder;
public function __construct(LoggableGeocoder $geocoder){
$this->geocoder = $geocoder;
}
/**
* Specifies the list of events to listen
*
* #return array
*/
public function getSubscribedEvents(){
return array(
'prePersist',
'preUpdate',
);
}
/**
* Sets a new MotorsAds's address components if not present
*
* #param LifecycleEventArgs $eventArgs
*/
public function prePersist(LifecycleEventArgs $eventArgs){
$motorsAds = $eventArgs->getEntity();
if($motorsAds instanceof \Minn\AdsBundle\Entity\MotorsAds){
if( !$motorsAds->getCountry()){
$em = $eventArgs->getEntityManager();
$this->geocodeMotorsAds($motorsAds,$em);
}
}
}
/**
* Sets an updating MotorsAds's address components if not present
* or any part of address updated
*
* #param PreUpdateEventArgs $eventArgs
*/
public function preUpdate(PreUpdateEventArgs $eventArgs){
$motorsAds = $eventArgs->getEntity();
if($motorsAds instanceof \Minn\AdsBundle\Entity\MotorsAds){
if( !$motorsAds->getCountry() ){
$em = $eventArgs->getEntityManager();
$this->geocodeMotorsAds($motorsAds,$em);
$uow = $em->getUnitOfWork();
$meta = $em->getClassMetadata(get_class($motorsAds));
$uow->recomputeSingleEntityChangeSet($meta, $motorsAds);
}
}
}
/**
* Geocode and set the MotorsAds's address components
*
* #param type $motorsAds
*/
private function geocodeMotorsAds($motorsAds,$em){
$result = $this->geocode
->using('google_maps')
->reverse($motorsAds->getLat(),$motorsAds->getLng());
$motorsAds->setCountry(
$em->getRepository("MinnAdsBundle:Country")->findCountryCode($result['countryCode']));
}
}
After that, I declared my EventSubscriber as a service:
services:
# ...
geocoder_motorsads.listener:
class: Minn\AdsBundle\Doctrine\Event\MotorsAdsGeocoderEventSubscriber
arguments: [#bazinga_geocoder.geocoder] # almost sure that the error is here!!
tags:
- { name: doctrine.event_subscriber }
Actually, I get this error:
ContextErrorException: Notice: Undefined property: Minn\AdsBundle\Doctrine\Event\MotorsAdsGeocoderEventSubscriber::$geocode in /home/amine/NetBeansProjects/tuto/src/Minn/AdsBundle/Doctrine/Event/MotorsAdsGeocoderEventSubscriber.php line 78
I am almost sure that error is in the declaration of arguments of the EventSubscriber. Is it #bazinga_geocoder.geocoder?
Thank you for your help!
Your property is $this->geocoder but you're calling $this->geocode, you're spelling it wrong.

Zend Framework 1.9.2+ Zend_Rest_Route Examples

With the introduction of Zend_Rest_Route in Zend Framework 1.9 (and its update in 1.9.2) we now have a standardized RESTful solution for routing requests. As of August 2009 there are no examples of its usage, only the basic documentation found in the reference guide.
While it is perhaps far more simple than I assume, I was hoping those more competent than I might provide some examples illustrating the use of the Zend_Rest_Controller in a scenario where:
Some controllers (such as indexController.php) operate normally
Others operate as rest-based services (returning json)
It appears the JSON Action Helper now fully automates and optimizes the json response to a request, making its use along with Zend_Rest_Route an ideal combination.
Appears it was rather simple. I've put together a Restful Controller template using the Zend_Rest_Controller Abstract. Simply replace the no_results return values with a native php object containing the data you want returned. Comments welcome.
<?php
/**
* Restful Controller
*
* #copyright Copyright (c) 2009 ? (http://www.?.com)
*/
class RestfulController extends Zend_Rest_Controller
{
public function init()
{
$config = Zend_Registry::get('config');
$this->db = Zend_Db::factory($config->resources->db);
$this->no_results = array('status' => 'NO_RESULTS');
}
/**
* List
*
* The index action handles index/list requests; it responds with a
* list of the requested resources.
*
* #return json
*/
public function indexAction()
{
// do some processing...
// Send the JSON response:
$this->_helper->json($this->no_results);
}
// 1.9.2 fix
public function listAction() { return $this->_forward('index'); }
/**
* View
*
* The get action handles GET requests and receives an 'id' parameter; it
* responds with the server resource state of the resource identified
* by the 'id' value.
*
* #param integer $id
* #return json
*/
public function getAction()
{
$id = $this->_getParam('id', 0);
// do some processing...
// Send the JSON response:
$this->_helper->json($this->no_results);
}
/**
* Create
*
* The post action handles POST requests; it accepts and digests a
* POSTed resource representation and persists the resource state.
*
* #param integer $id
* #return json
*/
public function postAction()
{
$id = $this->_getParam('id', 0);
$my = $this->_getAllParams();
// do some processing...
// Send the JSON response:
$this->_helper->json($this->no_results);
}
/**
* Update
*
* The put action handles PUT requests and receives an 'id' parameter; it
* updates the server resource state of the resource identified by
* the 'id' value.
*
* #param integer $id
* #return json
*/
public function putAction()
{
$id = $this->_getParam('id', 0);
$my = $this->_getAllParams();
// do some processing...
// Send the JSON response:
$this->_helper->json($this->no_results);
}
/**
* Delete
*
* The delete action handles DELETE requests and receives an 'id'
* parameter; it updates the server resource state of the resource
* identified by the 'id' value.
*
* #param integer $id
* #return json
*/
public function deleteAction()
{
$id = $this->_getParam('id', 0);
// do some processing...
// Send the JSON response:
$this->_helper->json($this->no_results);
}
}
great post, but I would have thought the Zend_Rest_Controller would route the request to the right action with respect to the HTTP method used. It'd be neat if a POST request to http://<app URL>/Restful would automatically _forward to postAction for example.
I'll go ahead and provide another strategy below, but maybe I'm missing the point behind Zend_Rest_Controller ... please comment.
My strategy:
class RestfulController extends Zend_Rest_Controller
{
public function init()
{
$this->_helper->viewRenderer->setNoRender();
$this->_helper->layout->disableLayout();
}
public function indexAction()
{
if($this->getRequest()->getMethod() === 'POST')
{return $this->_forward('post');}
if($this->getRequest()->getMethod() === 'GET')
{return $this->_forward('get');}
if($this->getRequest()->getMethod() === 'PUT')
{return $this->_forward('put');}
if($this->getRequest()->getMethod() === 'DELETE')
{return $this->_forward('delete');}
$this->_helper->json($listMyCustomObjects);
}
// 1.9.2 fix
public function listAction() { return $this->_forward('index'); }
[the rest of the code with action functions]