Skip to content

Commit

Permalink
Ajoute les documents (model + table + controllers + tests) à l'API (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
polosson committed Feb 15, 2021
1 parent 06ed7af commit 6e766bf
Show file tree
Hide file tree
Showing 29 changed files with 737 additions and 55 deletions.
3 changes: 3 additions & 0 deletions bin/release
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ rm -r src/var/cache && mkdir -m 777 src/var/cache/
rm -r src/var/logs && mkdir -m 777 src/var/logs/
rm -r src/var/tmp && mkdir -m 777 src/var/tmp/

echo -e "\nCréation du dossier des données privées..."
mkdir -m 777 data/

echo -e "\nDéfinition des permission des dossiers..."
chmod 777 src/App/Config
chmod 777 src/install
Expand Down
3 changes: 2 additions & 1 deletion server/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"robmorgan/phinx": "^0.11.4",
"delfimov/translate": "^2.6.0",
"dompdf/dompdf": "^0.8.5",
"twig/intl-extra": "^3.0.3"
"twig/intl-extra": "^3.0.3",
"cocur/slugify": "^4.0"
},
"require-dev": {
"there4/slim-test-helpers": "^2.1.3",
Expand Down
78 changes: 76 additions & 2 deletions server/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions server/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
29 changes: 16 additions & 13 deletions server/src/App/ApiRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,27 @@ class ApiRouter
'/materials[/]' => 'MaterialController:getAll',
'/materials/{id:[0-9]+}[/]' => 'MaterialController:getOne',
'/materials/{id:[0-9]+}/tags[/]' => 'MaterialController:getTags',
'/materials/{id:[0-9]+}/documents[/]' => 'MaterialController:getAllDocuments',
'/events[/]' => 'EventController:getAll',
'/events/{id:[0-9]+}[/]' => 'EventController:getOne',
'/events/{id:[0-9]+}/missing-materials[/]' => 'EventController:getMissingMaterials',
'/bills/{id:[0-9]+}[/]' => 'BillController:getOne',
],
'post' => [
'/token[/]' => 'TokenController:auth',
'/users/signin[/]' => 'TokenController:auth',
'/users/signup[/]' => 'UserController:create',
'/categories[/]' => 'CategoryController:create',
'/subcategories[/]' => 'SubCategoryController:create',
'/tags[/]' => 'TagController:create',
'/persons[/]' => 'PersonController:create',
'/companies[/]' => 'CompanyController:create',
'/parks[/]' => 'ParkController:create',
'/materials[/]' => 'MaterialController:create',
'/attributes[/]' => 'AttributeController:create',
'/events[/]' => 'EventController:create',
'/events/{eventId:[0-9]+}/bill[/]' => 'BillController:create',
'/token[/]' => 'TokenController:auth',
'/users/signin[/]' => 'TokenController:auth',
'/users/signup[/]' => 'UserController:create',
'/categories[/]' => 'CategoryController:create',
'/subcategories[/]' => 'SubCategoryController:create',
'/tags[/]' => 'TagController:create',
'/persons[/]' => 'PersonController:create',
'/companies[/]' => 'CompanyController:create',
'/parks[/]' => 'ParkController:create',
'/materials[/]' => 'MaterialController:create',
'/materials/{id:[0-9]+}/documents[/]' => 'MaterialController:handleUploadDocuments',
'/attributes[/]' => 'AttributeController:create',
'/events[/]' => 'EventController:create',
'/events/{eventId:[0-9]+}/bill[/]' => 'BillController:create',
],
'put' => [
'/users/{id:[0-9]+}[/]' => 'UserController:update',
Expand Down Expand Up @@ -81,6 +83,7 @@ class ApiRouter
'/materials/{id:[0-9]+}[/]' => 'MaterialController:delete',
'/events/{id:[0-9]+}[/]' => 'EventController:delete',
'/bills/{id:[0-9]+}[/]' => 'BillController:delete',
'/documents/{id:[0-9]+}[/]' => 'DocumentController:delete',
],
];

Expand Down
1 change: 1 addition & 0 deletions server/src/App/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private function _setAppRoutes()
// - Download files
$this->app->get('/bills/{id:[0-9]+}/pdf[/]', 'BillController:getOnePdf')->setName('getBillPdf');
$this->app->get('/events/{id:[0-9]+}/pdf[/]', 'EventController:getOnePdf')->setName('getEventPdf');
$this->app->get('/documents/{id:[0-9]+}/download[/]', 'DocumentController:getOne')->setName('getDocumentFile');

// - All remaining non-API routes should be handled by Front-End Router
$this->app->get('/[{path:.*}]', 'HomeController:entrypoint');
Expand Down
15 changes: 15 additions & 0 deletions server/src/App/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ class Config
'handlers' => [],
'max_files' => 10,
],
'authorizedFileTypes' => [
'application/pdf',
'application/zip',
'application/x-rar-compressed',
'image/jpeg',
'image/png',
'image/webp',
'text/plain',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.oasis.opendocument.text',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
],
];

