swagger-ui How do you hide rest methods not implemented - symfony

Maybe im just missing it, I would like to hide some rest methods from controllers that do not implement them like options , delete, head
Is there an annotation for this? I could not find it in the documentation
using https://github.com/nelmio/NelmioApiDocBundle v3
currently when i view /api/doc any controllers I add list all rest methods even if I only have a GET method implemented.
<?php
namespace ApiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Swagger\Annotations as SWG;
class UserController extends Controller
{
/**
* #Security("is_granted('IS_AUTHENTICATED_FULLY')")
* #Route("/api/users", name="get_users", methods={"GET"})
*
* #SWG\Response(
* response=200,
* description="Returns all users"
* )
* #SWG\Tag(name="users")
*
*
* #return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function getUsersAction()
{
$repo = $this->getDoctrine()
->getRepository('AccountBundle:User');
$users = $repo->createQueryBuilder('q')
->getQuery()
->getArrayResult();
return new JsonResponse($users);
}
}

Just figured it out if you do not specify the methods in the controller in the #Route() annotation then it will show all of them but if you add methods={} to the Route annotation then it will only list the defined methods
* #Route("/api/users", name="get_users", methods={"GET"})

Specify #Value and #method type in the #RequestMapping
#RequestMapping(value="/instances/all",method=RequestMethod.GET)
#JsonFormat
public String showInstances(){
return "instances";
}

Related

Get serialization context groups in controller

I have the problem that depending on user rights, there are different context groups used, and I can't find the place where the context groups are set.
For debugging issues I'm searching an possibility to find out which serialization context group an api call is using. This is my code:
<?php
namespace AppBundle\Controller\Api\Upload;
use AppBundle\Entity\Upload\UploadRepository;
use AppBundle\Entity\Upload\UploadType;
use AppBundle\Entity\Upload\UploadTypeRepository;
use Doctrine\ORM\ORMException;
use GuzzleHttp\Psr7\UploadedFile;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use AppBundle\General\Registry;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use AppBundle\Entity\Upload\Upload;
use AppBundle\Entity\Application\ApplicationData;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\Serializer\Serializer;
/**
* Class UploadController
*
* #package AppBundle\Controller\Api\Upload
*
* #ApiDoc()
* #ApiResource(attributes={"pagination_enabled"=true})
*/
class UploadController extends Controller
/**
* Get an upload.
*
* #ApiDoc(
* resource=true,
* description="gets an upload",
* )
* #Route(
* name="getUploadSpecial",
* path="/fileuploads/{id}",
* defaults={"_api_resource_class"=Upload::class, "_api_item_operation_name"="getUpload"}
* )
* #Method("GET")
*
* #param Upload $data
*
* #return null|string
*
*/
public function getUploadAction($data)
{
// here I'd like to return the serialization context group
return $data;
}
Is there the possibility to get the serialization context group in the controller?
Well, it seems, the controller isn't the right place to find it.
It is better to dump in
src/Serializer/JsonEncoder.php in function encode, right before the return like this:
/**
* {#inheritdoc}
*/
public function encode($data, $format, array $context = [])
{
dump($data, $context);die;
return $this->jsonEncoder->encode($data, $format, $context);
}

Symfony 4. Methods from the repository of the abstract class are not available

I have an abstract class:
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({
* "LegalInsuranceProof" = "LegalInsuranceProofDocument",
* "SalesReceipt" = "SalesReceiptDocument"
* })
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="document_abstract")
* #ORM\Entity(repositoryClass="App\Repository\DocumentRepository")
*/
abstract class AbstractDocument implements CreateFolderInterface
{
.
.
.
}
and the class, that extends this abstract class:
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="document_sales_receipt")
*/
class SalesReceiptDocument extends AbstractDocument
{
.
.
.
}
In the repo, I have defined the method getReviewListPaginator:
class DocumentRepository extends ServiceEntityRepository {
use PaginatorTrait;
public function __construct(RegistryInterface $registry) {
parent::__construct($registry, AbstractDocument::class);
}
public function getReviewListPaginator($limit, $offset) {
$this->assertQueryParameters($offset, $limit, "asc");
$qb = $this
->createQueryBuilder('d')
->select('PARTIAL d.{id, pageCount}')
->innerJoin('d.case', 'c')
->addSelect('PARTIAL c.{id}')
->setFirstResult($offset)
->setMaxResults($limit);
return new Paginator(
$qb->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY),
true
);
}
}
If I do
$this->em->getRepository(AbstractDocument::class)->getReviewListPaginator(5,2);
the method getReviewListPaginator is called.
But If I do
$paginator = $this->em->getRepository(SalesReceiptDocument::class)->getReviewListPaginator(5,2);
I get en error message:
BadMethodCallException : Undefined method 'getReviewListPaginator'. The method name must start with either findBy, findOneBy or countBy!
But why? Should I define a repo for the SalesReceiptDocument entity, that extends the App\Repository\DocumentRepository?
I don't think the Repository are extended by default.
I think you need to do a SalesReceiptReporsitory that explicitly exteands your DocumentRepository
And add the repositoryClass options to your #Entity on SalesReceiptDocument.
Your #Entity annotations do not have the repository specified, change them to:
#Entity(repositoryClass="..namespace..\DocumentRepository")
See the #Entity documentation.
Edit 1:
I just noticed your AbstractDocument has duplicate #Entity annotation, you can just delete the empty one
Edit 2:
To select different document types you need separate repositories, to keep your code simple and non-repeating, you can use the $_entityName attribute of EntityRepository if you are extending it or have your own private attribute that would indicate the entity name for a repository and then use this entity name in the getReviewListPaginator to dynamically query the type of entity you want.
As far as I can tell, you cannot achieve this without having separate repositories for each type of document - even if each is empty, just extending the base repository and doing the parametrized query building as I described.

