Browse Source

Initial commit

master
Martins Eglitis 3 years ago
commit
f72952b4e3
23 changed files with 673 additions and 0 deletions
  1. +3
    -0
      .gitignore
  2. +21
    -0
      LICENSE
  3. +10
    -0
      README.md
  4. +29
    -0
      composer.json
  5. +174
    -0
      composer.lock
  6. +41
    -0
      gulpfile.js
  7. +31
    -0
      package.json
  8. +0
    -0
      public/css/dist/main.css
  9. +0
    -0
      public/css/src/main.scss
  10. +0
    -0
      public/files/.gitkeep
  11. +0
    -0
      public/fonts/.gitkeep
  12. +0
    -0
      public/img/.gitkeep
  13. +9
    -0
      public/index.php
  14. +0
    -0
      public/js/dist/main.js
  15. +0
    -0
      public/js/src/main.js
  16. +9
    -0
      src/Config/Main.php
  17. +0
    -0
      src/Controllers/Main/.gitkeep
  18. +114
    -0
      src/Misc/Bootstrap.php
  19. +30
    -0
      src/Misc/Routes.php
  20. +70
    -0
      src/Models/Main/TemplateModel.php
  21. +73
    -0
      src/Models/Main/UrlModel.php
  22. +18
    -0
      src/Templates/Container.php
  23. +41
    -0
      src/Views/Main/MainView.php

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
node_modules
vendor
.composer_lock

+ 21
- 0
LICENSE View File

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2018 Martins Eglitis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 10
- 0
README.md View File

@@ -0,0 +1,10 @@
# skeleton

A simple MVC skeleton for php apps.

## Requirements

- php >= 5.6
- composer
- npm
- gulp

+ 29
- 0
composer.json View File

@@ -0,0 +1,29 @@
{
"name": "",
"description": "",
"keywords": [],
"license": "MIT",
"homepage": "https://sitilge.id.lv",
"support": {
"issues": "https://sitilge.id.lv",
"source": "https://sitilge.id.lv"
},
"authors": [
{
"name": "Martins Eglitis",
"email": "martins@sitilge.id.lv"
}
],
"require": {
"php": ">= 5.6",
"nikic/fast-route": "*",
"filp/whoops": "*"
},
"require-dev" : {
},
"autoload": {
"psr-4": {
"Project\\": "src/"
}
}
}

+ 174
- 0
composer.lock View File

@@ -0,0 +1,174 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bc575a9b191a15b1234f4813b1576987",
"packages": [
{
"name": "filp/whoops",
"version": "2.1.14",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/c6081b8838686aa04f1e83ba7e91f78b7b2a23e6",
"reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6",
"shasum": ""
},
"require": {
"php": "^5.5.9 || ^7.0",
"psr/log": "^1.0.1"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "^4.8.35 || ^5.7",
"symfony/var-dumper": "^2.6 || ^3.0"
},
"suggest": {
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"Whoops\\": "src/Whoops/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Filipe Dobreira",
"homepage": "https://github.com/filp",
"role": "Developer"
}
],
"description": "php error handling for cool kids",
"homepage": "https://filp.github.io/whoops/",
"keywords": [
"error",
"exception",
"handling",
"library",
"throwable",
"whoops"
],
"time": "2017-11-23T18:22:44+00:00"
},
{
"name": "nikic/fast-route",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "181d480e08d9476e61381e04a71b34dc0432e812"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
"reference": "181d480e08d9476e61381e04a71b34dc0432e812",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35|~5.7"
},
"type": "library",
"autoload": {
"psr-4": {
"FastRoute\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov",
"email": "nikic@php.net"
}
],
"description": "Fast request router for PHP",
"keywords": [
"router",
"routing"
],
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "psr/log",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2016-10-10T12:19:37+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">= 5.6"
},
"platform-dev": []
}

+ 41
- 0
gulpfile.js View File

@@ -0,0 +1,41 @@
// Include gulp
var gulp = require('gulp');

// Include Plugins
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var cssnano = require('gulp-cssnano');
var concatcss = require('gulp-concat-css');
var concatjs = require('gulp-concat');
var uglifyjs = require('gulp-uglify');

// Compile Sass
gulp.task('sass', function() {
return gulp.src('public/css/src/*.scss')
.pipe(sass.sync())
.pipe(concatcss('main.css'))
.pipe(cssnano())
.pipe(gulp.dest('public/css/dist'));
});

