diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ea0efb7 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +BASE_URL=/ diff --git a/.gitignore b/.gitignore index af39706..eb1573f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,12 @@ /vendor/ composer.lock +# NPM +/node_modules/ +package-lock.json + # Environment .env + +# Blade +/cache/ diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..407e75c --- /dev/null +++ b/Readme.md @@ -0,0 +1,17 @@ +# ProVM Basic Web Project + +Basic structure for files and folders common for every web project. + +## Includes + ++ [Slim](http://slimframework.com/) ++ [Nyholm/Psr7](https://github.com/Nyholm/psr7) ++ [Nyholm/Psr7-Server](https://github.com/Nyholm/psr7-server) ++ [PHP-DI/Slim-Bridge](https://github.com/PHP-DI/Slim-Bridge) ++ [Slim-Blade](https://github.com/rubellum/Slim-Blade-View) ++ [Slim-Whoops](https://github.com/zeuxisoo/php-slim-whoops) ++ [PHP dotenv](https://github.com/vlucas/phpdotenv) ++ [jQuery](https://jquery.com/) ++ [Fomantic-UI](https://github.com/fomantic/Fomantic-UI) ++ [PHPUnit](https://phpunit.de/) ++ [Kint](https://kint-php.github.io/kint/) diff --git a/common/Alias/View.php b/common/Alias/View.php new file mode 100644 index 0000000..f28aeda --- /dev/null +++ b/common/Alias/View.php @@ -0,0 +1,5 @@ +render($response, 'home'); + } +} diff --git a/common/Definition/View.php b/common/Definition/View.php new file mode 100644 index 0000000..cfc21c6 --- /dev/null +++ b/common/Definition/View.php @@ -0,0 +1,8 @@ +separator = $separator; + } + protected $array; + public function start(): Merger { + $this->array = []; + return $this; + } + public function add($element): Merger { + $this->array []= $element; + return $this; + } + public function merge() { + return implode($this->separator, $this->array); + } +} diff --git a/common/Helper/Tree.php b/common/Helper/Tree.php new file mode 100644 index 0000000..38a9f00 --- /dev/null +++ b/common/Helper/Tree.php @@ -0,0 +1,58 @@ +merger = new Merger($separator); + } + protected $tree; + public function add($value, $parent = null, $alias = null): Tree { + if ($parent === null) { + if ($alias === null) { + $this->tree []= $value; + return $this; + } + $this->tree[$alias] = $value; + return $this; + } + if (!isset($this->tree[$parent])) { + return $this; + } + if ($alias === null) { + $this->tree []= $this->merger->start() + ->add($this->tree[$parent]) + ->add($value) + ->merge(); + return $this; + } + $this->tree[$alias] = $this->merger->start() + ->add($this->tree[$parent]) + ->add($value) + ->merge(); + return $this; + } + public function check_keys($tree) { + $bool = true; + foreach ($tree as $def) { + if (!isset($def[2])) { + continue; + } + $key = $def[2]; + $bool &= array_key_exists($key, $this->tree); + } + return $bool; + } + public function addTree($tree) { + while (!$this->check_keys($tree)) { + foreach ($tree as $def) { + $this->add($def[0], $def[1] ?? null, $def[2] ?? null); + } + } + } + public function build($tree) { + $this->tree = []; + $this->addTree($tree); + return (object) $this->tree; + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c0f5a1e --- /dev/null +++ b/composer.json @@ -0,0 +1,30 @@ +{ + "name": "provm/base_web", + "description": "Base web project", + "type": "project", + "license": "UNLICENSED", + "authors": [ + { + "name": "Aldarien", + "email": "aldarien85@gmail.com" + } + ], + "require": { + "slim/slim": "^4.7", + "nyholm/psr7": "^1.3", + "nyholm/psr7-server": "^1.0", + "rubellum/slim-blade-view": "^0.1.1", + "zeuxisoo/slim-whoops": "^0.7.3", + "php-di/slim-bridge": "^3.1", + "vlucas/phpdotenv": "^5.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5", + "kint-php/kint": "^3.3" + }, + "autoload": { + "psr-4": { + "ProVM\\Common\\": "common" + } + } +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..232a52b --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,66 @@ +const {src, dest, series, parallel} = require('gulp') +const fs = require('fs') +const path = require('path') +const concat = require('gulp-concat') +const sourcemaps = require('gulp-sourcemaps') +const babel = require('gulp-babel') +const uglify = require('gulp-uglify') +const rename = require('gulp-rename') +const merge = require('merge-stream') +const sass = require('gulp-dart-sass') + +let base_dir_js = 'resources/assets/scripts/' +let output_dir_js = 'public/assets/scripts/' + +function getFolders(dir) { + return fs.readdirSync(dir) + .filter(function(file) { + return fs.statSync(path.join(dir, file)).isDirectory() + }) +} + +function bundle_base_js(done) { + return src(base_dir_js + '*.js') + .pipe(concat('main.js')) + .pipe(dest(output_dir_js)) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(babel()) + .pipe(uglify()) + .pipe(rename('main.min.js')) + .pipe(sourcemaps.write('./')) + .pipe(dest(output_dir_js)) +} + +function bundle_js(done) { + let folders = getFolders(base_dir_js) + let tasks = folders.map(function(folder) { + return src(path.join(base_dir_js, folder, '**/*.js')) + .pipe(concat(folder + '.js', {newLine: ';'})) + .pipe(dest(output_dir_js)) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(babel()) + .pipe(uglify()) + .pipe(rename(folder + '.min.js')) + .pipe(sourcemaps.write('./')) + .pipe(dest(output_dir_js)) + }) + + return merge(tasks) +} + +let base_dir_sass = 'resources/assets/sass/' +let output_dir_css = 'public/assets/styles/' + +function bundle_base_sass(done) { + return src([base_dir_sass + '*.scss', '!' + base_dir_sass + '_*.scss']) + .pipe(sass()) + .pipe(rename({extname: '.css'})) + .pipe(dest(output_dir_css)) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) + .pipe(rename({extname: '.min.css'})) + .pipe(sourcemaps.write('./')) + .pipe(dest(output_dir_css)) +} + +exports.default = series(bundle_base_js, bundle_js, bundle_base_sass) diff --git a/package.json b/package.json new file mode 100644 index 0000000..3effc94 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "provm-base-web", + "version": "1.0.0", + "description": "Proyecto Base Web de ProVM", + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "author": "Aldarien", + "license": "UNLICENSED", + "devDependencies": { + "browserify": "^17.0.0", + "gulp": "^4.0.2", + "gulp-babel": "^8.0.0", + "gulp-buffer": "^0.0.2", + "gulp-concat": "^2.6.1", + "gulp-dart-sass": "^1.0.2", + "gulp-rename": "^2.0.0", + "gulp-sourcemaps": "^3.0.0", + "gulp-tap": "^2.0.0", + "gulp-uglify": "^3.0.2", + "merge-stream": "^2.0.0", + "mocha": "^8.0.0" + } +} diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..66ef8f6 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,4 @@ +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^ index.php [QSA,L] diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..159922a --- /dev/null +++ b/public/index.php @@ -0,0 +1,9 @@ +run(); diff --git a/resources/routes/web.php b/resources/routes/web.php new file mode 100644 index 0000000..4300725 --- /dev/null +++ b/resources/routes/web.php @@ -0,0 +1,16 @@ +add(__DIR__)->add($__environment)->merge(); +if (file_exists($folder)) { + $files = new DirectoryIterator($folder); + foreach ($files as $file) { + if ($file->isDir() or $file->getExtension() != 'php') { + continue; + } + include_once $file->getRealPath(); + } +} + +$app->get('/', Home::class); diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php new file mode 100644 index 0000000..56a1681 --- /dev/null +++ b/resources/views/home.blade.php @@ -0,0 +1,7 @@ +@extends('layout.base') + +@section('page_content') +
+