public const SETTINGS_FILE = __DIR__ . '/settings.json';
Expand Down
3 changes: 3 additions & 0 deletions server/src/App/Config/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
if (!defined('ROOT_FOLDER')) {
define('ROOT_FOLDER', dirname(dirname(dirname(dirname(__FILE__)))));
}
if (!defined('DATA_FOLDER')) {
define('DATA_FOLDER', ROOT_FOLDER . DS . 'data');
}
if (!defined('SRC_FOLDER')) {
define('SRC_FOLDER', ROOT_FOLDER . DS . 'src');
}
Expand Down
23 changes: 23 additions & 0 deletions server/src/App/Config/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,26 @@ function splitPeriods(array $slots): array

return $periods;
}

/**
* Déplace un fichier uploaded dans le dossier des data en sécurisant son nom
*
* @param string $directory dossier dans lequel placer le fichier (sera créé si inexistant)
* @param UploadedFile $uploadedFile le fichier à placer
* @return string le nom du fichier résultant
*/
function moveUploadedFile($directory, Slim\Http\UploadedFile $uploadedFile)
{
$name = $uploadedFile->getClientFilename();

$slugify = new Cocur\Slugify\Slugify(['lowercase' => false]);
$nameSecure = $slugify->slugify($name);

if (!is_dir($directory)) {
mkdir($directory, 0777, true);
}

$uploadedFile->moveTo($directory . DS . $nameSecure);

return $nameSecure;
}
62 changes: 62 additions & 0 deletions server/src/App/Controllers/DocumentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);

namespace Robert2\API\Controllers;

use Robert2\API\Models\Document;
use Robert2\API\Errors;
use Robert2\API\Controllers\Traits\FileResponse;
use Slim\Http\Request;
use Slim\Http\Response;

class DocumentController
{
use FileResponse;

protected $container;
protected $model;

public function __construct($container)
{
$this->container = $container;
$this->model = new Document();
}

// ——————————————————————————————————————————————————————
// —
// — Getters
// —
// ——————————————————————————————————————————————————————

public function getOne(Request $request, Response $response): Response
{
$id = (int)$request->getAttribute('id');
$model = $this->model->find($id);
if (!$model) {
throw new Errors\NotFoundException;
}

$filePath = Document::getFilePath((int)$model->material_id, $model->name);
debug($filePath, ['log' => true, 'append' => false]);

$fileContent = file_get_contents($filePath);
if (!$fileContent) {
throw new Errors\NotFoundException("The file of the document cannot be found.");
}

return $this->_responseWithFile($response, $model->name, $fileContent);
}

// ——————————————————————————————————————————————————————
// —
// — Setters
// —
// ——————————————————————————————————————————————————————

public function delete(Request $request, Response $response): Response
{
$id = (int)$request->getAttribute('id');
$this->model->remove($id);
return $response->withJson(['destroyed' => true], SUCCESS_OK);
}
}
80 changes: 79 additions & 1 deletion server/src/App/Controllers/MaterialController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
namespace Robert2\API\Controllers;

use Robert2\API\Errors;
use Robert2\API\Models\Attribute;
use Robert2\API\Config\Config;
use Robert2\API\Models\Event;
use Robert2\API\Models\Document;
use Robert2\API\Controllers\Traits\Taggable;
use Slim\Http\Request;
use Slim\Http\Response;
Expand Down Expand Up @@ -168,4 +169,81 @@ protected function _saveMaterial(?int $id, array $postData): array
$model = $this->model->find($result->id);
return $model->toArray();
}

public function getAllDocuments(Request $request, Response $response): Response
{
$id = (int)$request->getAttribute('id');
$model = $this->model->find($id);
if (!$model) {
throw new Errors\NotFoundException;
}

return $response->withJson($model->documents, SUCCESS_OK);
}

public function handleUploadDocuments(Request $request, Response $response): Response
{
$id = (int)$request->getAttribute('id');
$model = $this->model->find($id);
if (!$model) {
throw new Errors\NotFoundException;
}

$uploadedFiles = $request->getUploadedFiles();
$destDirectory = Document::getFilePath($id);

$errors = [];
$files = [];
foreach ($uploadedFiles as $file) {
if ($file->getError() !== UPLOAD_ERR_OK) {
$errors[$file->getClientFilename()] = 'File upload failed.';
continue;
}

$fileType = $file->getClientMediaType();
if (!in_array($fileType, Config::getSettings('authorizedFileTypes'))) {
$errors[$file->getClientFilename()] = 'This file type is not allowed.';
continue;
}

$filename = moveUploadedFile($destDirectory, $file);
if (!$filename) {
$errors[$file->getClientFilename()] = 'Saving file failed.';
continue;
}

$files[] = [
'material_id' => $id,
'name' => $filename,
'type' => $fileType,
'size' => $file->getSize(),
];
}

foreach ($files as $document) {
try {
Document::updateOrCreate(
['material_id' => $id, 'name' => $document['name']],
$document
);
} catch (\Exception $e) {
$filePath = Document::getFilePath($id, $document['name']);
unlink($filePath);
$errors[$document['name']] = sprintf(
'Document could not be saved in database: %s',
$e->getMessage()
);
}
}

if (count($errors) > 0) {
throw new \Exception(implode("\n", $errors));
}

$result = [
'saved_files' => $files,
'errors' => $errors,
];
return $response->withJson($result, SUCCESS_OK);
}
}
Loading

0 comments on commit 6e766bf

Please sign in to comment.