// Concatenate & Minify JS
gulp.task('js', function() {
return gulp.src([
'public/js/src/jquery.js',
'public/js/src/*.js'])
.pipe(concatjs('main.js'))
.pipe(uglifyjs())
.pipe(gulp.dest('public/js/dist'));
});

// Watch Files For Changes
gulp.task('watch', function() {
gulp.watch(['public/css/src/*.scss'], ['sass']);
gulp.watch(['public/js/src/*.js'], ['js']);
});

// Default Task
gulp.task('default', [
'sass',
'js'
]);

+ 31
- 0
package.json View File

@@ -0,0 +1,31 @@
{
"name": "",
"version": "",
"description": "",
"main": "gulpfile.js",
"directories": {
"test": "tests"
},
"devDependencies": {
"gulp": "*",
"gulp-concat": "*",
"gulp-concat-css": "*",
"gulp-cssnano": "*",
"gulp-rename": "*",
"gulp-sass": "*",
"gulp-uglify": "*"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": ""
},
"author": "Martins Eglitis",
"license": "MIT",
"bugs": {
"url": ""
},
"homepage": ""
}

+ 0
- 0
public/css/dist/main.css View File


+ 0
- 0
public/css/src/main.scss View File


+ 0
- 0
public/files/.gitkeep View File


+ 0
- 0
public/fonts/.gitkeep View File


+ 0
- 0
public/img/.gitkeep View File


+ 9
- 0
public/index.php View File

@@ -0,0 +1,9 @@
<?php

$root = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");

require $root."/../vendor/autoload.php";

$frontController = new \Project\Misc\Bootstrap();

$frontController->init();

+ 0
- 0
public/js/dist/main.js View File


+ 0
- 0
public/js/src/main.js View File


+ 9
- 0
src/Config/Main.php View File

@@ -0,0 +1,9 @@
<?php

return [
"fqdn" => "/",
"development" => true,
"callable" => function($exception, $inspector, $run) {
echo "Some error.";
}
];

+ 0
- 0
src/Controllers/Main/.gitkeep View File


+ 114
- 0
src/Misc/Bootstrap.php View File

@@ -0,0 +1,114 @@
<?php

namespace Project\Misc;

use FastRoute\RouteCollector;
use Whoops\Handler\Handler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Run;

