Compare commits
14 Commits
323504901d
...
ecac73451b
Author | SHA1 | Date | |
---|---|---|---|
ecac73451b | |||
c2e8979c38 | |||
f5936c91ef | |||
11db4c173a | |||
2584170ac9 | |||
031d184e27 | |||
b9dc605924 | |||
c8d122ce3f | |||
acde7a5023 | |||
6c945e915f | |||
736eb72254 | |||
559d287a3d | |||
0d8aee20da | |||
4314902384 |
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
BASE_URL=/
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -2,5 +2,12 @@
|
||||
/vendor/
|
||||
composer.lock
|
||||
|
||||
# NPM
|
||||
/node_modules/
|
||||
package-lock.json
|
||||
|
||||
# Environment
|
||||
.env
|
||||
|
||||
# Blade
|
||||
/cache/
|
||||
|
17
Readme.md
Normal file
17
Readme.md
Normal file
@ -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/)
|
5
common/Alias/View.php
Normal file
5
common/Alias/View.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias;
|
||||
|
||||
interface View {
|
||||
}
|
12
common/Controller/Home.php
Normal file
12
common/Controller/Home.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Alias\View;
|
||||
|
||||
class Home {
|
||||
public function __invoke(Request $request, Response $response, View $view) {
|
||||
return $view->render($response, 'home');
|
||||
}
|
||||
}
|
8
common/Definition/View.php
Normal file
8
common/Definition/View.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Definition;
|
||||
|
||||
use Slim\Views\Blade;
|
||||
use ProVM\Common\Alias\View as ViewInterface;
|
||||
|
||||
class View extends Blade implements ViewInterface {
|
||||
}
|
21
common/Helper/Merger.php
Normal file
21
common/Helper/Merger.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Helper;
|
||||
|
||||
class Merger {
|
||||
protected $separator;
|
||||
public function __construct(string $separator) {
|
||||
$this->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);
|
||||
}
|
||||
}
|
58
common/Helper/Tree.php
Normal file
58
common/Helper/Tree.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Helper;
|
||||
|
||||
class Tree {
|
||||
protected $merger;
|
||||
public function __construct($separator) {
|
||||
$this->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;
|
||||
}
|
||||
}
|
30
composer.json
Normal file
30
composer.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
66
gulpfile.js
Normal file
66
gulpfile.js
Normal file
@ -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)
|
25
package.json
Normal file
25
package.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
4
public/.htaccess
Normal file
4
public/.htaccess
Normal file
@ -0,0 +1,4 @@
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^ index.php [QSA,L]
|
9
public/index.php
Normal file
9
public/index.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
$__environment = 'web';
|
||||
include_once implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__),
|
||||
'setup',
|
||||
'app.php'
|
||||
]);
|
||||
|
||||
$app->run();
|
16
resources/routes/web.php
Normal file
16
resources/routes/web.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
use ProVM\Common\Helper\Merger;
|
||||
use ProVM\Common\Controller\Home;
|
||||
|
||||
$folder = (new Merger(DIRECTORY_SEPARATOR))->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);
|
7
resources/views/home.blade.php
Normal file
7
resources/views/home.blade.php
Normal file
@ -0,0 +1,7 @@
|
||||
@extends('layout.base')
|
||||
|
||||
@section('page_content')
|
||||
<div class="ui center aligned container">
|
||||
<h1 class="header">Home</h1>
|
||||
</div>
|
||||
@endsection
|
5
resources/views/layout/base.blade.php
Normal file
5
resources/views/layout/base.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
@include('layout.head')
|
||||
@include('layout.body')
|
||||
</html>
|
5
resources/views/layout/body.blade.php
Normal file
5
resources/views/layout/body.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<body>
|
||||
@include('layout.header')
|
||||
@yield('page_content')
|
||||
@include('layout.footer')
|
||||
</body>
|
3
resources/views/layout/footer.blade.php
Normal file
3
resources/views/layout/footer.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<footer>
|
||||
</footer>
|
||||
@include('layout.scripts')
|
5
resources/views/layout/head.blade.php
Normal file
5
resources/views/layout/head.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Control de Gestión</title>
|
||||
@include('layout.styles')
|
||||
</head>
|
2
resources/views/layout/header.blade.php
Normal file
2
resources/views/layout/header.blade.php
Normal file
@ -0,0 +1,2 @@
|
||||
<header>
|
||||
</header>
|
7
resources/views/layout/scripts.blade.php
Normal file
7
resources/views/layout/scripts.blade.php
Normal file
@ -0,0 +1,7 @@
|
||||
@if (isset($assets) and isset($assets['scripts']))
|
||||
@foreach ($assets['scripts'] as $script)
|
||||
{!!$script!!}
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@stack('scripts')
|
15
resources/views/layout/styles.blade.php
Normal file
15
resources/views/layout/styles.blade.php
Normal file
@ -0,0 +1,15 @@
|
||||
@if (isset($assets))
|
||||
@foreach ($assets as $type => $list)
|
||||
@foreach ($list as $style)
|
||||
@if ($type == 'styles')
|
||||
<link rel="stylesheet" href="{{$style}}" />
|
||||
@elseif ($type == 'fonts')
|
||||
<link href={{$style}} />
|
||||
@elseif ($type == 'links')
|
||||
{!!$style!!}
|
||||
@endif
|
||||
@endforeach
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@stack('styles')
|
52
setup/app.php
Normal file
52
setup/app.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
use DI\ContainerBuilder as Builder;
|
||||
use DI\Bridge\Slim\Bridge;
|
||||
|
||||
include_once 'composer.php';
|
||||
|
||||
$dotenv = Dotenv\Dotenv::createImmutable(dirname(__DIR__));
|
||||
$dotenv->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';
|
16
setup/common/config.php
Normal file
16
setup/common/config.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
use ProVM\Common\Helper\Tree;
|
||||
|
||||
return [
|
||||
'debug' => 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']
|
||||
]);
|
||||
}
|
||||
];
|
6
setup/composer.php
Normal file
6
setup/composer.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
include_once implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__),
|
||||
'vendor',
|
||||
'autoload.php'
|
||||
]);
|
5
setup/router.php
Normal file
5
setup/router.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
include_once implode(DIRECTORY_SEPARATOR, [
|
||||
$app->getContainer()->get('folders')->routes,
|
||||
$__environment . '.php'
|
||||
]);
|
50
setup/web/config.php
Normal file
50
setup/web/config.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use ProVM\Common\Helper\Tree;
|
||||
use ProVM\Common\Helper\Merger;
|
||||
|
||||
return [
|
||||
'folders' => 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' => [
|
||||
'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/semantic.min.css" integrity="sha512-g/MzOGVPy3OQ4ej1U+qe4D/xhLwUn5l5xL0Fa7gdC258ZWVJQGwsbIR47SWMpRxSPjD0tfu/xkilTy+Lhrl3xg==" crossorigin="anonymous" />'
|
||||
],
|
||||
'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' => [
|
||||
'<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>',
|
||||
'<script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.7/semantic.min.js" integrity="sha512-1Nyd5H4Aad+OyvVfUOkO/jWPCrEvYIsQENdnVXt1+Jjc4NoJw28nyRdrpOCyFH4uvR3JmH/5WmfX1MJk2ZlhgQ==" crossorigin="anonymous"></script>'
|
||||
]
|
||||
];
|
||||
return $arr;
|
||||
}
|
||||
];
|
2
setup/web/middleware.php
Normal file
2
setup/web/middleware.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
$app->add(new Zeuxisoo\Whoops\Slim\WhoopsMiddleware());
|
20
setup/web/setup.php
Normal file
20
setup/web/setup.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
|
||||
return [
|
||||
ProVM\Common\Alias\View::class => 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')
|
||||
]
|
||||
);
|
||||
}
|
||||
];
|
Reference in New Issue
Block a user