Home

+
+@endsection diff --git a/resources/views/layout/base.blade.php b/resources/views/layout/base.blade.php new file mode 100644 index 0000000..9deb8c1 --- /dev/null +++ b/resources/views/layout/base.blade.php @@ -0,0 +1,5 @@ + + +@include('layout.head') +@include('layout.body') + diff --git a/resources/views/layout/body.blade.php b/resources/views/layout/body.blade.php new file mode 100644 index 0000000..36dc72b --- /dev/null +++ b/resources/views/layout/body.blade.php @@ -0,0 +1,5 @@ + + @include('layout.header') + @yield('page_content') + @include('layout.footer') + diff --git a/resources/views/layout/footer.blade.php b/resources/views/layout/footer.blade.php new file mode 100644 index 0000000..348b9ab --- /dev/null +++ b/resources/views/layout/footer.blade.php @@ -0,0 +1,3 @@ + +@include('layout.scripts') diff --git a/resources/views/layout/head.blade.php b/resources/views/layout/head.blade.php new file mode 100644 index 0000000..bcdbce6 --- /dev/null +++ b/resources/views/layout/head.blade.php @@ -0,0 +1,5 @@ + + + Control de Gestión + @include('layout.styles') + diff --git a/resources/views/layout/header.blade.php b/resources/views/layout/header.blade.php new file mode 100644 index 0000000..3306939 --- /dev/null +++ b/resources/views/layout/header.blade.php @@ -0,0 +1,2 @@ +
+
diff --git a/resources/views/layout/scripts.blade.php b/resources/views/layout/scripts.blade.php new file mode 100644 index 0000000..b84fe33 --- /dev/null +++ b/resources/views/layout/scripts.blade.php @@ -0,0 +1,7 @@ +@if (isset($assets) and isset($assets['scripts'])) + @foreach ($assets['scripts'] as $script) + {!!$script!!} + @endforeach +@endif + +@stack('scripts') diff --git a/resources/views/layout/styles.blade.php b/resources/views/layout/styles.blade.php new file mode 100644 index 0000000..23c8d33 --- /dev/null +++ b/resources/views/layout/styles.blade.php @@ -0,0 +1,15 @@ +@if (isset($assets)) + @foreach ($assets as $type => $list) + @foreach ($list as $style) + @if ($type == 'styles') + + @elseif ($type == 'fonts') + + @elseif ($type == 'links') + {!!$style!!} + @endif + @endforeach + @endforeach +@endif + +@stack('styles') diff --git a/setup/app.php b/setup/app.php new file mode 100644 index 0000000..5a17d3c --- /dev/null +++ b/setup/app.php @@ -0,0 +1,52 @@ +load(); + +$builder = new Builder(); + +$folders = [ + 'common', + $__environment +]; +$files = [ + 'config', + 'setup' +]; +foreach ($files as $file) { + foreach ($folders as $folder) { + $filename = implode(DIRECTORY_SEPARATOR, [ + __DIR__, + $folder, + $file . '.php' + ]); + if (!file_exists($filename)) { + continue; + } + $builder->addDefinitions($filename); + } +} + +$container = $builder->build(); +$app = Bridge::create($container); +$app->setBasePath($container->get('base_url')); + +foreach ($folders as $folder) { + $filename = implode(DIRECTORY_SEPARATOR, [ + __DIR__, + $folder, + 'middleware.php' + ]); + if (!file_exists($filename)) { + continue; + } + include_once $filename; +} + +$app->addRoutingMiddleware(); + +include_once 'router.php'; diff --git a/setup/common/config.php b/setup/common/config.php new file mode 100644 index 0000000..0b1b9ad --- /dev/null +++ b/setup/common/config.php @@ -0,0 +1,16 @@ + true, + 'base_url' => $_ENV['BASE_URL'], + 'folders' => function() { + $directory = new Tree(DIRECTORY_SEPARATOR); + return $directory->build([ + [dirname(__DIR__, 2), null, 'base'], + ['public', 'base', 'public'], + ['resources', 'base', 'resources'], + ['routes', 'resources', 'routes'] + ]); + } +]; diff --git a/setup/composer.php b/setup/composer.php new file mode 100644 index 0000000..2d27ee1 --- /dev/null +++ b/setup/composer.php @@ -0,0 +1,6 @@ +getContainer()->get('folders')->routes, + $__environment . '.php' +]); diff --git a/setup/web/config.php b/setup/web/config.php new file mode 100644 index 0000000..460c297 --- /dev/null +++ b/setup/web/config.php @@ -0,0 +1,50 @@ + DI\decorate(function($prev, Container $c) { + $merger = new Merger(DIRECTORY_SEPARATOR); + $arr = (array) $prev; + $arr['templates'] = $merger->start()->add($prev->resources)->add('views')->merge(); + $arr['cache'] = $merger->start()->add($prev->base)->add('cache')->merge(); + return (object) $arr; + }), + 'urls' => function(Container $c) { + $tree = new Tree('/'); + return $tree->build([ + [$c->get('base_url'), null, 'base'], + ['assets', 'base', 'assets'], + ['images', 'assets', 'images'], + ['scripts', 'assets', 'scripts'], + ['styles', 'assets', 'styles'] + ]); + }, + 'assets' => function(Container $c) { + $arr = [ + 'links' => [ + '' + ], + 'fonts' => [ + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/icons.eot', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/icons.ttf', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/icons.woff', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/icons.woff2', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/outline-icons.eot', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/outline-icons.ttf', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/outline-icons.woff', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/outline-icons.woff2', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/brand-icons.eot', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/brand-icons.ttf', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/brand-icons.woff', + 'https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/themes/default/assets/fonts/brand-icons.woff2' + ], + 'scripts' => [ + '', + '' + ] + ]; + return $arr; + } +]; diff --git a/setup/web/middleware.php b/setup/web/middleware.php new file mode 100644 index 0000000..94c3ce7 --- /dev/null +++ b/setup/web/middleware.php @@ -0,0 +1,2 @@ +add(new Zeuxisoo\Whoops\Slim\WhoopsMiddleware()); diff --git a/setup/web/setup.php b/setup/web/setup.php new file mode 100644 index 0000000..c1071bd --- /dev/null +++ b/setup/web/setup.php @@ -0,0 +1,20 @@ + function(Container $c) { + if (!file_exists($c->get('folders')->cache)) { + mkdir($c->get('folders')->cache); + chmod($c->get('folders')->cache, 777); + } + return new ProVM\Common\Definition\View( + $c->get('folders')->templates, + $c->get('folders')->cache, + null, + [ + 'urls' => $c->get('urls'), + 'assets' => $c->get('assets') + ] + ); + } +];