I have a MediaObject exposed as a subresource within a normalization context group "modules":
/**
* #ApiResource(
* attributes={"access_control"="is_granted('ROLE_ADMIN')"},
* collectionOperations={
* "get",
* "post",
* "allData"={
* "method"="GET",
* "path"="/appdata",
* "normalization_context"={"groups"={"modules"}},
* "access_control"="is_granted('IS_AUTHENTICATED_ANONYMOUSLY')"
* }
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\LearningModuleRepository")
* #UniqueEntity("identifier")
*
*/
class LearningModule
/**
* #ORM\Entity(
* repositoryClass="App\Repository\MediaObjectRepository"
* )
* #ApiResource(
* iri="http://schema.org/MediaObject",
* normalizationContext={
* "groups"={"media_object_read"},
* },
* attributes={"access_control"="is_granted('ROLE_ADMIN')"},
* collectionOperations={
* "post"={
* "controller"=CreateMediaObject::class,
* "deserialize"=false,
* "validation_groups"={"Default", "media_object_create"},
* "swagger_context"={
* "consumes"={
* "multipart/form-data",
* },
* "parameters"={
* {
* "in"="formData",
* "name"="file",
* "type"="file",
* "description"="The file to upload",
* },
* },
* },
* },
* "get",
* },
* itemOperations={
* "get",
* "delete"
* },
* )
* #Vich\Uploadable
*/
class MediaObject
/**
* #var string|null
*
* #ApiProperty(iri="http://schema.org/contentUrl")
* #Groups({"media_object_read", "modules"})
*/
public $contentUrl;
/**
* #var string|null
* #Groups({"modules"})
* #ORM\Column(nullable=true)
*/
public $filePath;
When exposed through the normalization group I only get filePath but not contentUrl. Im assuming the propblem has to do with the the ContentUrlSubscriber as outlined in the official docs:
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => ['onPreSerialize', EventPriorities::PRE_SERIALIZE],
];
}
public function onPreSerialize(GetResponseForControllerResultEvent $event): void
{
$controllerResult = $event->getControllerResult();
$request = $event->getRequest();
if ($controllerResult instanceof Response || !$request->attributes->getBoolean('_api_respond', true)) {
return;
}
if (!($attributes = RequestAttributesExtractor::extractAttributes($request)) || !\is_a($attributes['resource_class'], MediaObject::class, true)) {
return;
}
$mediaObjects = $controllerResult;
if (!is_iterable($mediaObjects)) {
$mediaObjects = [$mediaObjects];
}
foreach ($mediaObjects as $mediaObject) {
if (!$mediaObject instanceof MediaObject) {
continue;
}
$mediaObject->contentUrl = $this->storage->resolveUri($mediaObject, 'file');
}
}
Does anybody have a clue how to handle the preSerialization in this case?
Thank You
I have found a solution to this problem:
The callback on PRE_SERIALIZE is aborted, since a LearningModule Object (not a MediaObject) has triggered the serialization ($attributes['resource_class'] === LearningModule).
To overcome this limitation, a decorated normalizer should be used as follows:
<?php
namespace App\Serializer;
use App\Entity\MediaObject;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Vich\UploaderBundle\Storage\StorageInterface;
final class MediaObjectContentUrlNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
private $decorated;
private $storage;
public function __construct(NormalizerInterface $decorated, StorageInterface $storage)
{
if (!$decorated instanceof DenormalizerInterface) {
throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));
}
$this->decorated = $decorated;
$this->storage = $storage;
}
public function supportsNormalization($data, $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
public function normalize($object, $format = null, array $context = [])
{
$data = $this->decorated->normalize($object, $format, $context);
if ($object instanceof MediaObject) {
$data['contentUrl'] = $this->storage->resolveUri( $object, 'file');
}
return $data;
}
public function supportsDenormalization($data, $type, $format = null)
{
return $this->decorated->supportsDenormalization($data, $type, $format);
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->decorated->denormalize($data, $class, $format, $context);
}
public function setSerializer(SerializerInterface $serializer)
{
if($this->decorated instanceof SerializerAwareInterface) {
$this->decorated->setSerializer($serializer);
}
}
}
Implementation details can be found here:
https://api-platform.com/docs/core/serialization/#decorating-a-serializer-and-adding-extra-data
Related
Good day everyone! I encounter some problem. I have sonata admin + symfony 4 + some entities with manytoone relations. I have 3 simple tables named banner videobanner photobanner and now i want to create admin part which will be created from 1 2 or 3 simple banners video banners or photobbanners. It is almost done but the form have some bugs. I can create simple banner and it is ok record created sucessfully but parentId is empty because it does not have any parents for now but later when im set in in admin parentId is createing in child table but later when im trying to delete the relation sonata admin deletes it with a child record, but i want sonata admin to delete only parentId child record must stay with parentId = NULL.
<?php
namespace App\Admin\Action\Banner;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use App\Cms\Entity\Banner\NestedBanner;
use App\Admin\Form\DataTransformer\BannerDataTransformer;
use App\Cms\Entity\Banner\Banner;
/**
*
* Class NestedBannerAdmin.
*/
class NestedBannerAdmin extends AbstractAdmin
{
/**
*
* #param FormMapper $formMapper
*/
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('title', TextType::class);
$formMapper->add('description', TextareaType::class);
$formMapper->add('banners');
$formMapper->add('photoBanners');
$formMapper->add('videoBanners');
$formMapper->add('promoBlockBanners');
// $formMapper
// ->get('banners')
// ->addModelTransformer(new BannerDataTransformer($this->getSubject()));
}
/**
*
* #param DatagridMapper $datagridMapper
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('title');
$datagridMapper->add('description');
$datagridMapper->add('banners');
$datagridMapper->add('photoBanners');
$datagridMapper->add('videoBanners');
$datagridMapper->add('promoBlockBanners');
}
/**
*
* #param ListMapper $listMapper
*/
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('title');
$listMapper->addIdentifier('description');
$listMapper->add(
'banners',
null,
[
'label' => 'Banners',
'sortable' => false,
'allow_add' => false,
'allow_delete' => false,
]
);
$listMapper->add(
'photoBanners',
null,
[
'label' => 'Photo banners',
'sortable' => false,
'allow_add' => true,
'allow_delete' => false,
]
);
$listMapper->add(
'videoBanners',
null,
[
'label' => 'Video banners',
'sortable' => false,
'allow_add' => true,
'allow_delete' => false,
]
);
$listMapper->add(
'promoBlockBanners',
null,
[
'label' => 'Promo block banners',
'sortable' => false,
'allow_add' => true,
'allow_delete' => false,
]
);
}
public function preUpdate($object)
{
// dd($object);
if($object instanceof NestedBanner){
foreach ($object->getBanners() as $banner) {
$nestedBanner = $banner->getNestedBanner();
if(null == $nestedBanner){
$banner->setNestedBanner($object);
}
}
foreach ($object->getVideoBanners() as $banner) {
$nestedBanner = $banner->getNestedBanner();
if(null == $nestedBanner){
$banner->setNestedBanner($object);
}
}
foreach ($object->getPhotoBanners() as $banner) {
$nestedBanner = $banner->getNestedBanner();
if(null == $nestedBanner){
$banner->setNestedBanner($object);
}
}
foreach ($object->getPromoBlockBanners() as $banner) {
$nestedBanner = $banner->getNestedBanner();
if(null == $nestedBanner){
$banner->setNestedBanner($object);
}
}
}
}
}
<?php
namespace App\Cms\Entity\Banner;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use App\Cms\Entity\Banner\Banner;
use App\Cms\Entity\Banner\PhotoBanner;
use App\Cms\Entity\Banner\VideoBanner;
use App\Cms\Entity\Banner\PromoBlockBanner;
/**
*
* #ORM\Entity(repositoryClass="App\Cms\Repository\Banner\NestedBannerRepository")
* #ORM\Table(name="nested_banner")
*/
class NestedBanner {
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #var bannerMaps
*
* #ORM\OneToMany(
* targetEntity="App\Cms\Entity\Banner\Banner",
* mappedBy="nestedBanner",
* orphanRemoval=true,
* cascade={"persist"}
* )
*
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $banners;
/**
* #var bannerMaps
*
* #ORM\OneToMany(
* targetEntity="App\Cms\Entity\Banner\VideoBanner",
* mappedBy="nestedBanner",
* orphanRemoval=true,
* cascade={"persist"})
*
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $videoBanners;
/**
* #var bannerMaps
*
* #ORM\OneToMany(
* targetEntity="App\Cms\Entity\Banner\PhotoBanner",
* mappedBy="nestedBanner",
* cascade={"persist"}),
* orphanRemoval=false
*
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $photoBanners;
/**
* #var bannerMaps
*
* #ORM\OneToMany(
* targetEntity="App\Cms\Entity\Banner\PromoBlockBanner",
* mappedBy="nestedBanner",
* cascade={"persist"})
*
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $promoBlockBanners;
/**
*
* #param type $id
* #param type $title
* #param type $description
* #param Collection $bannerMaps
*/
public function __construct() {
// $this->banners = new ArrayCollection();
// $this->videoBanners = new ArrayCollection();
// $this->photoBanners = new ArrayCollection();
// $this->promoBlockBanners = new ArrayCollection();
}
/**
*
* #return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
*
* #return string
*/
public function getTitle(): ?string
{
return $this->title;
}
/**
*
* #return string
*/
public function getBanners(): ?Collection
{
return $this->banners;
}
/**
*
* #return string
*/
public function getVideoBanners(): ?Collection
{
return $this->videoBanners;
}
/**
*
* #return string
*/
public function getPhotoBanners(): ?Collection
{
return $this->photoBanners;
}
/**
*
* #return string
*/
public function getPromoBlockBanners(): ?Collection
{
return $this->promoBlockBanners;
}
/**
*
* #return string
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
*
* #param int $id
*/
public function setId(int $id)
{
$this->id = $id;
}
/**
*
* #param string $title
*/
public function setTitle(string $title)
{
$this->title = $title;
}
/**
*
* #param Collection $banners
*/
public function addBanner(Banner $banner): self
{
dd('addBanner');
$this->banners[] = $banner;
return $this;
}
/**
*
* #param Collection $banners
*/
public function addBanners(Collection $banners): self
{
dd('addBanners');
$this->banners[] = $banner;
return $this;
}
/**
*
* #param Collection $banners
*/
public function setBanners(Collection $banners): self
{
dd('setBanners');
foreach($banners as $banner){
$banner->setNestedBanner($this);
}
$this->banners = $banners;
return $this;
}
/**
*
* #param Collection $banners
*/
public function removeBanner(Banner $banners): self
{
dd('removeBanner');
foreach($banners as $banner){
$banner->setNestedBanner($this);
}
$this->banners = $banners;
return $this;
}
/**
*
* #param Collection $banners
*/
public function banner(Banner $banners): self
{
dd('Banner');
foreach($banners as $banner){
$banner->setNestedBanner($this);
}
$this->banners = $banners;
return $this;
}
/**
*
* #param Collection $videoBanners
*/
public function setVideoBanners(Collection $videoBanners): self
{
$this->videoBanners = $videoBanners;
return $this;
}
/**
*
* #param Collection $photoBanners
*/
public function setPhotoBanners(Collection $photoBanners): self
{
$this->photoBanners = $photoBanners;
return $this;
}
/**
*
* #param Collection $banners
*/
public function setPromoBlockBanners(Collection $promoBlockBanners): self
{
$this->promoBlockBanners = $promoBlockBanners;
return $this;
}
/**
*
* #param string $description
*/
public function setDescription(string $description)
{
$this->description = $description;
}
// public function addBanner(Banner $banner): NestedBanner
// {
//
// dd($banner);
// $this->banners->add($banner);
//
// return $this;
// }
//
// public function setBanner(Banner $banner): NestedBanner
// {
//
// dd($banner);
// $this->banners->add($banner);
//
// return $this;
// }
// public function addPhotoBanner(PhotoBanner $photoBanner): NestedBanner
// {
// $this->photoBanners->add($photoBanner);
//
// return $this;
// }
//
// public function addVideoBanner(VideoBanner $videoBanner): NestedBanner
// {
// $this->videoBanners->add($videoBanner);
//
// return $this;
// }
//
// public function addPromoBlockBanner(PromoBlockBanner $promoBlockBanner): NestedBanner
// {
// $this->promoBlockBanners->add($promoBlockBanner);
//
// return $this;
// }
// public function removeBanner(Banner $banner): NestedBanner
// {
// $this->banners->removeElement($banner);
//
// return $this;
// }
//
// public function removePhotoBanner(PhotoBanner $photoBanner): NestedBanner
// {
// $this->photoBanners->removeElement($photoBanner);
//
// return $this;
// }
//
// public function removeVideoBanner(VideoBanner $videoBanner): NestedBanner
// {
// $this->videoBanners->removeElement($videoBanner);
//
// return $this;
// }
//
// public function removePromoBlockBanner(PromoBlockBanner $promoBlockBanner): NestedBanner
// {
// $this->promoBlockBanners->removeElement($promoBlockBanner);
//
// return $this;
// }
public function remove($param){
dd($param);
}
}
<?php
namespace App\Cms\Entity\Banner;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use App\Cms\Entity\Banner\NestedBanner;
/**
*
* #ORM\Entity(repositoryClass="App\Cms\Repository\Banner\BannerRepository")
* #ORM\Table(name="banner")
* #Vich\Uploadable()
*/
class Banner {
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var File
* #Vich\UploadableField(mapping="banner_background_image", fileNameProperty="backgroundImageName")
* #Assert\Image(
* mimeTypes = {"image/jpeg", "image/png", "image/svg+xml"},
* mimeTypesMessage = "Дозволені тільки формати (jpg,png,svg)",
* maxSize = "2M",
* maxSizeMessage = "Максимальний розмір 2Mb"
* )
*/
private $backgroundImage;
/**
* #var string
* #ORM\Column(type="string", nullable=true)
*/
private $backgroundImageName;
/**
* #ORM\Column(name="link", type="string", length=255)
*/
private $link;
/**
* #var $nestedBanner
*
* #ORM\ManyToOne(
* targetEntity="App\Cms\Entity\Banner\NestedBanner",
* inversedBy="banners")
*
*/
private $nestedBanner;
public function __construct()
{
}
/**
*
* #return type
*/
public function getId()
{
return $this->id;
}
/**
*
* #return type
*/
public function getTitle(): ?string
{
return $this->title;
}
/**
*
* #return type
*/
public function getName(): ?string
{
return $this->getBackgroundImageName();
}
/**
*
* #return type
*/
public function getBackgroundImage(): ?File
{
return $this->backgroundImage;
}
/**
*
* #return type
*/
public function getBackgroundImageName()
{
return $this->backgroundImageName;
}
/**
*
* #return type
*/
public function getLink()
{
return $this->link;
}
/**
*
* #return array
*/
public function getNestedBanner(): ?NestedBanner
{
return $this->nestedBanner;
}
/**
*
* #param type $id
*/
public function setId(int $id)
{
$this->id = $id;
}
/**
*
* #param string $title
*/
public function setTitle(string $title)
{
$this->title = $title;
}
/**
*
* #param string $backgroundImage
*/
public function setBackgroundImage(File $backgroundImage)
{
$this->backgroundImage = $backgroundImage;
if(!$this->backgroundImageName){
$this->backgroundImageName = $backgroundImage->getClientOriginalName();
}
}
/**
*
* #param string $backgroundImageName
*/
public function setBackgroundImageName($backgroundImageName)
{
$this->backgroundImageName = $backgroundImageName;
}
/**
*
* #param string $link
*/
public function setLink(string $link)
{
$this->link = $link;
}
/**
*
* #param NestedBanner $nestedBanner
*/
public function setNestedBanner(NestedBanner $nestedBanner)
{
$this->nestedBanner = $nestedBanner;
return $this;
}
/**
* #return string
*/
public function __toString(): string
{
return $this->title ?: '';
}
}
Consider taking a look at sonata's saving hooks.
It looks like you're already using the preUpdate() function and could utilize the preRemove() function to achieve what you are looking for.
You'll also likely have to remove onDelete="CASCADE" from your entity.
I have created this resource in order to request a password reset token:
POST {{api_base_url}}/users/password/reset-request
Payload example
{
"email" :"user#example.com"
}
Everything works fine but the response doesn't serialize ResetPasswordRequestOutput to show the result. I got this response instead (as User type)
{
"#context": {
"#vocab": "http://dev.api.xxxxxxxxxx.com/docs.jsonld#",
"hydra": "http://www.w3.org/ns/hydra/core#",
"token": "ResetPasswordRequestOutput/token"
},
"#type": "User",
"#id": "/users/00000000-0000-0000-0000-000000000002",
"token": "ORGOsGh01sr8R91J"
}
Expected output: (of type: ResetPasswordRequestOutput)
{
"#type": "ResetPasswordRequestOutput",
"token": "ORGOsGh01sr8R91J"
}
Code:
The controller class of the custom operation:
final class ResetPasswordRequest {
private $validator;
private $entityManager;
public function __construct(ValidatorInterface $validator, EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
$this->validator = $validator;
}
public function __invoke(ResetPasswordRequestInput $data)
{
$this->validator->validate($data);
$userRepository = $this->entityManager->getRepository(User::class);
/** #var User $user */
$user = $userRepository->findOneBy(['email' => $data->email]);
if (!$user) {
throw new ItemNotFoundException("invalid token");
}
if ($user->getStatus() !== UserStatus::ACTIVE) {
throw new AccessDeniedException("user is inactive");
}
$generator = (new Factory())->getGenerator(new Strength(Strength::MEDIUM));
$token = $generator->generateString(16, 'BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
$user->setToken($token);
return $user;
}
}
The data transofrmer that converts User object to ResetPasswordRequestOutput
namespace App\DataTransformer;
final class ResetPasswordRequestOutputDataTransformer implements DataTransformerInterface
{
private $normalizer;
public function __construct(NormalizerInterface $normalizer)
{
$this->normalizer = $normalizer;
}
/**
* {#inheritdoc}
*/
public function transform($data, string $to, array $context = [])
{
$output = new ResetPasswordRequestOutput();
$output->token = $data->getToken();
return $output;
}
/**
* {#inheritdoc}
*/
public function supportsTransformation($data, string $to, array $context = []): bool
{
return ResetPasswordRequestOutput::class === $to && $data instanceof User;
}
DTO object that holds input data
<?php
namespace App\Dto;
final class ResetPasswordRequestInput
{
/**
* #var string
*
* #Assert\Email
* #Groups({"user:write"})
*/
public $email;
}
DTO object that holds output data
namespace App\Dto;
final class ResetPasswordRequestOutput
{
/**
* #var string
*
* #Assert\NotNull()
* #Groups({"user:read"})
*/
public $token;
}
User Entity class with ApiResource annotation (partial) action=reset_password_request
/**
* #ApiResource(
* normalizationContext={"groups"={"user", "user:read"}},
* denormalizationContext={"groups"={"user", "user:write"}},
* collectionOperations={
* "get",
* "post",
* "reset_password_request" = {
* "method"= "POST",
* "read"=false,
* "path"="/users/password/reset-request",
* "controller"=ResetPasswordRequest::class,
* "status"=200,
* "input"=ResetPasswordRequestInput::class,
* "output"=ResetPasswordRequestOutput::class,
* "normalization_context"={"jsonld_embed_context"=false}
* },
It just my thought i just want to do like the same, I haven't try this because of i haven't any idea about this means how it will be done.
For Example:
I have - mysite.com/view?user_id=12 , I don't want to show url's parameters (?user_id=12) on url, On the place of this, I want to show like
mysite.com/view?_signature=encryptedparameter
(like : mysite.com/view?_signature=853ef7a0ff5aea6f24152b1d1ed4d771)
853ef7a0ff5aea6f24152b1d1ed4d771 will denotes user_id=12.
If i have multiple parameters it would be like the same and i will have a single encrypted string and i will get all parameters with that string.
Yes but i am using in Laravel 5.1
assume if i have "mysite.com/view?user_id=12"
And i want "mysite.com/view?_signature=encryptedparameter"
Please fallow some steps
laravel>packages>myfolder>core
+=>folder
-=>file
+packages
+Folder
+core
+src
+Faundation
-Application.php
+Routing
-RoutingServiceProvider.php
-UriGenerator.php
+Support
+Middleware
-UrlParamRevealerMiddleware.php
+ServiceProvider
-CoreServiceProvider.php
-UriParamProtector.php
<<IN APPLICATION.PHP>>
<?php
namespace Folder\Core\Foundation;
use Illuminate\Events\EventServiceProvider;
use Folder\Core\Routing\RoutingServiceProvider;
use Illuminate\Foundation\Application as BaseApplication;
use Folder\Core\Support\ServiceProvider\CoreServiceProvider;
class Application extends BaseApplication
{
/**
* Register all of the base service providers.
*
* #return void
*/
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new CoreServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
}
<<//IN APPLICATION.PHP>>
<<-RoutingServiceProvider>>
<?php
namespace Folder\Core\Routing;
use Folder\Core\Routing\UrlGenerator;
use Illuminate\Routing\RoutingServiceProvider as BaseServiceProvider;
class RoutingServiceProvider extends BaseServiceProvider
{
/**
* Register the URL generator service.
*
* #return void
*/
protected function registerUrlGenerator()
{
$this->app['url'] = $this->app->share(function ($app) {
$routes = $app['router']->getRoutes();
// The URL generator needs the route collection that exists on the router.
// Keep in mind this is an object, so we're passing by references here
// and all the registered routes will be available to the generator.
$app->instance('routes', $routes);
$url = $this->getUrlGenerator($routes);
$url->setSessionResolver(function () {
return $this->app['session'];
});
// If the route collection is "rebound", for example, when the routes stay
// cached for the application, we will need to rebind the routes on the
// URL generator instance so it has the latest version of the routes.
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
}
/**
* Get the url generator instance.
*
* #param \Illuminate\Routing\RouteCollection $routes
* #return \Folder\Core\Routing\UrlGenerator
*/
protected function getUrlGenerator($routes)
{
$url = new UrlGenerator(
$routes,
$this->app->rebinding(
'request',
$this->requestRebinder()
)
);
return $url;
}
}
<</-RoutingServiceProvider>>
<<UriGenerator.php>>
<?php
namespace Folder\Core\Routing;
use ErrorException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\UrlGenerator as BaseUrlGenerator;
class UrlGenerator extends BaseUrlGenerator
{
/**
* Get the URL to a named route.
*
* #param string $name
* #param mixed $parameters
* #param bool $absolute
* #return string
*
* #throws \InvalidArgumentException
*/
public function route($name, $parameters = [], $absolute = true)
{
$encryptedParameters = $parameters;
if (Auth::guest() === false) {
$encryptedParameters = $this->encrypt($name, $parameters);
}
return parent::route($name, $encryptedParameters, $absolute);
}
/**
* Get the cryptic engine.
*
* #return \Folder\Core\Support\UrlParamEncrypter
*
* #throws \ErrorException
*/
protected function getCrypt()
{
$app = App::getInstance();
if (isset($app['urlencryptor'])) {
return $app['urlencryptor'];
}
throw new ErrorException('URL Encryptor was not found.');
}
/**
* Get the protector engine.
*
* #return #return \Folder\Core\Support\UrlParamProtector
*
* #throws \ErrorException
*/
protected function getProtector()
{
$app = App::getInstance();
if (isset($app['urlprotector'])) {
return $app['urlprotector'];
}
throw new ErrorException('URL Protector was not found.');
}
/**
* Encrypts the parameter passed as querystring in URL.
*
* #param array $parameters
* #return array
*/
protected function encrypt($routeName, $parameters = [])
{
if (! is_array($parameters)) {
return $parameters;
}
if (count($parameters) === 0) {
return [];
}
if (Auth::guest() === true) {
return $parameters;
}
$protected = $this->getProtector()->protect($routeName, $parameters);
return ['__signature' => $protected];
}
}
<<//UriGenerator.php>>
<<UrlParamRevealerMiddleware.php>>
<?php
namespace Folder\Core\Support\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Folder\Core\Support\UrlParamProtector;
class UrlParamRevealerMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
(! Auth::guest()) && App::make(UrlParamProtector::class)->reveal($request);
return $next($request);
}
}
<<//UrlParamRevealerMiddleware.php>>
<<CoreServiceProvider.php>>
<?php
namespace Folder\Core\Support\ServiceProvider;
use Illuminate\Support\ServiceProvider;
use Folder\Core\Support\UrlParamProtector;
class CoreServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->app->make('Illuminate\Contracts\Http\Kernel')
->pushMiddleware('Folder\Core\Support\Middleware\UrlParamRevealerMiddleware');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerUrlProtector();
}
/**
* Register UrlProtector class.
*/
protected function registerUrlProtector()
{
$this->app->singleton('urlprotector', function () {
return new UrlParamProtector();
});
}
}
<<//CoreServiceProvider.php>>
<<-UriParamProtector.php>>
<?php
namespace Folder\Core\Support;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class UrlParamProtector
{
/**
* Session key.
*
* #var string
*/
protected $sessionKey = '__url_protector__';
/**
* Request class.
*
* #var \Illuminate\Http\Request
*/
protected $request;
/**
* Values those needs to be merged in request object.
*
* #var array
*/
protected $valuesToBeMerged;
/**
* Create and returns VALID RFC 4211 COMPLIANT
* Universally Unique IDentifiers (UUID) version 4.
*
* #return string
*/
protected function getNewGuid()
{
if (function_exists('com_create_guid') === true) {
return trim(com_create_guid(), '{}');
}
return sprintf(
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(16384, 20479),
mt_rand(32768, 49151),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535)
);
}
/**
* Create the route key.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
protected function getRouteKey($routeName, array $parameters = [])
{
if (count($parameters) <= 0) {
$paramToString = '';
} else {
$paramToString = implode('-', array_map(
function ($k, $v) {
return $k . '-' . $v;
},
array_keys($parameters),
array_values($parameters)
));
}
$routeKey = 'route__' . $routeName . (empty($paramToString) ? '' : '-' . $paramToString);
return $routeKey;
}
/**
* Returns a GUID for a URL parameter.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
public function protect($routeName, array $parameters)
{
$routeKey = $this->getRouteKey($routeName, $parameters);
if (Session::has($this->sessionKey . '.' . $routeKey) === false) {
$guid = Str::lower($this->getNewGuid());
Session::set($this->sessionKey . '.' . $routeKey, [
'guid' => $guid,
'loggedin_user_id' => (Auth::guest() ? 0 : Auth::user()->id),
'params' => $parameters,
]);
} else {
$guid = Session::get($this->sessionKey . '.' . $routeKey . '.guid');
}
return $guid;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
protected function isValidGuid($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if (!isset($value['guid'])) {
list($innerKey, $val) = each($value);
} else {
$val = $value;
}
if ($val['guid'] === $guid) {
$this->valuesToBeMerged = $val['params'];
return true;
}
}
return false;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
public function isValidGuidForPost($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if ($value['guid'] === $guid && Auth::user()->id === $value['loggedin_user_id']) {
$this->valuesToBeMerged = $value['params'];
return true;
}
}
return false;
}
/**
* Merge the request with our revealed values.
*/
protected function mergeRequest()
{
$this->request->merge($this->valuesToBeMerged);
}
/**
* Check whether a "__signature" is correct or not.
*
* #param \Illuminate\Http\Request $request
* #return boolean
*/
public function reveal(Request &$request)
{
$this->request = $request;
$guid = ($this->request->query('__signature') ? : false);
if ($guid === false) {
return false;
}
if ($this->isValidGuid($guid) === false) {
App::abort(400);
}
$this->mergeRequest();
}
}
<<//-UriParamProtector.php>>
==============================================
after that in "bootstrap>App.php"
use this=>
$app = new Folder\Core\Foundation\Application(
realpath(__DIR__.'/../')
);
instad of =>
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
in any link use "data-href"
<a data-href="route('modify_lead_status',['user_id' => $users->id])" href="javascript:void(0)"><i class=\"fa fa-random\"></i></a>"
and after that any controller,Routing,middleware will be same.....
>>composer auto-dump
<<Please check spealing be sure use same>>
i hope this is help full....thanks
I have an error in my service restuser.handler, other services work, what's the problem please
services:
# rest_user.example:
# class: %rest_user.example.class%
# arguments: [#service_id, "plain_value", %parameter%]
restuser.form.register:
class: REST\UserBundle\Form\RegisterType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: rest_user_register}
restuser.form.profile:
class: REST\UserBundle\Form\ProfileType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: rest_user_profile }
restuser.handler:
class: REST\UserBundle\Handler\UserHandler
arguments: [#doctrine.orm.entity_manager, #form.factory, #security.encoder_factory]
my controller is as follows:
class UserController extends FOSRestController{
/**
* #QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing pages.")
* #QueryParam(name="limit", requirements="\d+", nullable=true, default="20", description="How many pages to return.")
*
* #View()
*
* #param Request $request the request object
* #param ParamFetcherInterface $paramFetcher param fetcher service
*
* #return array
*/
public function getUsersAction(Request $request, ParamFetcherInterface $paramFetcher)
{
$offset = $paramFetcher->get('offset');
$offset = null == $offset ? 0 : $offset;
$limit = $paramFetcher->get('limit');
return $this->container->get('user.handler')->all($limit, $offset);
}
/**
* #param User $user
*
* #View()
* #return array
*/
public function getUserAction($id)
{
$user=$this->getOr404($id);
return $user;
}
/**
*
* #View()
*
* #param Request $request
* #param int $id
*
* #return View
*
* #throws NotFoundHttpException when user not exist
*/
public function putUserAction(Request $request, $id)
{
try {
if (!($user = $this->container->get('user.handler')->get($id))) {
$statusCode = Codes::HTTP_CREATED;
$user = $this->container->get('user.handler')->post($request);
} else {
$statusCode = Codes::HTTP_NO_CONTENT;
$user = $this->container->get('user.handler')->put($user, $request);
}
$response = new Response('El usuario ha sido guardado con éxito', $statusCode);
return $response;
} catch (\Exception $exception) {
return $exception->getMessage();
}
}
/**
*
* #View()
*
* #param Request $request
* #param int $id
*
* #return FormTypeInterface|View
*
* #throws NotFoundHttpException when user not exist
*/
public function patchUserAction(Request $request, $id)
{
try {
if (($user = $this->getOr404($id))) {
$statusCode = Codes::HTTP_ACCEPTED;
$user = $this->container->get('user.handler')->patch($user, $request);
} else {
$statusCode = Codes::HTTP_NO_CONTENT;
}
$response = new Response('El usuario ha sido guardado con éxito', $statusCode);
return $response;
} catch (NotFoundHttpException $exception) {
return $exception->getMessage();
}
}
/**
*
* #View()
*
* #param Request $request
* #param int $id
*
* #return FormTypeInterface|View
*
* #throws NotFoundHttpException when user not exist
*/
public function deleteUserAction(Request $request, $id)
{
if (($user = $this->container->get('user.handler')->get($id))) {
$statusCode = Codes::HTTP_ACCEPTED;
$user = $this->container->get('user.handler')->delete($user);
} else {
$statusCode = Codes::HTTP_NO_CONTENT;
}
$response = new Response('El usuario se ha eliminado', $statusCode);
return $response;
}
/**
* Fetch the Page or throw a 404 exception.
*
* #param mixed $id
*
* #return PageInterface
*
* #throws NotFoundHttpException
*/
protected function getOr404($id)
{
if (!($page = $this->container->get('user.handler')->get($id))) {
throw new NotFoundHttpException(sprintf('The User \'%s\' was not found.',$id));
}
return $page;
}
}
my class user handler is a s follows:
public function __construct(EntityManager $em, FormFactoryInterface $formFactory, EncoderFactory $encoderFactory)
{
$this->em = $em;
$this->factory = $formFactory;
$this->encoderFactory = $encoderFactory;
}
public function get($id = null, $email = null)
{
if ($email) {
return $this->em->getRepository('UserBundle:User')->findOneBy(array('email' => $email));
}
return $this->em->getRepository('UserBundle:User')->find($id);
}
/**
* #param int $limit the limit of the result
* #param int $offset starting from the offset
*
* #return array
*/
public function all($limit = 20, $offset = 0, $orderby = null)
{
return $this->em->getRepository('UserBundle:User')->findBy(array(), $orderby, $limit, $offset);
}
/**
* Create a new User.
*
* #param $request
*
* #return User
*/
public function post(Request $request)
{
$user = new User();
return $this->processForm($user, $request, 'POST');
}
/**
* #param User $user
* #param $request
*
* #return User
*/
public function put(User $entity, $request)
{
return $this->processForm($entity, $request);
}
/**
* #param User $user
* #param $request
*
* #return User
*/
public function patch(User $entity, $request)
{
return $this->processForm($entity, $request, 'PATCH');
}
/**
* #param User $user
*
* #return User
*/
public function delete(User $entity)
{
$this->em->remove($entity);
$this->em->flush($entity);
}
/**
* Processes the form.
*
* #param User $user
* #param array $parameters
* #param String $method
*
* #return User
*
* #throws \Exception
*/
private function processForm(User $entity, Request $request, $method = "PUT")
{
$form = $this->factory->create(new AppUserType(), $entity, array('method' => $method));
$form->handleRequest($request);
if ($form->isValid()) {
$req = $request->request->get('user');
if (!$req) {
$req = $request->request->get('user');
}
if ($req['password']!= "") {
$entity->setPassword($req['password']);
}
$this->em->persist($entity);
$this->em->flush($entity);
return $entity;
}
return View::create($form, 400);
}
I tried to clear the cache and change name of service but still not work, please help me
hello guys following the doc to make a file uploader but i cant find out why its not workin when i hit submit its gives an error Unable to create the "uploads/cv" directory although these folders exist already in project/src/My/UserBundle/Resources/public/images
my document entity
namespace My\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* My\UserBundle\Entity\Document
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="My\UserBundle\Entity\DocumentRepository")
*/
class Document
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $path
*
* #ORM\Column(name= "name",type="string", length=255)
*/
private $name;
/**
* #var string $path
*
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $path;
/**
* #Assert\File(maxSize="6000000")
*/
private $file ;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set path
*
* #param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
function getFile()
{
return $this->file;
}
function setFile($file)
{
$this->file =$file;
}
function preUpload()
{
if(null !== $this->file )
{
$this->path = uniqid() . '.' . $this->file->guessExtension();
}
}
function upload()
{
if(null === $this->file)
{
return ;
}
$this->file->move( $this->getUploadDir() ,$this->getPath );
unset($this->file);
}
function removeUpload()
{
if($file = $this->getAbsolutePath() )
{
unlink($file);
}
}
function getWebPath()
{
return $this->getUploadDir() . $this->getPath() ;
}
function getUploadDir()
{
return 'uploads/cv' ;
}
function getAbsolutePath()
{
return $this->getRootDir() . $this->getPath() ;
}
function getRootDir()
{
return __DIR__ . '../../../../src/' .$this->getUploadDir() ;
}
function setName($n)
{
$this->name =$n ;
}
function getName()
{
return $this->name ;
}
}
and my controller action
function uploadAction()
{
$document = new Document();
$form = $this->createFormBuilder($document)
->add('name')
->add('file')
->getForm();
$request = $this->getRequest() ;
if( $request->getMethod() == 'POST' )
{
$form->bindRequest($request);
if($form->isValid() )
{
$em = $this->getDoctrine()->getEntityManager() ;
$document->upload();
$em->persist($document);
$em->flush();
return
$this->render('MyUserBundle:Document:upload.html.twig');
}
}
else
{
return
$this->render('MyUserBundle:Document:upload.html.twig' ,array('form'=>$form->createView() );
}
thanks in advance
I think you created your uploads/cv folder in the wrong path.
It should be project/web/uploads/cv, not project/src/My/UserBundle/Resources/public/images.
Then give Symfony the write permissions to that folder with chmod.