class Bootstrap
{
/**
* The initial method called.
*/
public function init()
{
$this->initThrowable();

$this->initSession();

$this->initRoute();
}

/**
* Initialize the throwable.
*/
private function initThrowable()
{
$root = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");

$config = require $root."/../src/Config/Main.php";

if (empty($config["development"])) {
$this->initHandler(function($exception, $inspector, $run) use ($config) {
call_user_func_array($config["callable"], [
$exception,
$inspector,
$run
]);

return Handler::DONE;
});

return;
}

$server = filter_input_array(INPUT_SERVER);

if (!empty($server["HTTP_X_REQUESTED_WITH"])
&& strtolower($server["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest") {
$this->initHandler(new JsonResponseHandler());

return;
}

$this->initHandler(new PrettyPageHandler());
}

/**
* Initialize the throwable handler.
*/
private function initSession()
{
session_start();
}

/**
* Initialize the throwable handler.
*/
private function initHandler(Handler $handler)
{
$run = new Run();

$run->pushHandler($handler);

$run->register();
}

/**
* Initialize the route handler.
*/
private function initRoute()
{
$root = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");

$routes = require $root."/../src/Misc/Routes.php";

$dispatcher = \FastRoute\simpleDispatcher(function (RouteCollector $collector) use ($routes) {
foreach ($routes as $route) {
$collector->addRoute($route[0], $route[1], $route[2]);
}
});

$method = $_SERVER["REQUEST_METHOD"];
$uri = $_SERVER["REQUEST_URI"];

$route = $dispatcher->dispatch($method, $uri);

switch ($route[0]) {
case \FastRoute\Dispatcher::NOT_FOUND:
throw new \ErrorException("Route $method $uri not found.");
break;
case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
throw new \ErrorException("Method $method not allowed.");
break;
case \FastRoute\Dispatcher::FOUND:
$handler = $route[1];
$arguments = $route[2];

call_user_func_array($handler, $arguments);
}
}
}

+ 30
- 0
src/Misc/Routes.php View File

@@ -0,0 +1,30 @@
<?php

use Project\Models\Main\TemplateModel;
use Project\Models\Main\UrlModel;
use Project\Views\Main\MainView;

$mainRoute = function() {
return
[
["GET", "POST"],
"/",
function(...$segments) {
$templateModel = new TemplateModel();
$urlModel = new UrlModel();

$mainView = new MainView();

$mainView->segments = $segments;

$mainView->templateModel = $templateModel;
$mainView->urlModel = $urlModel;

$mainView->manageOutput();
}
];
};

return [
$mainRoute(),
];

+ 70
- 0
src/Models/Main/TemplateModel.php View File

@@ -0,0 +1,70 @@
<?php

namespace Project\Models\Main;

class TemplateModel
{
public $data = [];

public $file = "";

/**
* Set a file.
*/
public function file($file)
{
$this->file = $file;

if (empty(pathinfo($file, PATHINFO_EXTENSION))) {
$this->file .= ".php";
}

return $this;
}

/**
* Set a parameter.
*/
public function set($key, $value = null)
{
if (is_array($key)) {
foreach ($key as $name => $value) {
$this->data[$name] = $value;
}

return $this;
}

$this->data[$key] = $value;

return $this;
}

/**
* Get a parameter.
*/
public function get($key)
{
return isset($this->data[$key]) ? $this->data[$key] : null;
}

/**
* Render a template.
*/
public function render($input = null)
{
ob_start();

extract($this->data, EXTR_SKIP);

if (null !== $input) {
echo $input;

return ob_get_clean();
}

require $this->file;

return ob_get_clean();
}
}

+ 73
- 0
src/Models/Main/UrlModel.php View File

@@ -0,0 +1,73 @@
<?php

namespace Project\Models\Main;

class UrlModel
{
/**
* Make a route.
*/
public function makeUrl($segments = [])
{
$root = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");

$config = require $root."/../src/Config/Main.php";

$pattern = [];

foreach ($segments as $index => $segment) {
if ('' !== $segment) {
$pattern[] = "%s";
} else {
unset($segments[$index]);
}
}

return rtrim($config["fqdn"], "/")."/".$this->prepare(implode("/", $pattern), $segments);
}

/**
* Prepare a pattern.
*/
private function prepare($pattern, $segments)
{
foreach ($segments as &$argument) {
$argument = preg_replace("#[^a-zA-Z0-9_\-]#", "", str_replace(" ", "_", $argument));
}

return vsprintf($pattern, $segments);
}

/**
* Get a segment.
*/
public function getSegment($index = 0)
{
$url = trim($this->getUrl(), '/');

$segments = explode("/", $url);
$count = count($segments);

if ($count <= $index || $index < 0) {
return $segments[$count - 1];
}

return $segments[$index];
}

/**
* Get the current url.
*/
public function getUrl()
{
$server = filter_input_array(INPUT_SERVER);

if (!empty($server["PATH_INFO"])) {
return rawurldecode(parse_url($server["PATH_INFO"], PHP_URL_PATH));
} elseif (!empty($server["REQUEST_URI"])) {
return rawurldecode(parse_url($server["REQUEST_URI"], PHP_URL_PATH));
}

return false;
}
}

+ 18
- 0
src/Templates/Container.php View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="lv">
<head>
<title></title>
<meta charset="utf-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="width=device-width, initial-scale=1" name="viewport">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta content="" property="og:title">
<meta content="" property="og:image">
<meta content="" property="og:description">
<link rel="stylesheet" href="<?php echo $url->makeUrl(); ?>css/dist/container.css">
</head>
<body>
<h1>Hello, world!</h1>
<script src="<?php echo $url->makeUrl(); ?>js/dist/container.js"></script>
</body>
</html>

+ 41
- 0
src/Views/Main/MainView.php View File

@@ -0,0 +1,41 @@
<?php

namespace Project\Views\Main;

use Project\Models\Main\TemplateModel;
use Project\Models\Main\UrlModel;

class MainView
{
public $segments;

/**
* MainView constructor.
*/
public function __construct(
$segments = [],
TemplateModel $templateModel = null,
UrlModel $urlModel = null
) {
$this->segments = $segments;
$this->templateModel = $templateModel;
$this->urlModel = $urlModel;
}

/**
* Manage the output.
*/
public function manageOutput()
{
$root = filter_input(INPUT_SERVER, "DOCUMENT_ROOT");

$config = require $root."/../src/Config/Main.php";

$post = filter_input_array(INPUT_POST);

echo $template = $this->templateModel
->set("url", $this->urlModel)
->file($root."/../src/Templates/Container.php")
->render();
}
}

Loading…
Cancel
Save