FOSRestBundle : I can't see my new route

I've created a new controller (testController) which extends FOSRestController. I can't see the route "/test" i've created in this controller when I run symfony command "debug:router". With Postman, I've a 404 error...
I'm sure I forgot something but I don't know what. Here my code :
testController.php
<?php
namespace Project\ApiBundle\Controller;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Delete;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\Put;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\View\RouteRedirectView;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use JMS\Serializer\SerializationContext;
/**
* Class testController.
*/
class testController extends FOSRestController
{
/**
* List .
* #ApiDoc(
* resource = true,
* statusCodes = {
* 200 = "Returned when successful"
* }
* )
*
* #Rest\View()
* #Get("/test")
*
* #param Request $request the request object
*
* #return array
*/
public function getTest(Request $request)
{
return "hello world";
}
}
And, here my routing.yml file :
api_test:
type: rest
resource: Project\ApiBundle\Controller\TestController
What I've forgot ?
Thank you very much !
I finally found the answer... so easy but I didn't see it ! The method name :
=> getTestAction

FOSUserbundle access user from other controller

I'm using FOSUserbunble, how can access the user object from another controller/form in another bunble?
for example I have a BlogBundle and when I create a new post I need to save the userId in the post table.
for the form I'm using buildForm extending AbstractType.
thanks
Try $user = $this->getUser();
You can do it via SecurityContext.
let's a example ..
namespace YourPackage\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Model\UserInterface;
class YourController extends Controller{
/**
* Fetch a user object.
*
* #Route("/yourRoute", name="your_route")
* #Method()
* #Template()
*/
public function yourAction(Request $request)
{
$user = $this->container->get('security.context')->getToken()->getUser();
return $this->redirect($this->generateUrl('your_route'));
}}

override symfony2 bundle controller actions

/src/Vendor/JobQueueBundle/Controller/DefaultController.php
namespace Vendor\JobQueueBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\JobQueueBundle\Controller\JobController;
/**
* #Route("/jobs")
*/
class DefaultController extends JobController
{
/**
* #Route("/index")
*/
public function indexAction()
{
die();
}
}
/app/config/routing.yml
vendor_api_job_queue:
resource: "#VendorJobQueueBundle/Controller/"
type: annotation
prefix: /
JMSJobQueueBundle:
resource: "#JMSJobQueueBundle/Controller/"
type: annotation
/src/Syntetik/API/JobQueueBundle/SyntetikAPIJobQueueBundle.php
namespace Vendor\JobQueueBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class VendorJobQueueBundle extends Bundle
{
public function getParent()
{
return 'JMSJobQueueBundle';
}
}
When I try to call /jobs/index I get:
Method "JMS\JobQueueBundle\Controller\JobController::indexAction" does not exist.
DefaultController is completely ignored and not sure why?
Thanks!
It's known and opened issue of JMSDiExtraBundle https://github.com/schmittjoh/JMSDiExtraBundle/issues/39 so problem is that DiExtarBundle doesn't lookup parent class for annotations if child class has not at least one JMS annotation, so proxy class isn't generate at the metadata cache (look app/cache/dev/jms_diextra/metadata/)
The quickest solution is leave at least on annotation:
Parent Controller >>
<?php
namespace Namespace\SiteBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation as DI;
class IndexController extends Controller
{
/**
* #DI\Inject("doctrine.orm.entity_manager")
* #var \Doctrine\ORM\EntityManager $em
*/
protected $em;
/**
* #DI\Inject("namespace.search.manager")
* #var Namespace\SearchBundle\Services\SearchManager $searchManager
*/
protected $searchManager;
/**
* #DI\Inject("namespace.product.manager")
* #var Namespace\ProductBundle\Services\ProductManager $productManager
*/
protected $productManager;
/**
* #Route("/", name="homepage")
* #Template()
*/
public function indexAction() {
echo "parent!";
$defaultCategory = $this->searchManager->getDefaultCategory();
....
return $result;
}
}
Child controller >>
<?php
namespace OtherSpace\SiteBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation as DI;
use Namespace\SiteBundle\Controller\IndexController as BaseIndexController;
class IndexController extends BaseIndexController
{
/**
* The temprary solution base on known JMS/DiExtraBundle open issue https://github.com/schmittjoh/JMSDiExtraBundle/issues/39
* **We need to leave at leat one Inject in child class to get a proxy generated**
*
* #DI\Inject("doctrine.orm.entity_manager")
* #var \Doctrine\ORM\EntityManager $em
*/
protected $em;
/**
* #Route("/", name="homepage")
* #Template()
*/
public function indexAction() {
echo "child!";
$result = parent::indexAction();
return $result;
}
}
So this way proxy class will be generated for SpaceOther-IndexController and annotations will work
I also worked around fix this issue, you can look to my pull request https://github.com/schmittjoh/JMSDiExtraBundle/pull/153
Figured out the problem with this. It seems it's not symfony2 specific.
The problem is JMS\DiExtraBundle\JMSDiExtraBundle which mess the things around. Just removing that bundle makes everything works by the book.
Thanks!

Resources