Skip to content
This repository was archived by the owner on Jun 19, 2022. It is now read-only.

Commit c842636

Browse files
committed
init
1 parent ed5402a commit c842636

19 files changed

+913
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/vendor/

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "fd6130/hsl-bundle",
3+
"description": "Install this bundle if you need feature provided from this bundle.",
4+
"type": "library",
5+
"license": "MIT",
6+
"autoload": {
7+
"psr-4": {
8+
"Fd\\HslBundle\\": "src/"
9+
}
10+
},
11+
"require": {
12+
"php": "^7.2.5",
13+
"samj/fractal-bundle": "^4.0",
14+
"babdev/pagerfanta-bundle": "^2.2",
15+
"mark-gerarts/automapper-plus-bundle": "^1.2",
16+
"intervention/image": "^2.5",
17+
"lexik/jwt-authentication-bundle": "^2.7",
18+
"etnynl/jwt-refresh-token-bundle": "^0.9.3",
19+
"nesbot/carbon": "^2.32",
20+
"symfony-bundles/json-request-bundle": "^3.0",
21+
"symfony/apache-pack": "^1.0",
22+
"twig/cssinliner-extra": "^3.0",
23+
"twig/extra-bundle": "^3.0",
24+
"twig/inky-extra": "^3.0",
25+
"vich/uploader-bundle": "^1.13"
26+
},
27+
"require-dev": {
28+
"symfony/maker-bundle": "^1.0",
29+
"easycorp/easy-deploy-bundle": "^1.0"
30+
}
31+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace Fd\HslBundle\Command;
4+
5+
use Symfony\Component\Console\Command\Command;
6+
use Symfony\Component\Console\Input\InputInterface;
7+
use Symfony\Component\Console\Output\OutputInterface;
8+
use Symfony\Component\Process\Exception\ProcessFailedException;
9+
use Symfony\Component\Process\Process;
10+
11+
/**
12+
* Generate SSH keys.
13+
*/
14+
class LexikJWTKeyGeneratorCommand extends Command
15+
{
16+
protected static $defaultName = 'lexik:generate-keys';
17+
18+
protected function configure()
19+
{
20+
$this->setDescription('Generate SSH keys for LexikJWTAuthenticatorBundle.');
21+
}
22+
23+
protected function execute(InputInterface $input, OutputInterface $output)
24+
{
25+
$output->writeln([
26+
'<info>',
27+
'=========================================================',
28+
'| SSH keys generator for LexikJWTAuthenticatorBundle |',
29+
'| |',
30+
"| Generated keys will be save to 'config/jwt' folder. |",
31+
'=========================================================',
32+
'</info>',
33+
'',
34+
]);
35+
36+
$output->writeln('Creating folder \'config/jwt\'...');
37+
$output->writeln($this->makeDirectory());
38+
$output->writeln([
39+
'Done.',
40+
'',
41+
]);
42+
43+
$output->writeln('Generate Secret key...');
44+
$output->writeln($this->generatePrivateKey());
45+
$output->writeln([
46+
'Done.',
47+
'',
48+
]);
49+
50+
$output->writeln('Generate Public key...');
51+
$output->writeln($this->generatePublicKey());
52+
$output->writeln('Done.');
53+
$output->writeln([
54+
'',
55+
'<info>Remember to double check your \'config/packages/lexik_jwt_authentication.yaml\' and \'.env\' for configuration.</info>',
56+
''
57+
]);
58+
59+
return Command::SUCCESS;
60+
}
61+
62+
public function makeDirectory()
63+
{
64+
$process = new Process(['mkdir', '-p', 'config/jwt']);
65+
$process->run();
66+
67+
// executes after the command finishes
68+
if (!$process->isSuccessful()) {
69+
throw new ProcessFailedException($process);
70+
}
71+
72+
return $process->getOutput();
73+
}
74+
75+
public function generatePrivateKey()
76+
{
77+
$process = new Process(['openssl', 'genpkey', '-out', 'config/jwt/private.pem', '-aes256', '-algorithm', 'rsa', '-pkeyopt', 'rsa_keygen_bits:4096']);
78+
$process->run();
79+
80+
// executes after the command finishes
81+
if (!$process->isSuccessful()) {
82+
throw new ProcessFailedException($process);
83+
}
84+
85+
return $process->getOutput();
86+
}
87+
88+
public function generatePublicKey()
89+
{
90+
$process = new Process(['openssl', 'pkey', '-in', 'config/jwt/private.pem', '-out', 'config/jwt/public.pem', '-pubout']);
91+
$process->run();
92+
93+
// executes after the command finishes
94+
if (!$process->isSuccessful()) {
95+
throw new ProcessFailedException($process);
96+
}
97+
98+
return $process->getOutput();
99+
}
100+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Fd\HslBundle\DependencyInjection;
4+
5+
use Fd\HslBundle\HslInterface;
6+
use Symfony\Component\Config\FileLocator;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\Extension\Extension;
9+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
10+
11+
class FdHslExtension extends Extension
12+
{
13+
public function load(array $configs, ContainerBuilder $container)
14+
{
15+
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
16+
$loader->load('services.yaml');
17+
}
18+
}

src/DtoRequestInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Fd\HslBundle;
4+
5+
/**
6+
* Every DTO that need to initialize during POST/PUT request should implement this interface.
7+
*/
8+
interface DtoRequestInterface {}

src/DtoRequestResolver.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Fd\HslBundle;
4+
5+
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
6+
use Symfony\Component\HttpFoundation\Request;
7+
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
8+
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
9+
use Symfony\Component\Validator\Validator\ValidatorInterface;
10+
11+
/**
12+
* Use to resolve a request to DTO
13+
*/
14+
class DtoRequestResolver implements ArgumentValueResolverInterface
15+
{
16+
private $validator;
17+
18+
public function __construct(ValidatorInterface $validator)
19+
{
20+
$this->validator = $validator;
21+
}
22+
23+
/**
24+
* Return true if Dto is implements RequestDtoInterface
25+
*/
26+
public function supports(Request $request, ArgumentMetadata $argument)
27+
{
28+
try
29+
{
30+
$reflection = new \ReflectionClass($argument->getType());
31+
return $reflection->implementsInterface(DtoRequestInterface::class);
32+
}
33+
catch(\ReflectionException $e)
34+
{
35+
/**
36+
* Because some controller have to use value-type argument value instead of class-type argument,
37+
* without try-catch it will throw uncaught exception.
38+
*
39+
* So here i will catch it and just return false.
40+
*/
41+
return false;
42+
}
43+
44+
}
45+
46+
public function resolve(Request $request, ArgumentMetadata $argument)
47+
{
48+
$class = $argument->getType();
49+
$dto = new $class($request);
50+
51+
//do symfony validation here
52+
$errors = $this->validator->validate($dto);
53+
if(count($errors) > 0)
54+
{
55+
throw new BadRequestException((string) $errors);
56+
}
57+
58+
yield $dto;
59+
}
60+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
namespace Fd\HslBundle\Event\Listener;
4+
5+
use Intervention\Image\ImageManager;
6+
use Symfony\Component\HttpFoundation\File\File;
7+
use Vich\UploaderBundle\Event\Event;
8+
9+
/**
10+
* Custom listener that modify an image after post.
11+
*/
12+
class VichImageUploadListener
13+
{
14+
const MAX_WIDTH = 800;
15+
const MAX_BYTE = 1000000; // equal to 1MB
16+
17+
/**
18+
* @var ImageManager $imageManager
19+
*/
20+
private $imageManager;
21+
22+
public function __construct()
23+
{
24+
$this->imageManager = new ImageManager(array('driver' => 'gd'));
25+
}
26+
27+
public function onVichUploaderPostUpload(Event $event){
28+
$object = $event->getObject();
29+
$mapping = $event->getMapping();
30+
31+
/**
32+
* @var File $image
33+
*/
34+
$image = $object->getImageFile();
35+
36+
if($this->isNotEligibleForResave($image))
37+
{
38+
return;
39+
}
40+
41+
list($oriWidth, $oriHeight) = getimagesize($image->getPathname());
42+
$path = $image->getPath();
43+
$filename = pathinfo($image->getFileName(), PATHINFO_FILENAME);
44+
$saveFilePath = $image->getPathname();
45+
46+
$imageManager = $this->imageManager->make($image->getPathname());
47+
48+
if($this->isExceedMaxWidth($oriWidth))
49+
{
50+
$height = round( (self::MAX_WIDTH * $oriHeight) / $oriWidth);
51+
$imageManager = $imageManager->resize(self::MAX_WIDTH, $height);
52+
}
53+
54+
55+
if($this->notJPGExtension($image))
56+
{
57+
$saveFilePath = $path.'/'.$filename. '.jpg';
58+
$newFilename = $filename. '.jpg';
59+
60+
/**
61+
* 1. Delete original uploaded file because it won't replace the original image with
62+
* different extension filename.
63+
*
64+
* 2. MUST! Set entity ImageName to new filename.
65+
*/
66+
unlink($image->getPathname());
67+
$object->setImageName($newFilename);
68+
}
69+
70+
$imageManager->save($saveFilePath, 90);
71+
}
72+
73+
private function notJPGExtension($image)
74+
{
75+
return $image->getExtension() !== 'jpg';
76+
}
77+
78+
private function isExceedMaxWidth($imageWidth)
79+
{
80+
return $imageWidth > self::MAX_WIDTH;
81+
}
82+
83+
private function isNotEligibleForResave(File $image)
84+
{
85+
return filesize($image->getPathname()) < self::MAX_BYTE && !$this->notJPGExtension($image);
86+
}
87+
}

src/FdHslBundle.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Fd\HslBundle;
4+
5+
use Fd\HslBundle\DependencyInjection\Compiler\HslInterfacePass;
6+
use Symfony\Component\HttpKernel\Bundle\Bundle;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
9+
class FdHslBundle extends Bundle
10+
{
11+
// public function build(ContainerBuilder $container)
12+
// {
13+
// $container->addCompilerPass(new HslInterfacePass());
14+
// }
15+
}

src/FractalTrait.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Fd\HslBundle;
4+
5+
use League\Fractal\Manager;
6+
use Symfony\Component\HttpFoundation\Request;
7+
8+
trait FractalTrait
9+
{
10+
11+
/**
12+
* @var Manager
13+
*/
14+
protected $fractal;
15+
16+
/**
17+
* @return Manager
18+
*/
19+
protected function fractal(Request $request)
20+
{
21+
if ($request->query->has('include')) {
22+
$this->fractal->parseIncludes($request->query->get('include'));
23+
}
24+
25+
return $this->fractal;
26+
}
27+
}

0 commit comments

Comments
 (0)