From 58dc5beac76e384f483597e99537c4c51cd9ab08 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Thu, 18 Aug 2022 11:42:58 +0200 Subject: [PATCH] wip #5400 @3 --- app/Console/Commands/FluidbookPullSources.php | 48 +------- .../FluidbookPublication/PreviewOperation.php | 26 ++++- .../Admin/Operations/Tools/BaseTool.php | 36 ++++++ .../Operations/Tools/DockerWebContainer.php | 1 + .../Admin/Operations/Tools/Excel2JSON.php | 1 + .../Tools/FluidbookAssetsDownloader.php | 8 +- .../Tools/FluidbookBranchCreate.php | 45 +++++++ .../Tools/FluidbookBranchRemove.php | 44 +++++++ .../Admin/Operations/Tools/GitReposCreate.php | 19 ++- .../Controllers/Admin/ToolsController.php | 4 + app/Models/FluidbookPublication.php | 12 ++ app/Models/Traits/FluidbookPlayerBranches.php | 110 ++++++++++++++++++ resources/views/tools/sidebar.blade.php | 7 ++ 13 files changed, 300 insertions(+), 61 deletions(-) create mode 100644 app/Http/Controllers/Admin/Operations/Tools/BaseTool.php create mode 100644 app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchCreate.php create mode 100644 app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchRemove.php create mode 100644 app/Models/Traits/FluidbookPlayerBranches.php diff --git a/app/Console/Commands/FluidbookPullSources.php b/app/Console/Commands/FluidbookPullSources.php index a87c244e1..f556643e0 100644 --- a/app/Console/Commands/FluidbookPullSources.php +++ b/app/Console/Commands/FluidbookPullSources.php @@ -2,6 +2,7 @@ namespace App\Console\Commands; +use App\Models\Traits\FluidbookPlayerBranches; use Cubist\Backpack\Console\Commands\CubistCommand; use Cubist\Util\CommandLine\Git; use Cubist\Util\Files\Files; @@ -12,55 +13,12 @@ class FluidbookPullSources extends CubistCommand protected $signature = 'fluidbook:player:updatesources'; protected $description = 'Update fluidbook player sources from git repos'; - protected function executeGitCommands($dir, $commands) - { - if (!is_array($commands)) { - $commands = [$commands]; - } - $res = []; - foreach ($commands as $command) { - $res[] = $this->executeGitCommand($dir, $command); - } - return $res; - } - - protected function executeGitCommand($dir, $command) - { - $git = new Git($dir); - $output = $git->executeCmd($command); - - $this->line('' . $git->getCommand() . ''); - $this->line($output); - return $output; - } + use FluidbookPlayerBranches; public function handle() { PHP::neverStop(true); - - $playerDir = Files::mkdir(resource_path('fluidbookpublication/player')) . '/'; - $branchesDir = Files::mkdir($playerDir . 'branches/'); - $localDir = Files::mkdir($playerDir . 'local/'); - $baseBranchDir = Files::mkdir($branchesDir . 'fluidbook-html5'); - - $this->executeGitCommands($baseBranchDir, ['stash save --keep-index', 'stash drop', 'pull --all', 'fetch --all --prune']); - - $git = new Git($baseBranchDir); - $branches = $git->listBranches(); - foreach ($branches as $b) { - $gitsource = $branchesDir . $b; - $local = $localDir . $b; - if (!file_exists($branchesDir . $b)) { - $this->executeGitCommands($branchesDir, 'clone -b ' . $b . ' --single-branch git@git.cubedesigners.com:fluidbook-html5.git ' . $b); - } - if (!file_exists($local)) { - mkdir($local, 0777, true); - `cp -r $gitsource/* $local`; - `rm -rf $local/.git`; - } - $this->executeGitCommands($branchesDir . $b, ['reset --hard origin/' . $b, 'pull']); - } - file_put_contents($playerDir . '/activebranches', json_encode($branches)); + $this->updateAllBranches(); } } diff --git a/app/Http/Controllers/Admin/Operations/FluidbookPublication/PreviewOperation.php b/app/Http/Controllers/Admin/Operations/FluidbookPublication/PreviewOperation.php index a6a3c30a8..73b2d1608 100644 --- a/app/Http/Controllers/Admin/Operations/FluidbookPublication/PreviewOperation.php +++ b/app/Http/Controllers/Admin/Operations/FluidbookPublication/PreviewOperation.php @@ -10,7 +10,23 @@ trait PreviewOperation { protected function setupPreviewRoutes($segment, $routeName, $controller) { - Route::match(['get'], $segment . '/{id}_{hash}/preview', $controller . '@preview')->withoutMiddleware([CheckIfAdmin::class]); + // Redirect to the url with a timestamp to prevent cache + Route::match(['get'], $segment . '/preview/{id}_{hash}', function ($id, $hash) use ($segment) { + return redirect(backpack_url($segment . '/preview/' . $id . '_' . $hash . '_' . time())); + })->whereNumber('id') + ->where('hash', '[0-9a-f]{32}') + ->withoutMiddleware([CheckIfAdmin::class]); + + Route::match(['get'], $segment . '/preview/{id}_{hash}_{time}/{path?}', function ($id, $hash, $time, $path = 'index.html') use ($segment, $controller) { + // If timestamp is too old, redirect to a more recent one + if ($path === 'index.html' && (time() - $time) > 30) { + return redirect(backpack_url($segment . '/preview/' . $id . '_' . $hash . '_' . time() . '/')); + } + return $this->preview($id, $hash, $path); + })->whereNumber('id') + ->where('hash', '[0-9a-f]{32}') + ->where('path', '.*') + ->withoutMiddleware([CheckIfAdmin::class]); } protected function setupPreviewDefaults() @@ -18,11 +34,17 @@ trait PreviewOperation $this->crud->addButtonFromView('line', 'preview', 'fluidbook_publication.preview', 'end'); } - public function preview($id, $hash) + public function preview($id, $hash, $path = 'index.html') { $fluidbook = FluidbookPublication::where('id', $id)->where('hash', $hash)->first(); if (null === $fluidbook) { abort(404); } + $dest = $fluidbook->getFinalPath(); + + if ($path === 'index.html') { + $fluidbook->compile($dest); + } + return response('Preview of fluidbook ' . $id . ': ' . $path); } } diff --git a/app/Http/Controllers/Admin/Operations/Tools/BaseTool.php b/app/Http/Controllers/Admin/Operations/Tools/BaseTool.php new file mode 100644 index 000000000..265703c45 --- /dev/null +++ b/app/Http/Controllers/Admin/Operations/Tools/BaseTool.php @@ -0,0 +1,36 @@ +_flash($message, 'warning'); + return $this->_redirectReferer(); + } + + protected function _success($message) + { + $this->_flash($message, 'success'); + return $this->_redirectReferer(); + } + + protected function _error($message) + { + $this->_flash($message, 'error'); + return $this->_redirectReferer(); + } + + protected function _flash($message, $type = 'info') + { + Alert::add($type, $message)->flash(); + } + + protected function _redirectReferer() + { + return redirect(request()->input('_referrer')); + } +} diff --git a/app/Http/Controllers/Admin/Operations/Tools/DockerWebContainer.php b/app/Http/Controllers/Admin/Operations/Tools/DockerWebContainer.php index 329c88daf..8766af1bb 100644 --- a/app/Http/Controllers/Admin/Operations/Tools/DockerWebContainer.php +++ b/app/Http/Controllers/Admin/Operations/Tools/DockerWebContainer.php @@ -13,6 +13,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\F; trait DockerWebContainer { + use BaseTool; public function dockerwebcontainer() { $form = new Form(backpack_url('tools/dodockerwebcontainer')); diff --git a/app/Http/Controllers/Admin/Operations/Tools/Excel2JSON.php b/app/Http/Controllers/Admin/Operations/Tools/Excel2JSON.php index 5f704354b..ab5732499 100644 --- a/app/Http/Controllers/Admin/Operations/Tools/Excel2JSON.php +++ b/app/Http/Controllers/Admin/Operations/Tools/Excel2JSON.php @@ -10,6 +10,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; trait Excel2JSON { + use BaseTool; public function excel2json() { $form = new Form(backpack_url('tools/doexcel2json')); diff --git a/app/Http/Controllers/Admin/Operations/Tools/FluidbookAssetsDownloader.php b/app/Http/Controllers/Admin/Operations/Tools/FluidbookAssetsDownloader.php index 17197431b..8074a9e23 100644 --- a/app/Http/Controllers/Admin/Operations/Tools/FluidbookAssetsDownloader.php +++ b/app/Http/Controllers/Admin/Operations/Tools/FluidbookAssetsDownloader.php @@ -12,6 +12,8 @@ use Prologue\Alerts\Facades\Alert; trait FluidbookAssetsDownloader { + use BaseTool; + public function fluidbookassetsdownloader() { $form = new Form(backpack_url('tools/fluidbookassetsdownloaderDownload')); @@ -23,7 +25,7 @@ trait FluidbookAssetsDownloader 'type' => FluidbookID::class]); $form->addField('folder', SelectFromArray::class, __('Dossier'), ['allows_null' => false, 'options' => ['commerce' => __('Panier / eCommerce'), 'working' => __('Assets et liens')]]); $form->addField('url', Textarea::class, __('Liste des urls à télécharger'), ['hint' => __('Une URL par ligne')]); - $form->addField('type', SelectFromArray::class, __('Méthode'), ['allows_null' => false, 'options' => ['unzip' => __('Télécharger et dézipper'),'unzip_recursive' => __('Télécharger et dézipper'), 'download' => __('Télécharger les fichier')], 'hint' => __('Dézipper ne conservera pas l\'arborescence des fichiers dans le zip')]); + $form->addField('type', SelectFromArray::class, __('Méthode'), ['allows_null' => false, 'options' => ['unzip' => __('Télécharger et dézipper'), 'unzip_recursive' => __('Télécharger et dézipper'), 'download' => __('Télécharger les fichier')], 'hint' => __('Dézipper ne conservera pas l\'arborescence des fichiers dans le zip')]); $form->addField('debug', Checkbox::class, __('Mode débogage')); return view('tools.form', ['form' => $form]); @@ -38,7 +40,7 @@ trait FluidbookAssetsDownloader PHP::neverStop(false); } \App\Jobs\Tools\FluidbookAssetsDownloader::$func($request->input('url'), $request->input('type'), $request->input('fluidbook'), $request->input('folder'), backpack_user()); - Alert::add('success', __('L\'opération a été placée en file d\'attente. Vous recevrez un email lorsqu\'elle sera terminée.'))->flash(); - return redirect($request->input('_referrer')); + + return $this->_success(__('L\'opération a été placée en file d\'attente. Vous recevrez un email lorsqu\'elle sera terminée.')); } } diff --git a/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchCreate.php b/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchCreate.php new file mode 100644 index 000000000..3df7fe19d --- /dev/null +++ b/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchCreate.php @@ -0,0 +1,45 @@ +setTitle(__('Créer une branch fluidbook')); + $form->setSubmitLabel(__('Créer')); + $form->setSubmitIcon('la-git'); + $form->addField('branch', Text::class, __('Nom de la branche')); + + return view('tools.form', ['form' => $form]); + } + + public function dofluidbookbranchcreate() + { + $branch = request()->get('branch'); + if (null === $branch) { + return $this->_error(__('Le nom de la branche est invalide')); + } + $branch = \Cubist\Util\Text::str2url(trim($branch)); + $branches = $this->getActiveBranches(); + if (in_array($branch, $branches)) { + return $this->_error(__('La branche :branch existe déjà', ['branch', $branch])); + } + + if ($this->fluidbookCreateBranch($branch)) { + return $this->_success(__('La branche :branch a été crée', ['branch' => $branch])); + } else { + return $this->_error(__('Une erreur s\'est produite lors de la création de la branche :branch', ['branch' => $branch])); + } + } +} diff --git a/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchRemove.php b/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchRemove.php new file mode 100644 index 000000000..8026ef265 --- /dev/null +++ b/app/Http/Controllers/Admin/Operations/Tools/FluidbookBranchRemove.php @@ -0,0 +1,44 @@ +setTitle(__('Supprimer une branch fluidbook')); + $form->setSubmitLabel(__('Supprimer')); + $form->setSubmitIcon('la-git'); + $branches = array_diff($this->getActiveBranches(), self::$_fluidbookProtectedBranches); + $form->addField('branch', SelectFromArray::class, __('Nom de la branche'), ['options' => array_combine($branches, $branches)]); + + return view('tools.form', ['form' => $form]); + } + + public function dofluidbookbranchremove() + { + $branch = request()->get('branch'); + if (null === $branch) { + return $this->_error(__('Veuillez sélectionner une branche à supprimer')); + } + $branches = $this->getActiveBranches(); + if (!in_array($branch, $branches) || in_array($branch, self::$_fluidbookProtectedBranches)) { + return $this->_error(__('Impossible de supprimer la branche :branch', ['branch' => $branch])); + } + if ($this->fluidbookRemoveBranch($branch)) { + return $this->_success(__('La branche :branch a été supprimée', ['branch' => $branch])); + } else { + return $this->_error(__('Une erreur s\'est produite lors de la suppression de la branche :branch', ['branch' => $branch])); + } + } +} diff --git a/app/Http/Controllers/Admin/Operations/Tools/GitReposCreate.php b/app/Http/Controllers/Admin/Operations/Tools/GitReposCreate.php index 44933aa37..ec9891b13 100644 --- a/app/Http/Controllers/Admin/Operations/Tools/GitReposCreate.php +++ b/app/Http/Controllers/Admin/Operations/Tools/GitReposCreate.php @@ -2,24 +2,21 @@ namespace App\Http\Controllers\Admin\Operations\Tools; -use Cubist\Backpack\Magic\Fields\Checkbox; -use Cubist\Backpack\Magic\Fields\Integer; -use Cubist\Backpack\Magic\Fields\SelectFromArray; -use Cubist\Backpack\Magic\Fields\StandardFile; -use Cubist\Backpack\Magic\Fields\Text; use Cubist\Backpack\Magic\Form; -use Cubist\Util\Str; -use Prologue\Alerts\Facades\Alert; +use Cubist\Util\Text; + trait GitReposCreate { + use BaseTool; + public function gitreposcreate() { $form = new Form(backpack_url('tools/dogitreposcreate')); $form->setTitle(__('Créer un répertoire GIT')); $form->setSubmitLabel(__('Create')); $form->setSubmitIcon('la-git'); - $form->addField('repos', Text::class, __('Nom du répertoire'), ['prefix' => 'git@git.cubedesigners.com:', 'suffix' => '.git']); + $form->addField('repos', \Cubist\Backpack\Magic\Fields\Text::class, __('Nom du répertoire'), ['prefix' => 'git@git.cubedesigners.com:', 'suffix' => '.git']); return view('tools.form', ['form' => $form]); } @@ -33,7 +30,7 @@ trait GitReposCreate `cd $storage;git clone git@git.cubedesigners.com:gitolite-admin.git`; } `cd $gitolite;git stash;git pull`; - $repos = Str::slug($request->get('repos')); + $repos = Text::str2url($request->get('repos')); $projectsConf = $gitolite . '/conf/projects.conf'; $projects = trim(file_get_contents($projectsConf)); $projects .= "\n@allrepos = $repos\n"; @@ -41,7 +38,7 @@ trait GitReposCreate $projects; `cd $gitolite;git commit -a -m "Added $repos from Toolbox"`; `cd $gitolite;git push -u origin master`; - Alert::add('success', __('Le répertoire :repos a été crée', ['repos' => $repos]))->flash(); - return redirect($request->input('_referrer')); + + return $this->_success(__('Le répertoire :repos a été crée', ['repos' => $repos])); } } diff --git a/app/Http/Controllers/Admin/ToolsController.php b/app/Http/Controllers/Admin/ToolsController.php index 5b991dcfd..5660e907b 100644 --- a/app/Http/Controllers/Admin/ToolsController.php +++ b/app/Http/Controllers/Admin/ToolsController.php @@ -7,6 +7,8 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Admin\Operations\Tools\DockerWebContainer; use App\Http\Controllers\Admin\Operations\Tools\Excel2JSON; use App\Http\Controllers\Admin\Operations\Tools\FluidbookAssetsDownloader; +use App\Http\Controllers\Admin\Operations\Tools\FluidbookBranchCreate; +use App\Http\Controllers\Admin\Operations\Tools\FluidbookBranchRemove; use App\Http\Controllers\Admin\Operations\Tools\GitReposCreate; use App\Http\Controllers\Admin\Operations\Tools\JSON2Excel; use App\Http\Controllers\Admin\Operations\Tools\PDF2SVGOperation; @@ -22,6 +24,8 @@ class ToolsController extends Controller use DockerWebContainer; use JSON2Excel; use Excel2JSON; + use FluidbookBranchCreate; + use FluidbookBranchRemove; protected function index($tool, $args = '') { diff --git a/app/Models/FluidbookPublication.php b/app/Models/FluidbookPublication.php index 3469e3bb0..39086280d 100644 --- a/app/Models/FluidbookPublication.php +++ b/app/Models/FluidbookPublication.php @@ -22,6 +22,8 @@ use Cubist\Backpack\Magic\Fields\FormSuperSection; use Cubist\Backpack\Magic\Fields\Hidden; use Cubist\Backpack\Magic\Fields\Integer; use Cubist\Backpack\Magic\Fields\SelectFromArray; +use Cubist\Scorm\Manifest; +use Cubist\Util\Files\VirtualDirectory; class FluidbookPublication extends ToolboxModel { @@ -210,4 +212,14 @@ class FluidbookPublication extends ToolboxModel } return $res; } + + public function getFinalPath() + { + return protected_path('fluidbookpublication/final/' . $this->id); + } + + public function compile($dest) + { + + } } diff --git a/app/Models/Traits/FluidbookPlayerBranches.php b/app/Models/Traits/FluidbookPlayerBranches.php new file mode 100644 index 000000000..15a96a7d1 --- /dev/null +++ b/app/Models/Traits/FluidbookPlayerBranches.php @@ -0,0 +1,110 @@ +executeGitCommand($dir, $command); + } + return $res; + } + + protected function executeGitCommand($dir, $command) + { + $git = new Git($dir); + $output = $git->executeCmd($command); + + if (method_exists($this, 'line')) { + $this->line('' . $git->getCommand() . ''); + $this->line($output); + } + return $output; + } + + protected function getFluidbookPlayerBaseDirectory() + { + return Files::mkdir(resource_path('fluidbookpublication/player')) . '/'; + } + + protected function getActiveBranches() + { + $cacheFile = $this->getFluidbookPlayerBaseDirectory() . '/activebranches'; + return json_decode(file_get_contents($cacheFile)); + } + + protected function fluidbookCreateBranch($branch) + { + $playerDir = $this->getFluidbookPlayerBaseDirectory(); + + $this->updateAllBranches(); + + $branchesDir = $playerDir . 'branches/'; + $dir = $branchesDir . 'fluidbook-html5'; + $this->executeGitCommands($dir, ['checkout -b ' . $branch, 'push --set-upstream origin ' . $branch]); + + $this->updateAllBranches(); + $this->executeGitCommand($dir, 'checkout master'); + + $this->updateAllBranches(); + return in_array($branch, $this->getActiveBranches()); + } + + protected function fluidbookRemoveBranch($branch) + { + $playerDir = $this->getFluidbookPlayerBaseDirectory(); + $branchesDir = $playerDir . 'branches/'; + $localDir = $playerDir . 'local/'; + + $this->updateAllBranches(); + $this->executeGitCommand($branchesDir . 'fluidbook-html5', 'push --delete origin ' . $branch); + + `rm -rf $localDir$branch`; + `rm -rf $branchesDir$branch`; + + // TODO modifier la branche des fluidbooks qui utilisaient cette branche (self::resetPlayerVersion($branch);) + + $this->updateAllBranches(); + return !in_array($branch, $this->getActiveBranches()); + } + + protected function updateAllBranches() + { + PHP::neverStop(); + + $playerDir = $this->getFluidbookPlayerBaseDirectory(); + $branchesDir = Files::mkdir($playerDir . 'branches/'); + $localDir = Files::mkdir($playerDir . 'local/'); + $baseBranchDir = Files::mkdir($branchesDir . 'fluidbook-html5'); + + $this->executeGitCommands($baseBranchDir, ['stash save --keep-index', 'stash drop', 'pull --all', 'fetch --all --prune']); + + $git = new Git($baseBranchDir); + $branches = $git->listBranches(); + foreach ($branches as $b) { + $gitsource = $branchesDir . $b; + $local = $localDir . $b; + if (!file_exists($branchesDir . $b)) { + $this->executeGitCommands($branchesDir, 'clone -b ' . $b . ' --single-branch git@git.cubedesigners.com:fluidbook-html5.git ' . $b); + } + if (!file_exists($local)) { + mkdir($local, 0777, true); + `cp -r $gitsource/* $local`; + `rm -rf $local/.git`; + } + $this->executeGitCommands($branchesDir . $b, ['reset --hard origin/' . $b, 'pull']); + } + file_put_contents($playerDir . '/activebranches', json_encode($branches)); + } + +} diff --git a/resources/views/tools/sidebar.blade.php b/resources/views/tools/sidebar.blade.php index e4e8c4e71..b7e1eeb17 100644 --- a/resources/views/tools/sidebar.blade.php +++ b/resources/views/tools/sidebar.blade.php @@ -20,6 +20,13 @@ + + + {{-- --}} -- 2.39.5