feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
- Base: wintercms/winter branch 1.2 (full framework) - Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS - Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication - Partials: hero (offline-first), features, modes (offline/nube toggle), screenshots, pricing (3 planes), comparison, FAQ, CTA - Plugin VivesPOS.Site with ContactForm - Dockerfile: PHP 8.2 Apache, port 80, healthcheck - Added winter/wn-pages, blog, sitemap, seo plugins - Active theme set to vivespos
This commit is contained in:
272
modules/system/console/WinterMirror.php
Normal file
272
modules/system/console/WinterMirror.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php namespace System\Console;
|
||||
|
||||
use File;
|
||||
use Event;
|
||||
use StdClass;
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
/**
|
||||
* Console command to implement a "public" folder.
|
||||
*
|
||||
* This command will create symbolic links to files and directories
|
||||
* that are commonly required to be publicly available.
|
||||
*
|
||||
* @package winter\wn-system-module
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
class WinterMirror extends Command
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*/
|
||||
protected $name = 'winter:mirror';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*/
|
||||
protected $description = 'Generates a mirrored public folder using symbolic links.';
|
||||
|
||||
/**
|
||||
* @var array Files that should be mirrored
|
||||
*/
|
||||
protected $files = [
|
||||
'.htaccess',
|
||||
'.user.ini',
|
||||
'index.php',
|
||||
'favicon.ico',
|
||||
'robots.txt',
|
||||
'humans.txt',
|
||||
'sitemap.xml',
|
||||
'llms.txt',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array Directories that should be mirrored
|
||||
*/
|
||||
protected $directories = [
|
||||
'storage/app/uploads/public',
|
||||
'storage/app/media',
|
||||
'storage/app/resized',
|
||||
'storage/temp/public',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array Wildcard paths that should be mirrored
|
||||
*/
|
||||
protected $wildcards = [
|
||||
'modules/*/assets',
|
||||
'modules/*/resources',
|
||||
'modules/*/behaviors/*/assets',
|
||||
'modules/*/behaviors/*/resources',
|
||||
'modules/*/components/*/assets',
|
||||
'modules/*/components/*/resources',
|
||||
'modules/*/widgets/*/assets',
|
||||
'modules/*/widgets/*/resources',
|
||||
'modules/*/formwidgets/*/assets',
|
||||
'modules/*/formwidgets/*/resources',
|
||||
'modules/*/reportwidgets/*/assets',
|
||||
'modules/*/reportwidgets/*/resources',
|
||||
|
||||
'plugins/*/*/assets',
|
||||
'plugins/*/*/resources',
|
||||
'plugins/*/*/behaviors/*/assets',
|
||||
'plugins/*/*/behaviors/*/resources',
|
||||
'plugins/*/*/components/*/assets',
|
||||
'plugins/*/*/components/*/resources',
|
||||
'plugins/*/*/reportwidgets/*/assets',
|
||||
'plugins/*/*/reportwidgets/*/resources',
|
||||
'plugins/*/*/formwidgets/*/assets',
|
||||
'plugins/*/*/formwidgets/*/resources',
|
||||
'plugins/*/*/widgets/*/assets',
|
||||
'plugins/*/*/widgets/*/resources',
|
||||
|
||||
'themes/*/assets',
|
||||
'themes/*/resources',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string|null Local cache of the mirror destination path
|
||||
*/
|
||||
protected $destinationPath;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Register aliases for backwards compatibility with October
|
||||
$this->setAliases(['october:mirror']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->getDestinationPath();
|
||||
|
||||
$paths = new StdClass();
|
||||
$paths->files = $this->files;
|
||||
$paths->directories = $this->directories;
|
||||
$paths->wildcards = $this->wildcards;
|
||||
|
||||
/**
|
||||
* @event system.console.mirror.extendPaths
|
||||
* Enables extending the `php artisan winter:mirror` command
|
||||
*
|
||||
* You will have access to a $paths stdClass with `files`, `directories`, `wildcards` properties available for modifying.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* Event::listen('system.console.mirror.extendPaths', function ($paths) {
|
||||
* $paths->directories = array_merge($paths->directories, ['plugins/myauthor/myplugin/public']);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
Event::fire('system.console.mirror.extendPaths', [$paths]);
|
||||
|
||||
foreach ($paths->files as $file) {
|
||||
$this->mirrorFile($file);
|
||||
}
|
||||
|
||||
foreach ($paths->directories as $directory) {
|
||||
$this->mirrorDirectory($directory);
|
||||
}
|
||||
|
||||
foreach ($paths->wildcards as $wildcard) {
|
||||
$this->mirrorWildcard($wildcard);
|
||||
}
|
||||
|
||||
$this->output->writeln('<info>Mirror complete!</info>');
|
||||
}
|
||||
|
||||
protected function mirrorFile($file)
|
||||
{
|
||||
$this->output->writeln(sprintf('<info> - Mirroring: %s</info>', $file));
|
||||
|
||||
$src = base_path().'/'.$file;
|
||||
|
||||
$dest = $this->getDestinationPath().'/'.$file;
|
||||
|
||||
if (!File::isFile($src) || File::isFile($dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->mirror($src, $dest);
|
||||
}
|
||||
|
||||
protected function mirrorDirectory($directory)
|
||||
{
|
||||
$this->output->writeln(sprintf('<info> - Mirroring: %s</info>', $directory));
|
||||
|
||||
$src = base_path().'/'.$directory;
|
||||
|
||||
$dest = $this->getDestinationPath().'/'.$directory;
|
||||
|
||||
if (!File::isDirectory($src) || File::isDirectory($dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File::isDirectory(dirname($dest))) {
|
||||
File::makeDirectory(dirname($dest), 0755, true);
|
||||
}
|
||||
|
||||
$this->mirror($src, $dest);
|
||||
}
|
||||
|
||||
protected function mirrorWildcard($wildcard)
|
||||
{
|
||||
if (strpos($wildcard, '*') === false) {
|
||||
return $this->mirrorDirectory($wildcard);
|
||||
}
|
||||
|
||||
list($start, $end) = explode('*', $wildcard, 2);
|
||||
|
||||
$startDir = base_path().'/'.$start;
|
||||
|
||||
if (!File::isDirectory($startDir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (File::directories($startDir) as $directory) {
|
||||
$this->mirrorWildcard($start.basename($directory).$end);
|
||||
}
|
||||
}
|
||||
|
||||
protected function mirror($src, $dest)
|
||||
{
|
||||
if ($this->option('relative') && PHP_OS_FAMILY !== 'Windows') {
|
||||
$src = $this->getRelativePath($dest, $src);
|
||||
|
||||
if (strpos($src, '../') === 0) {
|
||||
$src = rtrim(substr($src, 3), '/');
|
||||
}
|
||||
}
|
||||
|
||||
File::link($src, $dest);
|
||||
}
|
||||
|
||||
protected function getDestinationPath()
|
||||
{
|
||||
if ($this->destinationPath !== null) {
|
||||
return $this->destinationPath;
|
||||
}
|
||||
|
||||
$destPath = $this->argument('destination');
|
||||
if (realpath($destPath) === false) {
|
||||
$destPath = base_path() . '/' . $destPath;
|
||||
}
|
||||
|
||||
if (!File::isDirectory($destPath)) {
|
||||
File::makeDirectory($destPath, 0755, true);
|
||||
}
|
||||
|
||||
$destPath = realpath($destPath);
|
||||
|
||||
$this->output->writeln(sprintf('<info>Destination: %s</info>', $destPath));
|
||||
|
||||
return $this->destinationPath = $destPath;
|
||||
}
|
||||
|
||||
protected function getRelativePath($from, $to)
|
||||
{
|
||||
$from = str_replace('\\', '/', $from);
|
||||
$to = str_replace('\\', '/', $to);
|
||||
|
||||
$dir = explode('/', is_file($from) ? dirname($from) : rtrim($from, '/'));
|
||||
$file = explode('/', $to);
|
||||
|
||||
while ($dir && $file && ($dir[0] == $file[0])) {
|
||||
array_shift($dir);
|
||||
array_shift($file);
|
||||
}
|
||||
|
||||
return str_repeat('../', count($dir)) . implode('/', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
* @return array
|
||||
*/
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['destination', InputArgument::REQUIRED, 'The destination path relative to the current directory. Eg: public/'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['relative', null, InputOption::VALUE_NONE, 'Create symlinks relative to the public directory.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user