├── .editorconfig ├── .env.example ├── .gitignore ├── Makefile ├── README.md ├── app ├── Controllers │ └── HomeController.php ├── Models │ └── User.php ├── helpers.php └── routes.php ├── composer.json ├── composer.lock ├── config ├── app.php ├── cookie.php ├── csrf.php ├── database.php ├── hash.php ├── logger.php ├── mail.php ├── pagination.php ├── services.php ├── session.php ├── slim.php └── view.php ├── database ├── migrations │ └── 20180803090653_create_users_table.php └── seeds │ ├── .gitkeep │ └── UserSeeder.php ├── docker-compose.yml ├── docker ├── build │ └── php │ │ └── Dockerfile ├── etc │ ├── nginx │ │ └── default.conf │ └── php │ │ ├── exim4.conf │ │ ├── php-default.ini │ │ └── xdebug.ini └── scripts.sh ├── docs ├── .gitignore ├── README.md ├── SUMMARY.md ├── facades │ ├── README.md │ ├── application.md │ └── service-provider.md ├── foundations │ ├── README.md │ └── form-request.md ├── handlers │ ├── README.md │ ├── error.md │ ├── not-allowed.md │ ├── not-found.md │ └── php-error.md ├── migrations │ ├── README.md │ └── migration.md ├── others │ ├── README.md │ ├── maildev.md │ └── xdebug.md ├── service-providers │ ├── README.md │ ├── cookie.md │ ├── csrf.md │ ├── database.md │ ├── flash.md │ ├── hash.md │ ├── logger.md │ ├── mail.md │ ├── pagination.md │ ├── redirection.md │ ├── session.md │ ├── validation.md │ └── view.md └── welcome │ └── structure.md ├── phinx.php ├── public └── index.php ├── resources └── views │ ├── errors │ ├── 400.csrf.html │ ├── 404.html │ ├── 405.html │ ├── 500.html │ └── 500.php.html │ ├── index.html │ └── paginations │ ├── default.html │ └── default.simple.html ├── slimork ├── Contracts │ ├── Controller.php │ ├── ExceptionHandler.php │ ├── Hasher.php │ ├── Middleware.php │ ├── Migration.php │ ├── Model.php │ ├── PaginatorView.php │ ├── ServiceProvider.php │ └── ViewExtension.php ├── Exceptions │ └── Handlers │ │ ├── ErrorHandler.php │ │ ├── NotAllowedHandler.php │ │ ├── NotFoundHandler.php │ │ └── PhpErrorHandler.php ├── Facades │ ├── App.php │ ├── Container.php │ ├── Cookie.php │ ├── Csrf.php │ ├── Database.php │ ├── Facade.php │ ├── Flash.php │ ├── Hash.php │ ├── Log.php │ ├── Mail.php │ ├── Paginator.php │ ├── Redirect.php │ ├── Request.php │ ├── Response.php │ ├── Router.php │ ├── Schema.php │ ├── Session.php │ ├── Settings.php │ ├── Validator.php │ └── View.php ├── Foundation │ ├── AliasLoader.php │ ├── App.php │ ├── Bootstrappers │ │ ├── Base │ │ │ ├── LoadEnvironmentVariables.php │ │ │ └── LoadSettings.php │ │ └── BuiltIn │ │ │ ├── RegisterFacades.php │ │ │ ├── RegisterHandlers.php │ │ │ ├── RegisterMiddlewares.php │ │ │ └── RegisterServiceProviders.php │ └── Http │ │ └── FormRequest.php ├── Middlewares │ └── Route │ │ └── DefaultMiddleware.php ├── Providers │ ├── Cookie │ │ ├── Cookie.php │ │ └── CookieServiceProvider.php │ ├── Csrf │ │ ├── Csrf.php │ │ ├── CsrfServiceProvider.php │ │ └── ViewExtension.php │ ├── Database │ │ ├── DatabaseManager.php │ │ ├── DatabaseServiceProvider.php │ │ └── PaginatorView.php │ ├── Flash │ │ ├── Flash.php │ │ ├── FlashServiceProvider.php │ │ └── ViewExtension.php │ ├── Hash │ │ ├── HashManager.php │ │ ├── HashServiceProvider.php │ │ └── Hasher │ │ │ ├── Argon2Hasher.php │ │ │ └── BCryptHasher.php │ ├── Log │ │ ├── Handlers │ │ │ ├── LogHandler.php │ │ │ └── RotatingFileHandler.php │ │ ├── LogServiceProvider.php │ │ └── Logger.php │ ├── Mail │ │ ├── Mail.php │ │ ├── MailServiceProvider.php │ │ └── Transport │ │ │ ├── MailgunTransport.php │ │ │ └── Transport.php │ ├── Pagination │ │ ├── DefaultPaginatorView.php │ │ ├── PaginationServiceProvider.php │ │ ├── Paginator │ │ │ ├── DefaultPaginator.php │ │ │ └── SimplePaginator.php │ │ ├── PaginatorManager.php │ │ └── Traits │ │ │ └── PaginatorOffset.php │ ├── Redirection │ │ ├── Http │ │ │ └── Response.php │ │ ├── Middleware │ │ │ └── Session.php │ │ ├── RedirectionServiceProvider.php │ │ ├── Redirector.php │ │ ├── Traits │ │ │ ├── RedirectorBackRequest.php │ │ │ └── RedirectorFormRequest.php │ │ └── ViewExtension.php │ ├── Session │ │ ├── Middleware │ │ │ └── Session.php │ │ ├── Segment.php │ │ ├── Session.php │ │ └── SessionServiceProvider.php │ ├── Validation │ │ ├── Rule.php │ │ ├── ValidationServiceProvider.php │ │ └── Validator.php │ └── View │ │ ├── DefaultViewExtension.php │ │ ├── ViewManager.php │ │ └── ViewServiceProvider.php └── helpers.php └── storage ├── cache └── views │ └── .gitignore └── logs └── .gitignore /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | indent_size = 4 18 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_TIMEZONE=Asia/Hong_Kong 2 | 3 | COOKIE_PATH=/ 4 | COOKIE_DOMAIN= 5 | 6 | CSRF_PREFIX=csrf 7 | CSRF_STRENGTH=16 8 | 9 | DB_CONNECTION=mysql 10 | DB_HOST=mysqldb 11 | DB_DATABASE=slimork 12 | DB_USERNAME=slimork 13 | DB_PASSWORD=12345678 14 | 15 | HASH_DRIVER=bcrypt 16 | HASH_BCRYPT_ROUNDS=10 17 | HASH_ARGON2_MEMORY_COST=1024 18 | HASH_ARGON2_THREADS=2 19 | HASH_ARGON2_TIME_COST=2 20 | 21 | LOGGER_ROTATE_MAX_FILE=5 22 | 23 | MAIL_DRIVER=sendmail 24 | MAIL_HOST= 25 | MAIL_PORT=25 26 | MAIL_USERNAME= 27 | MAIL_PASSWORD= 28 | MAIL_ENCRYPTION= 29 | 30 | PAGINATION_VIEWS_DEFAULT=default.html 31 | PAGINATION_VIEWS_SIMPLE=default.simple.html 32 | 33 | MAILGUN_SECRET= 34 | MAILGUN_DOMAIN= 35 | MAILGUN_ENDPOINT=https://api.mailgun.net 36 | 37 | SESSION_NAME=_sk 38 | SESSION_LIFETIME=7200 # 2 hour 39 | SESSION_PATH=/ 40 | SESSION_DOMAIN= 41 | 42 | VIEW_CHARSET=utf-8 43 | VIEW_AUTOESCAPE=html 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*~ 2 | .DS_Store 3 | 4 | .env 5 | 6 | /.vscode 7 | 8 | /docker/var/mysql/data 9 | /docker/tmp/php 10 | /node_modules 11 | /public/storage 12 | /storage/cache/view 13 | /storage/logs 14 | /vendor 15 | 16 | /storage/database.sqlite 17 | 18 | composer.phar 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo 3 | @echo "Web : Description" 4 | @echo "-------------- : ------------------" 5 | @echo "make composer : Download the composer.phar into current directory" 6 | @echo "make vendor : Download the required packages into vendor directory" 7 | @echo "make server : Run the dev server" 8 | @echo "make migration : Install the migration table to related database" 9 | @echo 10 | @echo "Docker : Description" 11 | @echo "--------------------------------- : -----------------" 12 | @echo "make docker-start : Start the docker service" 13 | @echo "make docker-stop : Stop the docker service" 14 | @echo "make docker-clean-tmp : Clean the tmp data" 15 | @echo "make docker-clean-mysql : Clean the mysql data" 16 | @echo "make docker-remove-containers : Remove slimork only docker containers" 17 | @echo "make docker-remove-all-containers : Remove all docker containers" 18 | @echo "make docker-remove-all-images : Remove all docker images" 19 | @echo "make docker-refresh : Remove the containers and images, then re-start the docker compose" 20 | @echo 21 | 22 | composer: 23 | @rm -rf composer.phar 24 | @curl https://getcomposer.org/composer.phar -o composer.phar 25 | 26 | vendor: 27 | @php composer.phar install 28 | 29 | server: 30 | @php -S localhost:8080 -t ./public 31 | 32 | migration: 33 | @php ./vendor/bin/phinx migrate 34 | 35 | docker-start: 36 | @bash ./docker/scripts.sh start 37 | 38 | docker-stop: 39 | @bash ./docker/scripts.sh stop 40 | @make docker-clean 41 | 42 | docker-clean: 43 | @make docker-clean-tmp 44 | 45 | docker-clean-tmp: 46 | @rm -rf ./docker/tmp/php/xdebug 47 | 48 | docker-clean-mysql: 49 | @rm -rf ./docker/var/mysql/data 50 | 51 | docker-remove-containers: 52 | @bash ./docker/scripts.sh remove-containers 53 | 54 | docker-remove-all-containers: 55 | @bash ./docker/scripts.sh remove-all-containers 56 | 57 | docker-remove-all-images: 58 | @bash ./docker/scripts.sh remove-all-images 59 | 60 | docker-refresh: 61 | @make docker-remove-all-containers 62 | @echo "-------- -------- -------->" 63 | @make docker-remove-all-images 64 | @echo "-------- -------- -------->" 65 | @make docker-start 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slimork 2 | 3 | A smallest skeleton application integrated slim and some packages 4 | 5 | ![Develop Status](https://img.shields.io/badge/status-beta-%230088FF.svg) 6 | ![Slim version](https://img.shields.io/badge/slim-3.x-green.svg) 7 | ![Slimork version](https://img.shields.io/badge/slimork-3.1.0-%23f330bd.svg) 8 | 9 | ## Container 10 | 11 | - [X] PHP-DI 12 | 13 | ## Providers 14 | 15 | - [X] Session 16 | - [X] Cookie 17 | - [X] Pagination 18 | - [X] Database 19 | - [X] Flash 20 | - [X] CSRF 21 | - [X] Validation 22 | - [X] View 23 | - [X] Mail 24 | - [X] Hash 25 | - [X] Logger 26 | - [X] Redirection 27 | 28 | ## Facades 29 | 30 | Application 31 | 32 | - [X] App 33 | - [X] Container 34 | - [X] Router 35 | - [X] Request 36 | - [X] Response 37 | - [X] Settings 38 | 39 | Service Provider 40 | 41 | - [X] Session 42 | - [X] Cookie 43 | - [X] Paginator 44 | - [X] DB 45 | - [X] Flash 46 | - [X] CSRF 47 | - [X] Validator 48 | - [X] View 49 | - [X] Mail 50 | - [X] Hash 51 | - [X] Log 52 | - [X] Redirection 53 | 54 | ## Migration 55 | 56 | - [X] Phpmig 57 | 58 | ## Other 59 | 60 | - [X] FormRequest 61 | -------------------------------------------------------------------------------- /app/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | view('index.html'); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | get('/', ['App\Controllers\HomeController', 'index'])->setName('home.index'); 3 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zeuxisoo/php-slimork", 3 | "description": "PHP Slim Framework skeleton application", 4 | "keywords": ["framework", "microframework", "slim", "skeleton", "rest"], 5 | "type": "project", 6 | "homepage": "https://github.com/zeuxisoo/php-slimork", 7 | "require": { 8 | "php": "^7.1.20", 9 | "slim/slim": "3.12.*", 10 | "slim/twig-view": "2.5.*", 11 | "slim/csrf": "0.8.*", 12 | "slim/flash": "0.4.*", 13 | "php-di/slim-bridge": "2.0.*", 14 | "symfony/var-dumper": "4.2.*", 15 | "monolog/monolog": "1.24.*", 16 | "swiftmailer/swiftmailer": "6.2.*", 17 | "respect/validation": "1.1.*", 18 | "cache/session-handler": "1.0.*", 19 | "illuminate/database": "5.8.*", 20 | "illuminate/pagination": "5.8.*", 21 | "illuminate/events": "5.8.*", 22 | "robmorgan/phinx": "0.10.*", 23 | "vlucas/phpdotenv": "3.3.*" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "App\\": "app/", 28 | "Slimork\\": "slimork/" 29 | }, 30 | "files": [ 31 | "app/helpers.php", 32 | "slimork/helpers.php" 33 | ] 34 | }, 35 | "config": { 36 | "preferred-install": "dist" 37 | }, 38 | "license": "BSD-2-Clause", 39 | "authors": [ 40 | { 41 | "name": "Zeuxis Lo", 42 | "email": "seekstudio@gmail.com" 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | env('APP_TIMEZONE', 'Asia/Hong_Kong'), 4 | 5 | 'middlewares' => [ 6 | Slimork\Middlewares\Route\DefaultMiddleware::class, 7 | ], 8 | 9 | 'handlers' => [ 10 | Slimork\Exceptions\Handlers\NotFoundHandler::class, 11 | Slimork\Exceptions\Handlers\NotAllowedHandler::class, 12 | Slimork\Exceptions\Handlers\ErrorHandler::class, 13 | Slimork\Exceptions\Handlers\PhpErrorHandler::class, 14 | ], 15 | 16 | 'providers' => [ 17 | Slimork\Providers\Session\SessionServiceProvider::class, 18 | Slimork\Providers\Cookie\CookieServiceProvider::class, 19 | Slimork\Providers\Pagination\PaginationServiceProvider::class, 20 | Slimork\Providers\Database\DatabaseServiceProvider::class, 21 | Slimork\Providers\Flash\FlashServiceProvider::class, 22 | Slimork\Providers\Csrf\CsrfServiceProvider::class, 23 | Slimork\Providers\Validation\ValidationServiceProvider::class, 24 | Slimork\Providers\View\ViewServiceProvider::class, 25 | Slimork\Providers\Mail\MailServiceProvider::class, 26 | Slimork\Providers\Hash\HashServiceProvider::class, 27 | Slimork\Providers\Log\LogServiceProvider::class, 28 | Slimork\Providers\Redirection\RedirectionServiceProvider::class, 29 | ], 30 | 31 | 'aliases' => [ 32 | 'App' => Slimork\Facades\App::class, 33 | 'Container' => Slimork\Facades\Container::class, 34 | 'Router' => Slimork\Facades\Router::class, 35 | 'Request' => Slimork\Facades\Request::class, 36 | 'Response' => Slimork\Facades\Response::class, 37 | 'Settings' => Slimork\Facades\Settings::class, 38 | 39 | 'Session' => Slimork\Facades\Session::class, 40 | 'Cookie' => Slimork\Facades\Cookie::class, 41 | 'Paginator' => Slimork\Facades\Paginator::class, 42 | 'DB' => Slimork\Facades\Database::class, 43 | 'Flash' => Slimork\Facades\Flash::class, 44 | 'Csrf' => Slimork\Facades\Csrf::class, 45 | 'Validator' => Slimork\Facades\Validator::class, 46 | 'View' => Slimork\Facades\View::class, 47 | 'Mail' => Slimork\Facades\Mail::class, 48 | 'Hash' => Slimork\Facades\Hash::class, 49 | 'Log' => Slimork\Facades\Log::class, 50 | 'Redirect' => Slimork\Facades\Redirect::class, 51 | 52 | 'Schema' => Slimork\Facades\Schema::class, 53 | ], 54 | ]; 55 | -------------------------------------------------------------------------------- /config/cookie.php: -------------------------------------------------------------------------------- 1 | new DateTime('+3 hours'), 4 | 'path' => env('COOKIE_PATH', '/'), 5 | 'domain' => env('COOKIE_DOMAIN', null), 6 | 'secure' => false, 7 | 'http_only' => true, 8 | ]; 9 | -------------------------------------------------------------------------------- /config/csrf.php: -------------------------------------------------------------------------------- 1 | true, 4 | 'prefix' => env('CSRF_PREFIX', 'csrf'), 5 | 'strength' => env('CSRF_STRENGTH', 16), 6 | ]; 7 | -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | env('DB_CONNECTION', 'mysql'), 4 | 5 | 'connections' => [ 6 | 'mysql' => [ 7 | 'driver' => 'mysql', 8 | 'host' => env('DB_HOST', 'mysqldb'), // IP or Host name or Docker service name 9 | 'database' => env('DB_DATABASE', 'slimork'), 10 | 'username' => env('DB_USERNAME', 'slimork'), 11 | 'password' => env('DB_PASSWORD', '12345678'), 12 | 'charset' => 'utf8', 13 | 'collation' => 'utf8_general_ci', 14 | 'prefix' => 'sw_', 15 | 'engine' => 'MyISAM', // MySQL Only 16 | ], 17 | 18 | 'sqlite' => [ 19 | 'driver' => 'sqlite', 20 | 'host' => env('DB_HOST', 'sqlite'), 21 | 'database' => env('DB_DATABASE', dirname(__DIR__).'/storage/database.sqlite'), 22 | 'username' => env('DB_USERNAME', 'slimork'), 23 | 'password' => env('DB_PASSWORD', '12345678'), 24 | 'charset' => 'utf8', 25 | 'collation' => 'utf8_general_ci', 26 | 'prefix' => 'sw_', 27 | 'engine' => 'MyISAM', // MySQL Only 28 | ], 29 | ], 30 | 31 | 'migration' => [ 32 | 'table' => 'migrations', 33 | ] 34 | ]; 35 | -------------------------------------------------------------------------------- /config/hash.php: -------------------------------------------------------------------------------- 1 | env('HASH_DRIVER', 'bcrypt'), // bcrypt, argon2 4 | 5 | 'bcrypt' => [ 6 | 'rounds' => env('HASH_BCRYPT_ROUNDS', 10), 7 | ], 8 | 9 | 'argon2' => [ 10 | 'memory_cost' => env('HASH_ARGON2_MEMORY_COST', 1024), 11 | 'threads' => env('HASH_ARGON2_THREADS', 2), 12 | 'time_cost' => env('HASH_ARGON2_TIME_COST', 2), 13 | ], 14 | ]; 15 | -------------------------------------------------------------------------------- /config/logger.php: -------------------------------------------------------------------------------- 1 | storage_path('/logs'), 4 | 5 | 'level' => Slimork\Providers\Log\Logger::DEBUG, 6 | 7 | 'processors' => [ 8 | Monolog\Processor\UidProcessor::class 9 | ], 10 | 11 | 'handlers' => [ 12 | 'rotate' => [ 13 | 'handler' => Slimork\Providers\Log\Handlers\RotatingFileHandler::class, 14 | 'options' => [ 15 | 'max_file' => env('LOGGER_ROTATE_MAX_FILE', 5) 16 | ] 17 | ] 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_DRIVER', 'sendmail'), // smtp, sendmail, mailgun 4 | 5 | // Smtp 6 | 'host' => env('MAIL_HOST', ''), 7 | 'port' => env('MAIL_PORT', 25), // 25, 587 etc 8 | 'username' => env('MAIL_USERNAME', ''), 9 | 'password' => env('MAIL_PASSWORD', ''), 10 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 11 | 12 | // Sendmail 13 | 'sendmail' => '/usr/sbin/sendmail -bs', 14 | ]; 15 | -------------------------------------------------------------------------------- /config/pagination.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'default' => env('PAGINATION_VIEWS_DEFAULT', 'default.html'), 5 | 'simple' => env('PAGINATION_VIEWS_SIMPLE', 'default.simple.html') 6 | ], 7 | 8 | 'paginator' => Slimork\Providers\Pagination\DefaultPaginatorView::class, 9 | ]; 10 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'secret' => env('MAILGUN_SECRET', ''), 6 | 'domain' => env('MAILGUN_DOMAIN', ''), 7 | 'endpoint' => env('MAILGUN_ENDPOINT', 'https://api.mailgun.net'), 8 | ], 9 | 10 | ]; 11 | -------------------------------------------------------------------------------- /config/session.php: -------------------------------------------------------------------------------- 1 | env('SESSION_NAME', '_sk'), 4 | 'lifetime' => env('SESSION_LIFETIME', 7200), // 2 hour 5 | 'path' => env('SESSION_PATH', '/'), 6 | 'domain' => env('SESSION_DOMAIN', null), 7 | 'secure' => false, 8 | 'httponly' => true, 9 | 'handler' => null, 10 | 'ini_sets' => [ 11 | 'cache_limiter' => 'nocache', 12 | 'cache_expire' => 180 13 | ] 14 | ]; 15 | -------------------------------------------------------------------------------- /config/slim.php: -------------------------------------------------------------------------------- 1 | '1.1', 4 | 'responseChunkSize' => 4096, 5 | 'outputBuffering' => 'append', 6 | 'determineRouteBeforeAppMiddleware' => true, 7 | 'displayErrorDetails' => true, 8 | 'addContentLengthHeader' => true, 9 | 'routerCacheFile' => false, 10 | ]; 11 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'charset' => env('VIEW_CHARSET', 'utf-8'), 6 | 'auto_reload' => true, 7 | 'strict_variables' => false, 8 | 'autoescape' => env('VIEW_AUTOESCAPE', 'html'), 9 | ], 10 | 11 | 'extensions' => [ 12 | Slimork\Providers\View\DefaultViewExtension::class 13 | ] 14 | 15 | ]; 16 | -------------------------------------------------------------------------------- /database/migrations/20180803090653_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 12 | $table->string('username'); 13 | $table->string('email')->unique(); 14 | $table->string('password'); 15 | $table->rememberToken(); 16 | $table->timestamps(); 17 | }); 18 | } 19 | 20 | public function down() { 21 | Schema::dropIfExists('users'); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /database/seeds/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeuxisoo/php-slimork/dbd52b281af0a5c17da805d5ced35f9be92aff5c/database/seeds/.gitkeep -------------------------------------------------------------------------------- /database/seeds/UserSeeder.php: -------------------------------------------------------------------------------- 1 | 'user', 9 | // 'password' => \Hash::make('useruser'), 10 | // 'email' => 'test@test.com' 11 | // ]); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | web: 5 | image: nginx:latest 6 | container_name: slimork-web 7 | restart: always 8 | ports: 9 | - "8080:80" 10 | - "3000:443" 11 | volumes: 12 | - "./docker/etc/nginx/default.conf:/etc/nginx/conf.d/default.conf" 13 | - ".:/slimork" 14 | depends_on: 15 | - php 16 | - mysqldb 17 | - maildev 18 | 19 | php: 20 | build: ./docker/build/php 21 | container_name: slimork-php 22 | restart: always 23 | expose: 24 | - "9000" 25 | volumes: 26 | - "./docker/etc/php/php-default.ini:/usr/local/etc/php/conf.d/php-default.ini" 27 | - "./docker/etc/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini" 28 | - "./docker/etc/php/exim4.conf:/etc/exim4/exim4.conf" 29 | - "./docker/tmp/php/xdebug:/tmp/php/xdebug" 30 | - ".:/slimork" 31 | 32 | mysqldb: 33 | image: mysql:5.6 34 | container_name: slimork-mysqldb 35 | restart: always 36 | ports: 37 | - "3306:3306" 38 | volumes: 39 | - "./docker/var/mysql/data:/var/lib/mysql" 40 | environment: 41 | - MYSQL_ROOT_PASSWORD=12345678 42 | - MYSQL_DATABASE=slimork 43 | - MYSQL_USER=slimork 44 | - MYSQL_PASSWORD=12345678 45 | 46 | maildev: 47 | image: djfarrelly/maildev 48 | container_name: slimork-maildev 49 | expose: 50 | - "25" 51 | ports: 52 | - "8081:80" 53 | -------------------------------------------------------------------------------- /docker/build/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.1.20-fpm 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update \ 6 | && apt-get install -q -y --assume-yes apt-utils \ 7 | exim4 mailutils libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng-dev libmcrypt-dev \ 8 | libcurl3 libcurl4-openssl-dev \ 9 | && rm -rf /var/lib/apt/lists/* 10 | 11 | RUN docker-php-ext-install gd mysqli pdo pdo_mysql zip gettext mcrypt curl 12 | 13 | RUN pecl install xdebug-2.6.1 14 | 15 | RUN echo "localhost localhost.localdomain" >> /etc/hosts 16 | 17 | WORKDIR /slimork 18 | 19 | EXPOSE 9000 20 | 21 | CMD ["php-fpm"] 22 | -------------------------------------------------------------------------------- /docker/etc/nginx/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | server_name localhost; 5 | 6 | index index.php index.html; 7 | 8 | error_log /var/log/nginx/error.log; 9 | access_log /var/log/nginx/access.log; 10 | 11 | root /slimork/public; 12 | 13 | location ~ \.php$ { 14 | try_files $uri =404; 15 | 16 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 17 | fastcgi_pass php:9000; 18 | fastcgi_index index.php; 19 | 20 | include fastcgi_params; 21 | 22 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 23 | fastcgi_param PATH_INFO $fastcgi_path_info; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docker/etc/php/php-default.ini: -------------------------------------------------------------------------------- 1 | display_errors = On 2 | 3 | sendmail_path=sendmail -i -t 4 | 5 | [Date] 6 | date.timezone=Asia/Hong_Kong 7 | -------------------------------------------------------------------------------- /docker/etc/php/xdebug.ini: -------------------------------------------------------------------------------- 1 | ; Xdebug 2 | ; See https://xdebug.org/docs/all_settings 3 | zend_extension="xdebug.so" 4 | 5 | [XDebug] 6 | xdebug.idekey=VSCODE 7 | xdebug.remote_enable=on 8 | xdebug.remote_handler=dbgp 9 | xdebug.remote_host="host.docker.internal" ; Or set your IDE/Editor ip 10 | xdebug.remote_port=9000 11 | xdebug.remote_autostart=on 12 | xdebug.remote_connect_back=off 13 | 14 | ;PHPStorm 15 | ;[Xdebug] 16 | ;xdebug.remote_enable=on 17 | ;xdebug.idekey=PHPSTORM 18 | ;xdebug.profiler_enable=0 19 | ;xdebug.max_nesting_level=700 20 | ;xdebug.remote_host="host.docker.internal" ; Or set your IDE/Editor ip 21 | ;xdebug.remote_port=9000 22 | 23 | ;Netbeans 24 | ;[Xdebug] 25 | ;xdebug.remote_enable=on 26 | ;xdebug.remote_handler=dbgp 27 | ;xdebug.remote_mode=req 28 | ;xdebug.remote_host="host.docker.internal" ; Or set your IDE/Editor ip 29 | ;xdebug.remote_port=9000 30 | 31 | ;Share 32 | xdebug.remote_log="/tmp/php/xdebug/xdebug.log" 33 | 34 | xdebug.profiler_enable=off 35 | xdebug.profiler_enable_trigger=on 36 | xdebug.profiler_output_dir="/tmp/php/xdebug" 37 | 38 | xdebug.auto_trace=off 39 | xdebug.trace_enable_trigger=on 40 | xdebug.trace_output_dir="/tmp/php/xdebug" 41 | 42 | xdebug.collect_params=on 43 | xdebug.collect_return=on 44 | xdebug.dump.GET=* 45 | xdebug.dump.POST=* 46 | xdebug.dump.COOKIE=* 47 | xdebug.dump.SESSION=* 48 | xdebug.var_display_max_data=512 ; default 512 49 | xdebug.var_display_max_depth=3 ; default 3 50 | -------------------------------------------------------------------------------- /docker/scripts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function start { 4 | docker-compose up -d 5 | } 6 | 7 | function stop { 8 | docker-compose down -v 9 | } 10 | 11 | function remove_all_containers { 12 | # Display all container numeric IDs 13 | containers=$(docker ps -a -q) 14 | 15 | if [ -z "$containers" ]; then 16 | echo "The containers is not exists" 17 | else 18 | echo "Deleting the containers" 19 | 20 | docker rm $containers 21 | fi 22 | } 23 | 24 | function remove_all_images { 25 | # Only show image numeric IDs 26 | images=$(docker images -q) 27 | 28 | if [ -z "$images" ]; then 29 | echo "The images is not exists" 30 | else 31 | echo "Deleting the images" 32 | 33 | docker rmi $images 34 | fi 35 | } 36 | 37 | function remove_containers { 38 | containers=$(docker ps -a | grep slimork | awk '{ print $1 }') 39 | 40 | if [ -z "$containers" ]; then 41 | echo "The slimork containers is not exists" 42 | else 43 | echo "Deleting the slimork containers" 44 | 45 | docker rm $containers 46 | fi 47 | } 48 | 49 | COMMAND=${@:$OPTIND:1} 50 | 51 | case $COMMAND in 52 | 53 | start) 54 | start 55 | ;; 56 | 57 | stop) 58 | stop 59 | ;; 60 | 61 | remove-all-containers) 62 | remove_all_containers 63 | ;; 64 | 65 | remove-all-images) 66 | remove_all_images 67 | ;; 68 | 69 | remove-containers) 70 | remove_containers 71 | ;; 72 | 73 | *) 74 | echo "- start" 75 | echo "- stop" 76 | echo "- remove-all-containers" 77 | echo "- remove-all-images" 78 | ;; 79 | 80 | esac 81 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | /_book 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Slimork 2 | 3 | Slimork is a set of packages to help you build your web project 4 | 5 | ## Introduction 6 | 7 | This is a simple documentation of `Slimork` 8 | 9 | The document will explain how to use the service provider, helpers, and other related functions 10 | 11 | ## Installation 12 | 13 | Create program from the Slimork 14 | 15 | composer create-project --prefer-dist --no-dev zeuxisoo/php-slimork:3.x-dev slimork 16 | 17 | Create the dotenv file from the example file 18 | 19 | > Optional, if the `dotenv` file is not exists, the application will using the default settings 20 | 21 | cp .env.example .env 22 | 23 | ## Settings 24 | 25 | The basic slim application settings in `./config/slim.php`. Other settings in the config directory, Please reference to the each service provider section 26 | 27 | ## Development 28 | 29 | Install the vendors 30 | 31 | 1. If the `composer` command already installed, run the following command 32 | 33 | composer install 34 | 35 | 2. If the `composer` command is not installed by default, run the following command 36 | 37 | make composer 38 | make vendor 39 | 40 | 3. Run the development server, the default url is `http://localhost:8080` 41 | 42 | make server 43 | 44 | ## Production 45 | 46 | 1. Install the vendor and composer like point 1 and 2 in development parts 47 | 48 | make composer 49 | make vendor 50 | 51 | 2. Create the dotenv for your production (`.env.production`) or using the default dotenv file (`.env`) 52 | 53 | cp .env .env.production 54 | 55 | 3. Run the server and set the APP_ENV variable like 56 | 57 | APP_ENV=production make server 58 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Welcome to Slimork](README.md) 4 | * [Structure](welcome/structure.md) 5 | * [Handlers](handlers/README.md) 6 | * [ErrorHandler](handlers/error.md) 7 | * [NotAllowedHandler](handlers/not-allowed.md) 8 | * [NotFoundHandler](handlers/not-found.md) 9 | * [PhpErrorHandler](handlers/php-error.md) 10 | * [Service Providers](service-providers/README.md) 11 | * [Session](service-providers/session.md) 12 | * [Cookie](service-providers/cookie.md) 13 | * [Pagination](service-providers/pagination.md) 14 | * [Database](service-providers/database.md) 15 | * [Flash](service-providers/flash.md) 16 | * [CSRF](service-providers/csrf.md) 17 | * [Validation](service-providers/validation.md) 18 | * [View](service-providers/view.md) 19 | * [Mail](service-providers/mail.md) 20 | * [Hash](service-providers/hash.md) 21 | * [Logger](service-providers/logger.md) 22 | * [Redirection](service-providers/redirection.md) 23 | * [Facades](facades/README.md) 24 | * [Application](facades/application.md) 25 | * [Service Provider](facades/service-provider.md) 26 | * [Foundations](foundations/README.md) 27 | * [FormRequest](foundations/form-request.md) 28 | * [Migrations](migrations/README.md) 29 | * [Migration](migrations/migration.md) 30 | * [Others](others/README.md) 31 | * [XDebug](others/xdebug.md) 32 | * [MailDev](others/maildev.md) 33 | -------------------------------------------------------------------------------- /docs/facades/README.md: -------------------------------------------------------------------------------- 1 | # Facades 2 | 3 | In slimork, we have provided facade pattern for you to easily to access the service provider 4 | 5 | ## Built-in 6 | 7 | Application 8 | 9 | - App 10 | - Container 11 | - Router 12 | - Request 13 | - Response 14 | - Settings 15 | 16 | Service provider 17 | 18 | - Session 19 | - Cookie 20 | - Paginator 21 | - Database 22 | - Flash 23 | - CSRF 24 | - Validation 25 | - View 26 | - Mail 27 | - Hash 28 | - Logger 29 | - Redirection 30 | -------------------------------------------------------------------------------- /docs/facades/application.md: -------------------------------------------------------------------------------- 1 | # Application 2 | 3 | In this level, We have providerd default container facade object to you. 4 | 5 | ## Facades 6 | 7 | **App** 8 | 9 | return the Slim object instance like `$app` 10 | 11 | **Container** 12 | 13 | return the Slim container like `$app->getContainer()` 14 | 15 | **Router** 16 | 17 | return the router from Slim container like `$app->getContainer()->get('router')` 18 | 19 | **Request** 20 | 21 | return the request from Slim container like `$app->getContainer()->get('request')` 22 | 23 | **Response** 24 | 25 | return the response from Slim container like `$app->getContainer()->get('response')` 26 | 27 | **Settings** 28 | 29 | return the settings from Slim container like `$app->getContainer()->get('settings')` 30 | 31 | extra methods: 32 | 33 | Settings::get('key'); 34 | Settings::set('key', 'value'); 35 | -------------------------------------------------------------------------------- /docs/facades/service-provider.md: -------------------------------------------------------------------------------- 1 | # Service Provider 2 | 3 | In this level, We have providerd service provider facade object to you. 4 | 5 | ## Facades 6 | 7 | The following code can be replaced with the related facades, like `session` 8 | 9 | // In controller 10 | $hello = $this->session->get('hello'); 11 | 12 | $session = $this->container->get('session'); 13 | $hello = $session->get('hello'); 14 | 15 | // In controller with facade 16 | $hello = Session::get('hello'); 17 | 18 | **Session** 19 | 20 | return the session service provider, like 21 | 22 | Session::set('name', 'value') 23 | Session::get('name') 24 | 25 | **Cookie** 26 | 27 | return the cookie service provider, like 28 | 29 | Cookie::set('name', 'value') 30 | Cookie::get('name') 31 | 32 | **Paginator** 33 | 34 | return the pagination service provider, like 35 | 36 | 37 | Paginator::findOffset('per_page', 'current_page') 38 | Paginator::items('[items]')->total('total')->perPage('per_page')->currentPage('current_page')->default() 39 | 40 | **DB** 41 | 42 | return the database service provider, like 43 | 44 | DB::table('names')->count() 45 | DB::table('names')->skip('offset')->take('per_page')->get() 46 | 47 | **Flash** 48 | 49 | return the flash service provider, like 50 | 51 | Flash::error('message') 52 | Flash::has('error') 53 | Flash::error() 54 | 55 | **CSRF** 56 | 57 | return the csrf serivce provider, like 58 | 59 | Csrf::getTokenForHiddenInputTags() 60 | Csrf::getTokenForMetaTags() 61 | Csrf::getTokens() 62 | 63 | **Validation** 64 | 65 | return the validation service provider, like 66 | 67 | $validator = Validator::validators(['username' => ''], [ 68 | 'username' => Slimork\Providers\Validation\Rule::stringType()->notEmpty() 69 | ]); 70 | 71 | $validator->fails(); 72 | 73 | **View** 74 | 75 | return the view service provider, like 76 | 77 | View::render(Container::get('response'), 'index.html') 78 | 79 | **Mail** 80 | 81 | return the mail service provider, like 82 | 83 | Mail::subject('subject')->from('email')->to('email')->body('content')->send() 84 | 85 | **Hash** 86 | 87 | return the hash service provider, like 88 | 89 | Hash::make('string') 90 | Hash::check('string', 'hashed_string') 91 | Hash::needsRehash('hashed_string') 92 | 93 | **Logger** 94 | 95 | return the logger service provider, like 96 | 97 | Log::info('message') 98 | 99 | **Redirection** 100 | 101 | return the redirection service provider, like 102 | 103 | Redirect::to('/home/index'); 104 | Redirect::route('home.index'); 105 | Redirect::away('http://hk.yahoo.com'); 106 | -------------------------------------------------------------------------------- /docs/foundations/README.md: -------------------------------------------------------------------------------- 1 | # Foundations 2 | 3 | In slimork, we have built-in some useful object for you to easy handle the incoming or outgoing data 4 | 5 | ## Built-in 6 | 7 | - FormRequest 8 | -------------------------------------------------------------------------------- /docs/foundations/form-request.md: -------------------------------------------------------------------------------- 1 | # FormRequest 2 | 3 | A easy way for you to validate the input data before process or store data 4 | 5 | ## Usage 6 | 7 | Create `Request` object like `LoginRequest` first, and the content like 8 | 9 | File: app\Requests\LoginRequest.php 10 | 11 | Rule::notEmpty()->noWhitespace()->length(4, 30), 22 | 'password' => Rule::notEmpty()->length(8, 30), 23 | ]; 24 | } 25 | 26 | public function messages() { 27 | return []; 28 | } 29 | 30 | } 31 | 32 | Now, import the `LoginRequest` object in the controller object, and the related variable will be auto validated and redirect back to submit page automatically when got error 33 | 34 | File: app\Controllers\HomeController.php 35 | 36 | getParams() 46 | ); 47 | } 48 | 49 | } 50 | 51 | ## Notes 52 | 53 | You cannot be using the variable named `$request` for any `FormRequest` object, because of this variable was declared and pointed to the `Slim\Http\Request` object in the PHP-DI container 54 | -------------------------------------------------------------------------------- /docs/handlers/README.md: -------------------------------------------------------------------------------- 1 | # Handlers 2 | 3 | In slimork, we have expose the basic `Slim` handler for users to easily custom the layout in HTML. 4 | 5 | ## Built-in 6 | 7 | - ErrorHandler 8 | - NotAllowedHandler 9 | - NotFoundHandler 10 | - PhpErrorHandler 11 | -------------------------------------------------------------------------------- /docs/handlers/error.md: -------------------------------------------------------------------------------- 1 | # ErrorHandler 2 | 3 | Overwrite default `Slim` framework application's error handler 4 | 5 | ## Usage 6 | 7 | 1. Open the `config/app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Enable the `Slimork` error handler 12 | 13 | 'handlers' => [ 14 | ... 15 | Slimork\Exceptions\Handlers\ErrorHandler::class, 16 | ... 17 | ], 18 | 19 | ## Custom layout 20 | 21 | If you want to custom the default error handler layout, You can follow these steps 22 | 23 | 1. Open the `resources/views/errors/500.html` 24 | 25 | vim resources/views/errors/500.html 26 | 27 | 2. Modify the content in HTML 28 | -------------------------------------------------------------------------------- /docs/handlers/not-allowed.md: -------------------------------------------------------------------------------- 1 | # NotAllowedHandler 2 | 3 | Overwrite to default `Slim` framework application's not allowed exception 4 | 5 | ## Usage 6 | 7 | 1. Open the `config/app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Enable the `Slimork` not allowered handler 12 | 13 | 'handlers' => [ 14 | ... 15 | Slimork\Exceptions\Handlers\NotAllowedHandler::class, 16 | ... 17 | ], 18 | 19 | ## Custom layout 20 | 21 | If you want to custom the default error handler layout, You can follow these steps 22 | 23 | 1. Open the `resources/views/errors/405.html` 24 | 25 | vim resources/views/errors/405.html 26 | 27 | 2. Modify the content in HTML 28 | -------------------------------------------------------------------------------- /docs/handlers/not-found.md: -------------------------------------------------------------------------------- 1 | # NotFoundHandler 2 | 3 | Overwrite to default `Slim` framework application's not found exception 4 | 5 | ## Usage 6 | 7 | 1. Open the `config/app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Enable the `Slimork` not found handler 12 | 13 | 'handlers' => [ 14 | ... 15 | Slimork\Exceptions\Handlers\NotFoundHandler::class, 16 | ... 17 | ], 18 | 19 | ## Custom layout 20 | 21 | If you want to custom the default error handler layout, You can follow these steps 22 | 23 | 1. Open the `resources/views/errors/404.html` 24 | 25 | vim resources/views/errors/404.html 26 | 27 | 2. Modify the content in HTML 28 | -------------------------------------------------------------------------------- /docs/handlers/php-error.md: -------------------------------------------------------------------------------- 1 | # NotFoundHandler 2 | 3 | Overwrite to default runtime PHP errors 4 | 5 | ## Usage 6 | 7 | 1. Open the `config/app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Enable the `Slimork` php error handler 12 | 13 | 'handlers' => [ 14 | ... 15 | Slimork\Exceptions\Handlers\PhpErrorHandler::class, 16 | ... 17 | ], 18 | 19 | ## Custom layout 20 | 21 | If you want to custom the default error handler layout, You can follow these steps 22 | 23 | 1. Open the `resources/views/errors/500.php.html` 24 | 25 | vim resources/views/errors/500.php.html 26 | 27 | 2. Modify the content in HTML 28 | -------------------------------------------------------------------------------- /docs/migrations/README.md: -------------------------------------------------------------------------------- 1 | # Migrations 2 | 3 | In slimork, we have included the `robmorgan/phinx` package for you transform the migration or seed to database 4 | 5 | ## Built-in 6 | 7 | - Migration 8 | - Seed 9 | -------------------------------------------------------------------------------- /docs/migrations/migration.md: -------------------------------------------------------------------------------- 1 | # Migration 2 | 3 | This command can help you migration the migration file transform to your database 4 | 5 | ## Usage 6 | 7 | Fist, you must run this command to migration the default migration file and default user table 8 | 9 | php ./vendor/bin/phinx migrate 10 | 11 | Next, Create the migration file, like 12 | 13 | php ./vendor/bin/phinx create CreateSomesTable 14 | 15 | Edit the generated file, like 16 | 17 | vim database/migrations/YYYYMMDDHHMMSS_create_somes_table.php 18 | 19 | And the content like 20 | 21 | increments('id'); 32 | $table->string('name'); 33 | $table->string('email')->unique(); 34 | $table->string('password'); 35 | $table->rememberToken(); 36 | $table->timestamps(); 37 | }); 38 | } 39 | 40 | public function down() { 41 | Schema::dropIfExists('somes'); 42 | } 43 | 44 | } 45 | 46 | Then, you can run the migration command again, to migrate the schema into database 47 | 48 | php ./vendor/bin/phinx migrate 49 | 50 | ## Other 51 | 52 | If you don't like to using the `Schema` facade, you can replace it with migration attribute 53 | 54 | $this->schema 55 | 56 | // like 57 | $this->schema->create('table', function(Blueprint $table) { 58 | ... 59 | ... 60 | ... 61 | }); 62 | 63 | $this->schema->dropIfExists('table'); 64 | -------------------------------------------------------------------------------- /docs/others/README.md: -------------------------------------------------------------------------------- 1 | # Others 2 | 3 | Related subject of Slimork 4 | 5 | ## Subjects 6 | 7 | - XDebug 8 | - MailDev 9 | -------------------------------------------------------------------------------- /docs/others/maildev.md: -------------------------------------------------------------------------------- 1 | # MailDev 2 | 3 | Simple way to testing mail service in development 4 | 5 | ## Requirement 6 | 7 | The docker service must started 8 | 9 | ## Web interface 10 | 11 | The default web GUI is `http://localhost:8081` 12 | 13 | ## Send by Sendmail 14 | 15 | Edit the `mail.php` in config directory like 16 | 17 | 'sendmail', 20 | 21 | ... 22 | ... 23 | 24 | 'sendmail' => '/usr/sbin/sendmail -bs', 25 | ]; 26 | 27 | 28 | ## Send by SMTP 29 | 30 | Edit the `mail.php` in config directory like 31 | 32 | 'smtp', 35 | 36 | 'host' => 'maildev', 37 | 'port' => 25, 38 | 'username' => '', 39 | 'password' => '', 40 | 'encryption' => '', 41 | 42 | ... 43 | ... 44 | ]; 45 | -------------------------------------------------------------------------------- /docs/others/xdebug.md: -------------------------------------------------------------------------------- 1 | # XDebug 2 | 3 | XDebug for the Editor / IDE 4 | 5 | ## Requirement 6 | 7 | The docker service must started 8 | 9 | ## VsCode 10 | 11 | **Installation** 12 | 13 | 1. Install the extension named `felixfbecker/vscode-php-debug` 14 | 15 | 2. Add the following settings in `Debug` => `Open launch.json` 16 | 17 | { 18 | "version": "0.2.0", 19 | "configurations": [ 20 | { 21 | "name": "Listen for XDebug", 22 | "type": "php", 23 | "request": "launch", 24 | "port": 9000, 25 | "pathMappings": { 26 | "/slimork": "${workspaceRoot}", 27 | }, 28 | "xdebugSettings": { 29 | 30 | } 31 | }, 32 | { 33 | "name": "Launch currently open script", 34 | "type": "php", 35 | "request": "launch", 36 | "program": "${file}", 37 | "cwd": "${fileDirname}", 38 | "port": 9000 39 | } 40 | ] 41 | } 42 | 43 | **Profiling** 44 | 45 | 1. Add the `XDEBUG_PROFILE` in the url like 46 | 47 | http://domain.com/?XDEBUG_PROFILE=1 48 | 49 | 2. The profiling result will store in the following path 50 | 51 | docker/tmp/php/xdebug/cachegrind.out.* 52 | 53 | **Trace** 54 | 55 | 1. Add the `XDEBUG_TRACE` in the url like 56 | 57 | http://domain.com/?XDEBUG_TRACE=1 58 | 59 | 2. The trace result will store in the following path 60 | 61 | docker/tmp/php/xdebug/trace.*.xt 62 | -------------------------------------------------------------------------------- /docs/service-providers/README.md: -------------------------------------------------------------------------------- 1 | # Service Providers 2 | 3 | In slimork, we have provided basic service providers for users to easily obtain these services through injection. 4 | 5 | ## Built-in 6 | 7 | - Session 8 | - Cookie 9 | - Pagination 10 | - Database 11 | - Flash 12 | - CSRF 13 | - Validation 14 | - View 15 | - Mail 16 | - Hash 17 | - Logger 18 | - Redirection 19 | -------------------------------------------------------------------------------- /docs/service-providers/cookie.md: -------------------------------------------------------------------------------- 1 | # Cookie 2 | 3 | The `cookie` service provider was provided easy way to control the cookie status in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Cookie\CookieServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default cookie config like store lifetime, path and so on 20 | 21 | vim config/cookie.php 22 | 23 | - default lifetime: `current time` + `3 hours` 24 | 25 | ## Usage 26 | 27 | You can access the cookie service provider by the following code 28 | 29 | **Set cookie** 30 | 31 | $this->cookie->set('name', 'value'); 32 | $this->cookie->set('name', 'value', [ 33 | // Optional, This argument can overwrite the default cookie option when value was provided 34 | ]); 35 | 36 | **Get cookie** 37 | 38 | $this->cookie->get('name'); 39 | 40 | **Remove cookie** 41 | 42 | $this->cookie->remove('name'); 43 | 44 | **Check the value is or not exists** 45 | 46 | $this->cookie->has('name'); 47 | -------------------------------------------------------------------------------- /docs/service-providers/csrf.md: -------------------------------------------------------------------------------- 1 | # CSRF 2 | 3 | This service provider provided CSRF protection in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Csrf\CsrfServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default csrf config like store prefix, strength 20 | 21 | vim config/csrf.php 22 | 23 | - default prefix: `csrf` 24 | - default strength: `16` 25 | 26 | ## Usage 27 | 28 | You can access the csrf service provider by the following code 29 | 30 | **Base usage** 31 | 32 | You can pass the generated token to view, and use it 33 | 34 | For controller: 35 | 36 | $tags = $this->csrf->getTokenForHiddenInputTags(); 37 | $tags = $this->csrf->getTokenForMetaTags(); 38 | 39 | For view: 40 | 41 | {% raw %} 42 | {{ tags | raw }} 43 | {% endraw %} 44 | 45 | **Advanace usage** 46 | 47 | Without controller, the view have global virables were named `csrf`, `csrf_metas` and `csrf_tags` 48 | 49 | When using the `{{ csrf }}` variable, you need to custom the HTML to what you want, like 50 | 51 | {% raw %} 52 | 53 | 54 | {% endraw %} 55 | 56 | But if you want to generate meta tags only, just call `{{ csrf_metas }}`, it will generate: 57 | 58 | 59 | 60 | 61 | 62 | Also, In the form protection, you can using the `{{ csrf_tags }}` to do it, generated html like: 63 | 64 | 65 | 66 | 67 | **Other usage** 68 | 69 | If you want to control more 70 | 71 | In controller: 72 | 73 | $csrf_tokens = $this->csrf->getTokens(); 74 | 75 | In view: 76 | 77 | {% raw %} 78 | {% for name, value in csrf_tokens %} 79 | 80 | {% endfor %} 81 | 82 | {% for name, value in csrf_tokens %} 83 | 84 | {% endfor %} 85 | {% endraw %} 86 | -------------------------------------------------------------------------------- /docs/service-providers/database.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 | This service provider can help developer easily to access the database by `Illuminate/Database` 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Database\DatabaseServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default database config 20 | 21 | vim config/database.php 22 | 23 | ## Usage 24 | 25 | If you have used `Illuminate/Database`, you can use similar code to achieve what you want. 26 | 27 | Base query in collector without define related model 28 | 29 | $user = $this->db->table('users')->find(1); 30 | $users = $this->db->table('users')->get(); 31 | 32 | Using other connection in query 33 | 34 | $this->db->getConnection('connection')->table('user')->find(1); 35 | 36 | Or you can define model first then access 37 | 38 | class User extends \Slimork\Contracts\Model { 39 | 40 | } 41 | 42 | $user = User::find(1); 43 | $user = User::on('connection')->find(1); 44 | 45 | Pagination for data 46 | 47 | $user = User::paginate(1); 48 | 49 | echo $paginate->render(); 50 | 51 | Other methods 52 | 53 | // Return object like: { total: 1 } 54 | $this->db->fetchOneRaw("SELECT COUNT(*) AS total FROM table"); 55 | 56 | More information you can reference to [this package](https://laravel.com/docs/master/queries) 57 | -------------------------------------------------------------------------------- /docs/service-providers/flash.md: -------------------------------------------------------------------------------- 1 | # Flash 2 | 3 | This service provider provided flash message in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Csrf\FlashServiceProvider::class, 16 | ... 17 | ] 18 | 19 | ## Usage 20 | 21 | You can access the flash service provider by the following code 22 | 23 | **Set the message** 24 | 25 | $this->flash->error('message'); 26 | $this->flash->success('message'); 27 | 28 | using the setter 29 | 30 | $this->flash->setError('message'); 31 | $this->flash->setSuccess('message'); 32 | 33 | set custom type for message 34 | 35 | $this->flash->setTypeMessage('type', 'message'); 36 | 37 | **Get the message** 38 | 39 | $this->flash->error(); 40 | $this->flash->success(); 41 | 42 | using the getter 43 | 44 | $this->flash->getError(); 45 | $this->flash->getSuccess(); 46 | 47 | get custom message by type 48 | 49 | $this->flash->getTypeMessage('type'); 50 | 51 | **Other methods** 52 | 53 | check the message is or not exists 54 | 55 | $this->flash->has('type'); 56 | 57 | **Get the message in view** 58 | 59 | This service provider was provided two view functions were named 60 | 61 | - `has_flash('type')`: Check the type of message is or not exists 62 | - `flash('type')`: Get the type of message from flash object and then remove it 63 | 64 | And the code looks like 65 | 66 | {% raw %} 67 | {% if has_flash('type') %} 68 |
69 | Oh! {{ flash('type') }} 70 |
71 | {% endif %} 72 | {% endraw %} -------------------------------------------------------------------------------- /docs/service-providers/hash.md: -------------------------------------------------------------------------------- 1 | # Hash 2 | 3 | This service provider can provide secure BCrypt and Argon2 hashing for store password 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Hash\HashServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default mail config like hash algorithm and related algorithm settings. 20 | 21 | vim config/hash.php 22 | 23 | - default hashing algorithm: `bcrypt` 24 | 25 | ## Usage 26 | 27 | You can access the hash service provider by the following code 28 | Base Usage** 29 | 30 | Create hashed string 31 | 32 | $this->hash->make('string'); 33 | 34 | Check the hashed string is or not matched 35 | 36 | $this->hash->check('string', 'hashed_string'); 37 | 38 | Rehash the value 39 | 40 | $this->hash->needsRehash('hashed_string'); 41 | 42 | **Overwrite default bcrypt options** 43 | 44 | Create hashed string (cost: 12) 45 | 46 | $this->hash->make('string', ['cost' => 10]); 47 | 48 | Rehash the value (cost: 12) 49 | 50 | $this->hash->needsRehash('hashed_string', ['cost' => 10]); 51 | 52 | **Overwrite default argon2 options** 53 | 54 | Create hashed string (memory: 2046, threads: 4, time: 4) 55 | 56 | $this->hash->make('string', [ 57 | 'memory_cost' => 2046, 58 | 'threads' => 4, 59 | 'time_cost' => 4, 60 | ]); 61 | 62 | Rehash the value (memory: 2046, threads: 4, time: 4) 63 | 64 | $this->hash->needsRehash('hashed_string', [ 65 | 'memory_cost' => 2046, 66 | 'threads' => 4, 67 | 'time_cost' => 4, 68 | ]); 69 | -------------------------------------------------------------------------------- /docs/service-providers/logger.md: -------------------------------------------------------------------------------- 1 | # Logger 2 | 3 | This service provider can provider `Monolog` logging service in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Log\LogServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default logger config like store log path, level and so on 20 | 21 | vim config/logger.php 22 | 23 | - default store log path: `/storage/logs` 24 | 25 | ## Usage 26 | 27 | You can access the logger service provider by the following code 28 | 29 | $this->log->debug('message'); 30 | $this->log->info('message'); 31 | $this->log->notice('message'); 32 | $this->log->warn('message'); 33 | $this->log->warning('message'); 34 | $this->log->error('message'); 35 | $this->log->critical('message'); 36 | $this->log->alert('message'); 37 | $this->log->emergency('message'); 38 | 39 | ## Processors 40 | 41 | This logger service provider was enabled uid processor by default. 42 | 43 | If you want to add or disable processor, please change the processor section in the logger config (`config/logger.php`) like 44 | 45 | 'processors' => [ 46 | Monolog\Processor\UidProcessor::class, 47 | ... 48 | Your\Custom\Or\Monolog\Processor::class, 49 | ... 50 | ], 51 | 52 | ## Handlers 53 | 54 | This logger service provider was enabled rotating file handler by default. 55 | 56 | If you want to add or disable processor, please change the handler section in the logger config (`config/logger.php`) like 57 | 58 | 'handlers' => [ 59 | 'rotate' => [ 60 | 'handler' => Slimork\Providers\Log\Handlers\RotatingFileHandler::class, 61 | 'options' => [ 62 | 'max_file' => 5 63 | ] 64 | ], 65 | ... 66 | 'IDENTITY_NAME' => [ 67 | 'handler' => Your\Custom\Or\Monolog\Handler::class, 68 | 'option' => [ 69 | 'HANDLER_OPTION_KEY' = 'HANDLER_OPTION_VALUE' 70 | ] 71 | ], 72 | ... 73 | ], 74 | 75 | -------------------------------------------------------------------------------- /docs/service-providers/mail.md: -------------------------------------------------------------------------------- 1 | # Mail 2 | 3 | This service provider provided basic send mail function in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Mail\MailServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default mail config like send mail method, server, username, password and port 20 | 21 | vim config/mail.php 22 | 23 | - default send mail method: `sendmail` 24 | 25 | ## Prerequisites 26 | 27 | If you are using the `mailgun` driver, you must install the Mailgun related package first, Please add the following lines to your `compose.json` file 28 | 29 | "mailgun/mailgun-php": "2.6.*", 30 | "php-http/guzzle6-adapter": "1.1.*" 31 | 32 | ## Usage 33 | 34 | You can access the mail service provider by the following code 35 | 36 | **Send mail (one recipient and sender)** 37 | 38 | $this->mail 39 | ->subject('subject') 40 | ->from('email') 41 | ->to('email') 42 | ->body('content') 43 | ->send(); 44 | 45 | **Send mail (one recipient and sender are named)** 46 | 47 | $this->mail 48 | ... 49 | ->from(['email' => 'name']) 50 | ->to(['email' => 'name']) 51 | ... 52 | ->send(); 53 | 54 | **Send mail (many recipient and sender)** 55 | 56 | $this->mail 57 | ... 58 | ->from(['email', 'email']) 59 | ->to(['email', 'email']) 60 | ... 61 | ->send(); 62 | 63 | **Send mail (many recipient and sender are named)** 64 | 65 | $this->mail 66 | ... 67 | ->from(['email' => 'name', 'email' => 'name']) 68 | ->to(['email' => 'name', 'email' => 'name']) 69 | ... 70 | ->send(); 71 | 72 | **Send mail with attachments** 73 | 74 | $this->mail 75 | ... 76 | ... 77 | ->attach(['file_paths', 'file_paths']) 78 | ->send(); 79 | 80 | **Send mail (content is plain text only, default is `text/html`)** 81 | 82 | $this->mail 83 | ... 84 | ... 85 | ->body('content', 'text/plain') 86 | ->send(); 87 | -------------------------------------------------------------------------------- /docs/service-providers/pagination.md: -------------------------------------------------------------------------------- 1 | # Pagination 2 | 3 | Simple pagination service to automate generate navigation links by `Illuminate/Pagination` 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Pagination\PaginationServiceProvider::class, 16 | ... 17 | ] 18 | 19 | ## Usage 20 | 21 | This package mainly provides pagination services for database service providers. 22 | 23 | But you can also use it independently to provide pagination services. 24 | 25 | **Create simple paginator** 26 | 27 | $paginator = $this->paginator->items('[items]')->perPage(1)->currentPage(1)->simple(); 28 | 29 | **Create default paginator** 30 | 31 | $paginator = $this->paginator->items('[items]')->total(5)->perPage(1)->currentPage(1)->default(); 32 | 33 | **Directly create simple pagiantor** 34 | 35 | $paginator = $this->paginator->createSimplePaginator('[items]', 'per_page', 'current_page'); 36 | 37 | **Directly create default pagiantor** 38 | 39 | $paginator = $this->paginator->createDefaultPaginator('[items]', 'total_item', 'per_page', 'current_page'); 40 | 41 | **Render the pagination** 42 | 43 | echo $pagination->render(); 44 | 45 | **Render the pagination with custom view** 46 | 47 | echo $pagination->render('custom_view.html'); 48 | 49 | **Render the pagination with custom view and data** 50 | 51 | echo $pagination->render('custom_view.html', [ 52 | 'name' => 'value' 53 | ]); 54 | 55 | ## Example 56 | 57 | ```php 58 | // Define the pagination related variables 59 | $per_page = 1; 60 | $current_page = isset($_GET['page']) ? $_GET['page'] : 1; 61 | 62 | // Find the offset by pagination variables 63 | $offset = $this->paginator->findOffset($per_page, $current_page); 64 | 65 | // Get total records of the admin table 66 | $total = $this->db->table('admins')->count(); 67 | 68 | // Get the admin records within range 69 | // - generate the default paginator 70 | // - generate the simple paginator 71 | $page_default_admins = $this->db->table('admins')->skip($offset)->take($per_page)->get(); 72 | $page_default_paginate_admins = $this->paginator->items($page_default_admins)->total($total)->perPage($per_page)->currentPage($current_page)->default(); 73 | 74 | $page_simple_admins = $this->db->table('admins')->skip($offset)->take($per_page + 1)->get(); 75 | $page_simple_paginate_admins = $this->paginator->items($page_simple_admins)->perPage($per_page)->currentPage($current_page)->simple(); 76 | 77 | // But you can simplify the above code like this, it will automatically calculate the range value 78 | $page_default_admins = $this->db->table('admins'); 79 | $page_default_paginator = $this->paginator->items($page_default_admins)->total($total)->perPage($per_page)->currentPage($current_page)->default(); 80 | 81 | $page_simple_admins = $this->db->table('admins'); 82 | $page_simple_paginator = $this->paginator->items($page_simple_admins)->perPage($per_page)->currentPage($current_page)->simple(); 83 | 84 | // Finally, you can reading records within loop and render the paginator 85 | foreach($page_default_paginator as $admin) { 86 | print_r($admin); 87 | } 88 | 89 | echo $page_default_paginator->render(); 90 | ``` 91 | 92 | More details or methods, please reference to [`Illuminate/Pagination`](https://laravel.com/api/5.6/Illuminate/Pagination/Paginator.html) 93 | -------------------------------------------------------------------------------- /docs/service-providers/redirection.md: -------------------------------------------------------------------------------- 1 | # Redirection 2 | 3 | This service provider provided redirect action in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Redirection\RedirectionServiceProvider::class, 16 | ... 17 | ] 18 | 19 | ## Usage 20 | 21 | Redirect to path like `/` , `/admin` 22 | 23 | $this->redirect->to('/admin'); 24 | 25 | Redirect to any url like `https://google.com/` 26 | 27 | $this->redirect->away('http://google.com/'); 28 | 29 | set custom type for message 30 | 31 | $this->flash->setTypeMessage('type', 'message'); 32 | 33 | Redirect to named route like `home.index` 34 | 35 | this->redirect->route('home.index'); 36 | 37 | Redirect back to previous page 38 | 39 | $this->redirect->back(); 40 | 41 | Redirect back to previous page with input data 42 | 43 | $this->redirect->back()->withRequestParams(); 44 | 45 | Redirect back to previous page with input data, custom header and so on 46 | 47 | $this->redirect->back()->withRequestParams()->withHeader('X-Hello', 'Params included'); 48 | 49 | The `old_param()` methods can help you to show the previous form input data 50 | 51 | > E.g. The form had validation error, you must redirect back to previous page to show the error message, and the user input must re-populate in form. 52 | 53 | old_param('name') 54 | old_param('name', 'default_value') 55 | 56 | For example, Default show the user inputed data when redirect back was triggered 57 | 58 | {% raw %} 59 | 60 | 61 | {% endraw %} 62 | 63 | Redirect with flash message 64 | 65 | $this->redirect->to('/path/to/page')->withError('message') 66 | $this->redirect->route('page.index')->withMessage('message') 67 | $this->redirect->back()->withTypeMessage('erorr|success|custom', 'message') 68 | -------------------------------------------------------------------------------- /docs/service-providers/session.md: -------------------------------------------------------------------------------- 1 | # Session 2 | 3 | This service provider provided basic session management function in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Session\SessionServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default session config like store name, lifetime, path and so on 20 | 21 | vim config/session.php 22 | 23 | - default name: `_sk` 24 | - default lifetime: `7200` second (= `2` hours) 25 | 26 | ## Usage 27 | 28 | You can access the session service provider by the following code 29 | 30 | **Set key and value** 31 | 32 | $this->session->set('key', 'value') 33 | 34 | **Get value** 35 | 36 | $this->session->get('key') 37 | 38 | **Check the value is or not exists** 39 | 40 | $this->session->has('key2') 41 | 42 | **Remove value** 43 | 44 | remove this value first before retrieve and reutrn value 45 | 46 | $this->session->remove('key') 47 | 48 | **Pop value** 49 | 50 | retrieve this value first, then delete it and return the retrieved value 51 | 52 | $this->session->pop('key'); 53 | 54 | **Push value to array item** 55 | 56 | the key must not exist 57 | 58 | $this->session->push('key3', 'a'); // return value: ['a'] 59 | $this->session->push('key3', 'b'); // return value: ['a', 'b'] 60 | $this->session->push('key3', 'c'); // return value: ['a', 'b', 'c'] 61 | 62 | **Pull value from array item** 63 | 64 | $this->session->pull('key3'); // return value: c 65 | $this->session->pull('key3'); // return value: b 66 | $this->session->pull('key3'); // return value: a 67 | 68 | **Custom segment scope, like** 69 | 70 | $this->session->segment('scope')->set('key', 'value'); 71 | $this->session->segment('scope')->get('key'); 72 | -------------------------------------------------------------------------------- /docs/service-providers/validation.md: -------------------------------------------------------------------------------- 1 | # Validation 2 | 3 | This service provider to provide `Respect` validation service in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\Validation\ValidationServiceProvider::class, 16 | ... 17 | ] 18 | 19 | ## Usage 20 | 21 | First, you need to import the validation rule namespace to create your rule statement 22 | 23 | use Slimork\Providers\Validation\Rule; 24 | 25 | 26 | And then, you can get the validator object from the service provider in any controller 27 | 28 | $validator = $this->validator; 29 | 30 | Now, add rule for request paramters 31 | 32 | $validator->validators($request->getParams(), [ 33 | 'username' => Rule::notEmpty()->noWhitespace()->length(4, 30), 34 | 'password' => Rule::notEmpty()->length(8, 30), 35 | ]); 36 | 37 | If you need to custom the translations, you can using the third arguments like 38 | 39 | $validator->validators($request->getParams(), [ 40 | 'username' => Rule::notEmpty()->noWhitespace()->length(4, 30), 41 | 'password' => Rule::notEmpty()->length(8, 30), 42 | ], [ 43 | 'username.notEmpty' => "The {{name}} is empty", 44 | 'username.length' => "The {{name}} must have a length between {{minValue}} and {{maxValue}}" 45 | ]); 46 | 47 | Finally, you can call the `fails()` method to check is or not passed, `errors()` method to get all errors and `firstError()` method to get fisrt error message 48 | 49 | if ($validator->fails() === true) { 50 | // Format like: [ 'username' => ['notEmpty' => 'message', ...] , 'password' => ['notEmpty' => 'message', ...] ] 51 | $errors = $validator->errors(); 52 | 53 | // Format like: ['notEmpty' => 'message', 'length' => 'message'] 54 | $errors = $validator->errors('username'); 55 | 56 | // The top of error message in errors stack 57 | $error = $validator->firstError(); 58 | }else{ 59 | ... 60 | ... 61 | } 62 | -------------------------------------------------------------------------------- /docs/service-providers/view.md: -------------------------------------------------------------------------------- 1 | # View 2 | 3 | This service provider can provider `Twig` template engine in the application 4 | 5 | ## Installation 6 | 7 | 1. Open the default application config file named `app.php` 8 | 9 | vim config/app.php 10 | 11 | 2. Add/Enable the following line 12 | 13 | 'providers' => [ 14 | ... 15 | Slimork\Providers\View\ViewServiceProvider::class, 16 | ... 17 | ] 18 | 19 | 3. Edit the default view config like default charset, auto reload status and so on 20 | 21 | vim config/view.php 22 | 23 | - default cache path: `/storage/cache/views` 24 | 25 | ## Usage 26 | 27 | You can access the view service provider by the following code 28 | 29 | $this->view->render('view.html'); 30 | $this->view->render('view.html', compact('variable')); 31 | 32 | In the controller, it can access by the following code 33 | 34 | $this->render('view.html'); 35 | $this->render('view.html', compact('variable')); 36 | 37 | ## Extensions 38 | 39 | This view service provider was providered base default extensions. 40 | 41 | If you want to add your custom extension, please add the extension in the view config (`config/view.php`) like 42 | 43 | 'extensions' => [ 44 | Slimork\Providers\View\DefaultViewExtension::class, 45 | ... 46 | Your\Custom\View\Extension\MyCustomViewExtension::class 47 | ... 48 | ] 49 | 50 | The custom extension may like 51 | 52 | loadBeforeBootstrappers(); 16 | $app->loadAppCore(); 17 | $app->loadAfterBootstrappers(); 18 | $app->loadRoutes(); 19 | 20 | $config = $app->getContainer()->get('settings'); 21 | 22 | // Initial 23 | date_default_timezone_set($config['app']['timezone']); 24 | 25 | // Database 26 | $databaseConfig = $config['database']; 27 | $databaseConnections = $databaseConfig['connections']; 28 | $defaultConnection = $databaseConnections[$databaseConfig['default']]; 29 | 30 | $capsule = new Capsule; 31 | 32 | foreach($databaseConnections as $name => $connection) { 33 | $capsule->addConnection( 34 | $connection, 35 | (strtolower($databaseConfig['default']) == $name) ? "default" : $name 36 | ); 37 | } 38 | 39 | $capsule->setAsGlobal(); 40 | $capsule->bootEloquent(); 41 | 42 | // Return 43 | return [ 44 | 'paths' => [ 45 | 'migrations' => BASE_ROOT.'/database/migrations', 46 | 'seeds' => BASE_ROOT.'/database/seeds' 47 | ], 48 | 'migration_base_class' => Simork\Contracts\Migration::class, 49 | 'environments' => [ 50 | 'default_migration_table' => $defaultConnection['prefix'].$databaseConfig['migration']['table'], 51 | 'default_database' => 'default', 52 | 'default' => [ 53 | 'connection' => $capsule->getConnection()->getPdo(), 54 | 'name' => $defaultConnection['database'], 55 | 'table_prefix' => $defaultConnection['prefix'] 56 | ] 57 | ], 58 | ]; 59 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | loadBeforeBootstrappers(); 21 | $app->loadAppCore(); 22 | $app->loadAfterBootstrappers(); 23 | $app->loadRoutes(); 24 | $app->run(); 25 | -------------------------------------------------------------------------------- /resources/views/errors/400.csrf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 400 - Bad Request - Csrf 6 | 7 | 8 | 38 | 39 |
40 |
41 |
42 | 400 Csrf.... 43 |
44 | 47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/views/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 - Page not found 6 | 7 | 8 | 38 | 39 |
40 |
41 |
42 | 404 .... 43 |
44 | 47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/views/errors/405.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 405 - Method not allowed 6 | 7 | 8 | 38 | 39 |
40 |
41 |
42 | 405 .... 43 |
44 | 47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/views/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 - Internet server error (Normal) 6 | 7 | 8 | 38 | 39 |
40 |
41 |
42 | 500 normal.... 43 |
44 | 47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/views/errors/500.php.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 - Internet server error (Code) 6 | 7 | 8 | 38 | 39 |
40 |
41 |
42 | 500 code.... 43 |
44 | 47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /resources/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Slimork 6 | 7 | 8 | 35 | 36 |
37 |
38 |
39 | Slimork 40 |
41 |
42 | Simple way to do your work 43 |
44 |
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /resources/views/paginations/default.html: -------------------------------------------------------------------------------- 1 | {% if (paginator.hasPages()) %} 2 | 31 | {% endif %} 32 | -------------------------------------------------------------------------------- /resources/views/paginations/default.simple.html: -------------------------------------------------------------------------------- 1 | {% if (paginator.hasPages()) %} 2 | 23 | {% endif %} 24 | -------------------------------------------------------------------------------- /slimork/Contracts/Controller.php: -------------------------------------------------------------------------------- 1 | container = $container; 12 | } 13 | 14 | public function __get($name) { 15 | return $this->container->get($name); 16 | } 17 | 18 | /** 19 | * Usage 20 | * ===== 21 | * 22 | * View: 23 | * 24 | * $this->view('template.html'); 25 | * $this->view('template.html', compact('variable1', 'variable2')); 26 | */ 27 | protected function view($view, array $arguments = []) { 28 | $response = $this->view->render($view, $arguments); 29 | 30 | return $response; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /slimork/Contracts/ExceptionHandler.php: -------------------------------------------------------------------------------- 1 | app = $app; 13 | $this->container = $app->getContainer(); 14 | } 15 | 16 | abstract public function register(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /slimork/Contracts/Hasher.php: -------------------------------------------------------------------------------- 1 | settings = $settings; 10 | } 11 | 12 | public function password_info($value) { 13 | return password_get_info($value); 14 | } 15 | 16 | abstract public function make($value, array $options = []); 17 | abstract public function check($value, $hashed_value); 18 | abstract public function needsRehash($hashed_value, array $options = []); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /slimork/Contracts/Middleware.php: -------------------------------------------------------------------------------- 1 | app = $app; 13 | $this->container = $app->getContainer(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /slimork/Contracts/Migration.php: -------------------------------------------------------------------------------- 1 | schema = Capsule::schema(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /slimork/Contracts/Model.php: -------------------------------------------------------------------------------- 1 | app = $app; 13 | $this->container = $app->getContainer(); 14 | } 15 | 16 | // Optional, After service provider was registered, this method will triggered 17 | public function boot() { 18 | } 19 | 20 | abstract function register(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /slimork/Contracts/ViewExtension.php: -------------------------------------------------------------------------------- 1 | container = $container; 12 | } 13 | 14 | public function getFilters() { 15 | return [ 16 | // new Twig_SimpleFilter('name', [$this, 'method']), 17 | ]; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /slimork/Exceptions/Handlers/ErrorHandler.php: -------------------------------------------------------------------------------- 1 | container->get('settings'); 10 | 11 | if ($settings['displayErrorDetails'] === false) { 12 | $this->container->set('errorHandler', function($c) { 13 | return function($request, $response, $exception) use ($c) { 14 | // Write to log file 15 | if ($c->has('log') === true) { 16 | $c->get('log')->error($exception); 17 | } 18 | 19 | // Render error page 20 | $content = render_error('500.html'); 21 | 22 | return $response 23 | ->withStatus(500) 24 | ->withHeader('Content-Type', 'text/html') 25 | ->write($content); 26 | }; 27 | }); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /slimork/Exceptions/Handlers/NotAllowedHandler.php: -------------------------------------------------------------------------------- 1 | container->set('notAllowedHandler', function($c) { 10 | return function($request, $response, $methods) use ($c) { 11 | $content = render_error('405.html'); 12 | 13 | return $response 14 | ->withStatus(405) 15 | ->withHeader('Allow', implode(', ', $methods)) 16 | ->withHeader('Content-Type', 'text/html') 17 | ->write($content); 18 | }; 19 | }); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /slimork/Exceptions/Handlers/NotFoundHandler.php: -------------------------------------------------------------------------------- 1 | container->set('notFoundHandler', function($c) { 10 | return function($request, $response) use ($c) { 11 | $content = render_error('404.html'); 12 | 13 | return $response 14 | ->withStatus(404) 15 | ->withHeader('Content-Type', 'text/html') 16 | ->write($content); 17 | }; 18 | }); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /slimork/Exceptions/Handlers/PhpErrorHandler.php: -------------------------------------------------------------------------------- 1 | container->get('settings'); 10 | 11 | if ($settings['displayErrorDetails'] === false) { 12 | $this->container->set('phpErrorHandler', function($c) { 13 | return function($request, $response, $error) use ($c) { 14 | // Write to log file 15 | if ($c->has('log') === true) { 16 | $c->get('log')->error($error); 17 | } 18 | 19 | // Render error page 20 | $content = render_error('500.php.html'); 21 | 22 | return $response 23 | ->withStatus(500) 24 | ->withHeader('Content-Type', 'text/html') 25 | ->write($content); 26 | }; 27 | }); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /slimork/Facades/App.php: -------------------------------------------------------------------------------- 1 | getContainer(); 13 | 14 | return static::$fadeInstances[$name]; 15 | } 16 | 17 | public static function getFacadeAccessor() { 18 | return 'container'; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /slimork/Facades/Cookie.php: -------------------------------------------------------------------------------- 1 | getContainer()->get($name); 39 | 40 | return static::$fadeInstances[$name]; 41 | } 42 | 43 | public static function __callStatic($method, $args) { 44 | $instance = static::getFacadeRoot(); 45 | 46 | return $instance->$method(...$args); 47 | } 48 | 49 | public static function getFacadeAccessor() { 50 | throw new \RuntimeException('The facade object must implement getFacadeAccessor method.'); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /slimork/Facades/Flash.php: -------------------------------------------------------------------------------- 1 | getContainer()->get('settings'); 12 | $new_settings = array_merge($old_settings, [ 13 | $key => $value 14 | ]); 15 | 16 | static::$app->getContainer()->set('settings', $new_settings); 17 | 18 | return $new_settings; 19 | } 20 | 21 | public static function get($key, $default = null) { 22 | $settings = static::$app->getContainer()->get('settings'); 23 | 24 | return array_key_exists($key, $settings) === true ? $settings[$key] : $default; 25 | } 26 | 27 | public static function all() { 28 | return static::$app->getContainer()->get('settings'); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /slimork/Facades/Validator.php: -------------------------------------------------------------------------------- 1 | Namespace\Path\To\Database::class])->register(); 11 | */ 12 | class AliasLoader { 13 | 14 | protected static $instance = null; 15 | 16 | protected $aliases; 17 | 18 | protected $registered = false; 19 | 20 | public function __construct(array $aliases = []) { 21 | $this->aliases = $aliases; 22 | } 23 | 24 | public static function getInstance(array $aliases = []) { 25 | if (static::$instance === null) { 26 | return static::$instance = new static($aliases); 27 | } 28 | 29 | static::$instance->setAliases($aliases); 30 | 31 | return static::$instance; 32 | } 33 | 34 | public function setAliases(array $aliases) { 35 | $this->aliases = $aliases; 36 | } 37 | 38 | public function register() { 39 | if ($this->registered === false) { 40 | $this->prependToAutoloader(); 41 | $this->registered = true; 42 | } 43 | } 44 | 45 | protected function prependToAutoloader() { 46 | spl_autoload_register([$this, 'load'], true, true); 47 | } 48 | 49 | public function load($alias) { 50 | if (isset($this->aliases[$alias]) === true) { 51 | return class_alias($this->aliases[$alias], $alias); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /slimork/Foundation/App.php: -------------------------------------------------------------------------------- 1 | addDefinitions($this->settings); 33 | } 34 | 35 | // Loaders 36 | public function loadBeforeBootstrappers() { 37 | foreach($this->before_bootstrappers as $bootstrapper) { 38 | (new $bootstrapper())->bootstrap($this); 39 | } 40 | } 41 | 42 | public function loadAppCore() { 43 | parent::__construct(); 44 | } 45 | 46 | public function loadAfterBootstrappers() { 47 | foreach($this->after_bootstrappers as $bootstrapper) { 48 | (new $bootstrapper())->bootstrap($this); 49 | } 50 | } 51 | 52 | public function loadRoutes() { 53 | // expose the $app object 54 | $app = $this; 55 | 56 | require_once APP_ROOT.'/routes.php'; 57 | } 58 | 59 | // Helpers 60 | public function setSettings(array $settings) { 61 | $this->settings = $settings; 62 | } 63 | 64 | public function getSettings() { 65 | return $this->settings; 66 | } 67 | 68 | public function getSetting($name) { 69 | $settings = $this->getContainer()->get('settings'); 70 | 71 | if (array_key_exists($name, $settings) === true) { 72 | return $settings[$name]; 73 | }else{ 74 | return []; 75 | } 76 | } 77 | 78 | public function getBeforeBootstrappers() { 79 | return $this->before_bootstrappers; 80 | } 81 | 82 | public function setBeforeBootstrappers(array $bootstrappers) { 83 | $this->before_bootstrappers = $bootstrappers; 84 | } 85 | 86 | public function getAfterBootstrappers() { 87 | return $this->after_bootstrappers; 88 | } 89 | 90 | public function setAfterBootstrappers(array $bootstrappers) { 91 | $this->after_bootstrappers = $bootstrappers; 92 | } 93 | 94 | public function getEnvironmentPath() { 95 | return $this->environment_path ?? BASE_ROOT; 96 | } 97 | 98 | public function setEnvironmentPath($path) { 99 | $this->environment_path = $path; 100 | } 101 | 102 | public function getEnvironmentFile() { 103 | return $this->environment_file ?? '.env'; 104 | } 105 | 106 | public function setEnvironmentFile($file) { 107 | $this->environment_file = $file; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/Base/LoadEnvironmentVariables.php: -------------------------------------------------------------------------------- 1 | setSpecificEnvironmentFile($app); 13 | 14 | try { 15 | (Dotenv::create( 16 | $app->getEnvironmentPath(), 17 | $app->getEnvironmentFile() 18 | ))->load(); 19 | } catch (InvalidPathException $e) { 20 | // Nothing to do, if not found .env in specified path, it will using the default settings file 21 | } catch (InvalidFileException $e) { 22 | exit('The environment file is invalid: '.$e->getMessage()); 23 | } 24 | } 25 | 26 | public function setSpecificEnvironmentFile(App $app) { 27 | $app_env = env('APP_ENV'); 28 | 29 | if ($app_env !== null) { 30 | // Like: .env.production / .env.local 31 | $app->setEnvironmentFile($app->getEnvironmentFile().'.'.$app_env); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/Base/LoadSettings.php: -------------------------------------------------------------------------------- 1 | $slim_config 12 | ]; 13 | 14 | // Merge all config in settings namespace 15 | foreach(glob(CONFIG_ROOT."/*.php") as $file_path) { 16 | $file_name = basename($file_path, ".php"); 17 | 18 | if ($file_name !== 'slim') { 19 | $final_config['settings'][$file_name] = require_once $file_path; 20 | } 21 | } 22 | 23 | // Make the slim config in global with `settings` prefix 24 | foreach($slim_config as $name => $value) { 25 | $final_config['settings.'.$name] = $value; 26 | } 27 | 28 | date_default_timezone_set($final_config['settings']['app']['timezone']); 29 | 30 | $app->setSettings($final_config); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/BuiltIn/RegisterFacades.php: -------------------------------------------------------------------------------- 1 | getSetting('app')['aliases'])->register(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/BuiltIn/RegisterHandlers.php: -------------------------------------------------------------------------------- 1 | getSetting('app')['handlers'] as $handler) { 10 | $handler = new $handler($app); 11 | $handler->register(); 12 | } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/BuiltIn/RegisterMiddlewares.php: -------------------------------------------------------------------------------- 1 | getSetting('app')['middlewares'] as $middleware) { 10 | $app->add(new $middleware($app)); 11 | } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /slimork/Foundation/Bootstrappers/BuiltIn/RegisterServiceProviders.php: -------------------------------------------------------------------------------- 1 | getSetting('app')['providers'] as $provider) { 12 | $provider = new $provider($app); 13 | $provider->register(); 14 | 15 | array_push($providers, $provider); 16 | } 17 | 18 | foreach($providers as $provider) { 19 | $provider->boot(); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /slimork/Foundation/Http/FormRequest.php: -------------------------------------------------------------------------------- 1 | Rule::notEmpty()->noWhitespace()->length(4, 30), 25 | * 'password' => Rule::notEmpty()->length(8, 30), 26 | * ]; 27 | * } 28 | * 29 | * public function messages() { 30 | * return []; 31 | * } 32 | * 33 | * } 34 | * 35 | * File: app\Controllers\HomeController.php 36 | * 37 | * class HomeController extends Controller { 38 | * 39 | * public function test(LoginRequest $loginRequest) { 40 | * dd( 41 | * $loginRequest->getParams() 42 | * ); 43 | * } 44 | * 45 | * } 46 | * 47 | */ 48 | abstract class FormRequest extends SlimRequest { 49 | 50 | protected $container; 51 | 52 | public function __construct(Container $container) { 53 | $environment = $container->get('environment'); 54 | 55 | // Re-create the environment 56 | $method = $environment['REQUEST_METHOD']; 57 | $uri = Uri::createFromEnvironment($environment); 58 | $headers = Headers::createFromEnvironment($environment); 59 | $cookies = Cookies::parseHeader($headers->get('Cookie', [])); 60 | $serverParams = $environment->all(); 61 | $body = new RequestBody(); 62 | $uploadedFiles = UploadedFile::createFromEnvironment($environment); 63 | 64 | parent::__construct($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); 65 | 66 | // Handle the post action 67 | $has_form_data = in_array($this->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data']); 68 | 69 | if ($method === 'POST' && $has_form_data === true) { 70 | $this->withParsedBody($_POST); 71 | } 72 | 73 | // Set the container 74 | $this->container = $container; 75 | 76 | // Validate the form data 77 | $this->validate(); 78 | } 79 | 80 | public function validate() { 81 | if ($this->container->has('validator') === false) { 82 | throw new RuntimeException("The validation service provider does not exists"); 83 | } 84 | 85 | if ($this->container->has('redirect') === false) { 86 | throw new RuntimeException("The redirection service provider does not exists"); 87 | } 88 | 89 | // 90 | $validator = $this->container->get('validator'); 91 | $redirect = $this->container->get('redirect'); 92 | 93 | // 94 | $validator->validators($this->getParams(), $this->rules(), $this->messages()); 95 | 96 | if ($validator->fails() === true) { 97 | $response = $redirect->back()->withRequestParams()->withError($validator->firstError()); 98 | 99 | if (headers_sent() === false) { 100 | foreach ($response->getHeaders() as $name => $values) { 101 | foreach ($values as $value) { 102 | header(sprintf('%s: %s', $name, $value), false); 103 | } 104 | } 105 | 106 | header(sprintf( 107 | 'HTTP/%s %s %s', 108 | $response->getProtocolVersion(), 109 | $response->getStatusCode(), 110 | $response->getReasonPhrase() 111 | )); 112 | 113 | exit; 114 | } 115 | } 116 | } 117 | 118 | // 119 | public function all() { 120 | return $this->getParams(); 121 | } 122 | 123 | public function only($keys) { 124 | $keys = is_array($keys) === true ? $keys : func_get_args(); 125 | 126 | return array_intersect_key( 127 | $this->getParams(), 128 | array_flip($keys) 129 | ); 130 | } 131 | 132 | public function except($keys) { 133 | $keys = is_array($keys) === true ? $keys : func_get_args(); 134 | 135 | return array_diff_key( 136 | $this->getParams(), 137 | array_flip($keys) 138 | ); 139 | } 140 | 141 | // 142 | public function rules() { 143 | throw new \RuntimeException('The FormRequest object must implement rules method.'); 144 | } 145 | 146 | public function messages() { 147 | throw new \RuntimeException('The FormRequest object must implement messages method.'); 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /slimork/Middlewares/Route/DefaultMiddleware.php: -------------------------------------------------------------------------------- 1 | container = $container; 14 | $this->cookie = $_COOKIE; 15 | } 16 | 17 | public function set($name, $value, $options = []) { 18 | $options = array_merge([ 19 | 'expires' => new DateTime('+1 hours'), 20 | 'path' => '/', 21 | 'domain' => null, 22 | 'secure' => false, 23 | 'http_only' => true, 24 | ], $this->container->get('settings')['cookie'], $options); 25 | 26 | if ($options['expires'] instanceof DateTime) { 27 | $options['expires'] = $options['expires']->getTimestamp(); 28 | } 29 | 30 | setcookie( 31 | $name, $value, 32 | $options['expires'], $options['path'], $options['domain'], $options['secure'], $options['http_only'] 33 | ); 34 | } 35 | 36 | public function has($name) { 37 | return array_key_exists($name, $_COOKIE); 38 | } 39 | 40 | public function get($name, $default = null) { 41 | return $this->has($name) === true ? $_COOKIE[$name] : $default; 42 | } 43 | 44 | public function remove($name) { 45 | if ($this->has($name) === true) { 46 | unset($_COOKIE[$name]); 47 | 48 | $this->set($name, "", [ 49 | 'expires' => new DateTime('-10 years') 50 | ]); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /slimork/Providers/Cookie/CookieServiceProvider.php: -------------------------------------------------------------------------------- 1 | cookie->set('name', 'value'); 14 | * $this->cookie->set('name', 'value', [option]); 15 | * 16 | * # Get cookie 17 | * $this->cookie->get('name'); 18 | * 19 | * # Remove cookie 20 | * $this->cookie->remove('name'); 21 | * 22 | * # Is value exists or not 23 | * $this->cookie->has('name'); 24 | */ 25 | class CookieServiceProvider extends ServiceProvider { 26 | 27 | public function register() { 28 | $this->container->set('cookie', function($container) { 29 | return new Cookie($container); 30 | }); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /slimork/Providers/Csrf/Csrf.php: -------------------------------------------------------------------------------- 1 | request = parent::generateNewToken($request); 16 | 17 | return $this->request; 18 | } 19 | 20 | public function setStrength($length = 16) { 21 | $this->strength = $length; 22 | } 23 | 24 | public function getTokens() { 25 | $token_name_key = $this->getTokenNameKey(); 26 | $token_value_key = $this->getTokenValueKey(); 27 | 28 | $csrf = [ 29 | $token_name_key => $this->request->getAttribute($token_name_key), 30 | $token_value_key => $this->request->getAttribute($token_value_key) 31 | ]; 32 | 33 | return $csrf; 34 | } 35 | 36 | public function getTokenForHiddenInputTags() { 37 | $html = []; 38 | 39 | foreach($this->getTokens() as $name => $value) { 40 | array_push($html, sprintf("", $name, $value)); 41 | } 42 | 43 | return join("\n", $html); 44 | } 45 | 46 | public function getTokenForMetaTags() { 47 | $html = []; 48 | 49 | foreach($this->getTokens() as $name => $value) { 50 | array_push($html, sprintf("", $name, $value)); 51 | } 52 | 53 | return join("\n", $html); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /slimork/Providers/Csrf/CsrfServiceProvider.php: -------------------------------------------------------------------------------- 1 | csrf->getTokenForHiddenInputTags(); 18 | * $tags = $this->csrf->getTokenForMetaTags(); 19 | * 20 | * # View 21 | * {{ tags | raw }} 22 | * 23 | * Advanace (without controller, the view has global csrf, csrf_metas, csrf_tags variable) 24 | * 25 | * {{ csrf }} 26 | * 27 | * 28 | * 29 | * {{ csrf_metas }} 30 | * 31 | * 32 | * 33 | * {{ csrf_tags }} 34 | * 35 | * 36 | * 37 | * Other pass token to view for custom 38 | * 39 | * # Controller 40 | * $csrf_tokens = $this->csrf->getTokens(); 41 | * 42 | * # View 43 | * {% for name, value in csrf_tokens %} 44 | * 45 | * {% endfor %} 46 | * 47 | * {% for name, value in csrf_tokens %} 48 | * 49 | * {% endfor %} 50 | */ 51 | class CsrfServiceProvider extends ServiceProvider { 52 | 53 | public function register() { 54 | $this->container->set('csrf', function($container) { 55 | $settings = $container->get('settings'); 56 | $csrf = $settings['csrf']; 57 | 58 | $guard = new Csrf($csrf['prefix']); 59 | $guard->setStrength($csrf['strength']); 60 | 61 | return $guard; 62 | }); 63 | } 64 | 65 | public function boot() { 66 | $this->container->get('csrf')->setFailureCallable(function(Request $request, Response $response, $next) { 67 | $headers = $request->getHeaders(); 68 | $referers = array_key_exists('HTTP_REFERER', $headers) === true ? $headers['HTTP_REFERER'] : []; 69 | $referer = empty($referers) === true ? '/' : current($referers); 70 | 71 | $content = render_error('400.csrf.html', compact('referer')); 72 | 73 | return $response 74 | ->withStatus(400) 75 | ->withHeader('Content-Type', 'text/html') 76 | ->write($content); 77 | }); 78 | 79 | // 80 | $settings = $this->container->get('settings'); 81 | 82 | if ($settings['csrf']['global'] === true) { 83 | $this->app->add($this->container->get('csrf')); 84 | } 85 | 86 | // 87 | if ($this->container->has('view') === true) { 88 | $this->container->get('view')->addExtension(new ViewExtension($this->container)); 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /slimork/Providers/Csrf/ViewExtension.php: -------------------------------------------------------------------------------- 1 | 19 | * 20 | * 21 | * # csrf_metas 22 | * 23 | * 24 | * 25 | * # csrf_tags 26 | * 27 | * 28 | * 29 | */ 30 | public function getGlobals() { 31 | $csrf = $this->container->get('csrf'); 32 | 33 | $csrf_name_key = $csrf->getTokenNameKey(); 34 | $csrf_value_key = $csrf->getTokenValueKey(); 35 | 36 | $csrf_name = $csrf->getTokenName($csrf_name_key); 37 | $csrf_value = $csrf->getTokenValue($csrf_value_key); 38 | 39 | return [ 40 | 'csrf' => [ 41 | 'keys' => [ 42 | 'name' => $csrf_name_key, 43 | 'value' => $csrf_value_key 44 | ], 45 | 'name' => $csrf_name, 46 | 'value' => $csrf_value 47 | ], 48 | 49 | 'csrf_metas' => new \Twig_Markup($csrf->getTokenForMetaTags(), 'UTF-8'), 50 | 'csrf_tags' => new \Twig_Markup($csrf->getTokenForHiddenInputTags(), 'UTF-8'), 51 | ]; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /slimork/Providers/Database/DatabaseManager.php: -------------------------------------------------------------------------------- 1 | container['config']['database.default'] = $name; 11 | } 12 | 13 | // Select in raw sql statement and only return first row like 14 | public function fetchOneRaw($sql) { 15 | $connection = $this->getConnection(); 16 | 17 | return collect($connection->select( 18 | $connection->raw($sql) 19 | ))->first(); 20 | } 21 | 22 | // 23 | public function __call($method, $arguments) { 24 | // dd('abc'); 25 | return $this->getConnection()->$method(...$arguments); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /slimork/Providers/Database/DatabaseServiceProvider.php: -------------------------------------------------------------------------------- 1 | db->table('user')->find(1); 18 | * 19 | * # Other connection 20 | * $this->db->getConnection('connection')->table('user')->find(1) 21 | * 22 | * Model: 23 | * 24 | * $user = User::find(1); 25 | * $user = User::on('connection')->find(1); 26 | * 27 | * Paginate: 28 | * 29 | * $user = User::paginate(1); 30 | * 31 | * echo $paginate->render(); 32 | * 33 | * Other: 34 | * 35 | * # Return the first row like { total: 1 } 36 | * $this->db->fetchOneRaw("SELECT COUNT(*) AS total FROM table"); 37 | * 38 | */ 39 | class DatabaseServiceProvider extends ServiceProvider { 40 | 41 | public function register() { 42 | // Setup capsule manager 43 | $settings = $this->container->get('settings'); 44 | 45 | // 46 | $capsule = new DatabaseManager; 47 | $capsule->setDefaultConnection($settings['database']['default']); 48 | 49 | foreach($settings['database']['connections'] as $name => $database) { 50 | $capsule->addConnection($database, $name); 51 | } 52 | 53 | $capsule->setAsGlobal(); 54 | $capsule->setEventDispatcher(new Dispatcher()); 55 | $capsule->bootEloquent(); 56 | 57 | // Setup db service provider 58 | $this->container->set('db', function() use ($capsule) { 59 | return $capsule; 60 | }); 61 | 62 | $this->container->set('db.connection', function() use ($capsule) { 63 | return $capsule->getConnection(); 64 | }); 65 | } 66 | 67 | public function boot() { 68 | if ($this->container->has('paginator') === false) { 69 | $settings = $this->container->get('settings'); 70 | $request = $this->container->get('request'); 71 | 72 | // Get current url and page no 73 | $query_pairs = []; 74 | 75 | parse_str($request->getUri()->getQuery(), $query_pairs); 76 | 77 | if (array_key_exists('page', $query_pairs) === true) { 78 | unset($query_pairs['page']); 79 | } 80 | 81 | $query_string = http_build_query($query_pairs); 82 | $current_url = (string) $request->getUri()->withQuery($query_string); 83 | $current_page = $request->getParam('page'); 84 | 85 | // Get template name 86 | $default_template = empty($settings['pagination']['views']['default']) === false ? $settings['pagination']['views']['default'] : 'default.html'; 87 | $simple_template = empty($settings['pagination']['views']['simple']) === false ? $settings['pagination']['views']['simple'] : 'default.simple.html'; 88 | 89 | // Get paginator view object 90 | $pagiantor_view = empty($settings['pagination']['paginator']) === false ? $settings['pagination']['paginator'] : PaginatorView::class; 91 | 92 | // Setup paginator template 93 | Paginator::defaultView($default_template); 94 | Paginator::defaultSimpleView($simple_template); 95 | 96 | // Setup paginator resolver 97 | Paginator::viewFactoryResolver(function() use ($pagiantor_view) { 98 | return new $pagiantor_view($this->container); 99 | }); 100 | 101 | Paginator::currentPathResolver(function () use ($current_url) { 102 | return $current_url; 103 | }); 104 | 105 | Paginator::currentPageResolver(function() use ($current_page) { 106 | return $current_page; 107 | }); 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /slimork/Providers/Database/PaginatorView.php: -------------------------------------------------------------------------------- 1 | get('settings'); 14 | 15 | $loader = new \Twig_Loader_Filesystem(RESOURCES_ROOT.'/views/paginations'); 16 | $twig = new \Twig_Environment($loader, [ 17 | 'charset' => 'utf-8', 18 | 'cache' => false, 19 | 'auto_reload' => true, 20 | 'strict_variables' => false, 21 | 'autoescape' => 'html', 22 | ]); 23 | 24 | if (array_key_exists('view', $settings) === true) { 25 | foreach($settings['view']['extensions'] as $extension) { 26 | $twig->addExtension(new $extension($container)); 27 | } 28 | }else{ 29 | $twig->addTest(new \Twig_SimpleTest('string', function($value) { 30 | return is_string($value); 31 | })); 32 | 33 | $twig->addTest(new \Twig_SimpleTest('array', function($value) { 34 | return is_array($value); 35 | })); 36 | } 37 | 38 | $this->view = $twig; 39 | } 40 | 41 | public function make($view, $data = [], $merge_data = []) { 42 | $this->template = $this->view->load($view); 43 | $this->variables = array_merge($data, $merge_data); 44 | 45 | return $this; 46 | } 47 | 48 | public function render() { 49 | return $this->template->render($this->variables); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /slimork/Providers/Flash/Flash.php: -------------------------------------------------------------------------------- 1 | addMessage($type, $message); 11 | } 12 | 13 | public function getTypeMessage($type) { 14 | $error_messages = $this->getMessage($type); 15 | $first_message = is_array($error_messages) === true ? array_shift($error_messages) : null; 16 | 17 | return $first_message; 18 | } 19 | 20 | // Getter and Setter for error and success messages 21 | public function setError($message = "") { 22 | return $this->setTypeMessage('error', $message); 23 | } 24 | 25 | public function getError() { 26 | return $this->getTypeMessage('error'); 27 | } 28 | 29 | public function setSuccess($message = "") { 30 | return $this->setTypeMessage('success', $message); 31 | } 32 | 33 | public function getSuccess() { 34 | return $this->getTypeMessage('success'); 35 | } 36 | 37 | // Simple method 38 | public function error($message = "") { 39 | if (empty($message) === true) { 40 | return $this->getError(); 41 | } 42 | 43 | $this->setError($message); 44 | } 45 | 46 | public function success($message = "") { 47 | if (empty($message) === true) { 48 | return $this->getSuccess(); 49 | } 50 | 51 | $this->setSuccess($message); 52 | } 53 | 54 | public function has($type) { 55 | return empty($this->getMessage($type)) === false; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /slimork/Providers/Flash/FlashServiceProvider.php: -------------------------------------------------------------------------------- 1 | flash->error('message'); 16 | * $this->flash->success('message'); 17 | * 18 | * # getter and setter methods 19 | * $this->flash->setError('message'); 20 | * $this->flash->setSuccess('message'); 21 | * 22 | * # other methods 23 | * $this->flash->setTypeMessage('type', 'message'); 24 | * 25 | * Get message 26 | * 27 | * # simple method 28 | * $this->flash->error(); 29 | * $this->flash->success(); 30 | * 31 | * # getter and setter methods 32 | * $this->flash->getError(); 33 | * $this->flash->getSuccess(); 34 | * 35 | * # otehr methods 36 | * $this->flash->getTypeMessage('type'); 37 | * 38 | * Other methods 39 | * 40 | * # check the type of message is or not exists 41 | * $this->flash->has('type'); 42 | * 43 | * In view like: 44 | * 45 | * {% if has_flash('error') %} 46 | *
47 | * Error! {{ flash('error') }} 48 | *
49 | * {% endif %} 50 | */ 51 | class FlashServiceProvider extends ServiceProvider { 52 | 53 | public function register() { 54 | $this->container->set('flash', function($container) { 55 | return new Flash(); 56 | }); 57 | } 58 | 59 | public function boot() { 60 | if ($this->container->has('view') === true) { 61 | $this->container->get('view')->addExtension(new ViewExtension($this->container)); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /slimork/Providers/Flash/ViewExtension.php: -------------------------------------------------------------------------------- 1 | 26 | * Error! {{ flash('error') }} 27 | * 28 | * {% endif %} 29 | */ 30 | public function hasFlash($type) { 31 | return $this->container->get('flash')->has($type); 32 | } 33 | 34 | public function flash($type) { 35 | return $this->container->get('flash')->getTypeMessage($type); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /slimork/Providers/Hash/HashManager.php: -------------------------------------------------------------------------------- 1 | container = $container; 16 | $this->settings = $this->container->get('settings'); 17 | } 18 | 19 | public function driver() { 20 | $driver = $this->getDefaultDriver(); 21 | $settings = array_key_exists($driver, $this->settings['hash']) ? $this->settings['hash'][$driver] : []; 22 | 23 | switch($driver) { 24 | case 'bcrypt': 25 | return new BCryptHasher($settings); 26 | break; 27 | case 'argon2': 28 | return new Argon2Hasher($settings); 29 | break; 30 | } 31 | } 32 | 33 | public function make($value, array $options = []) { 34 | return $this->driver()->make($value, $options); 35 | } 36 | 37 | public function check($value, $hashed_value) { 38 | return $this->driver()->check($value, $hashed_value); 39 | } 40 | 41 | public function needsRehash($hashed_value, array $options = []) { 42 | return $this->driver()->needsRehash($hashed_value, $options); 43 | } 44 | 45 | public function getDefaultDriver() { 46 | return $this->settings['hash']['driver'] ?? 'bcrypt'; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /slimork/Providers/Hash/HashServiceProvider.php: -------------------------------------------------------------------------------- 1 | hash->make('string'); 15 | * $this->hash->check('string', 'hashed_string'); 16 | * $this->hash->needsRehash('hashed_string'); 17 | * 18 | * Overwrite default bcrypt options 19 | * 20 | * $this->hash->make('string', ['cost' => 10]); 21 | * $this->hash->needsRehash('hashed_string', ['cost' => 10]); 22 | * 23 | * Overwrite default argon2 options 24 | * 25 | * $this->hash->make('string', [ 26 | * 'memory_cost' => 2046, 27 | * 'threads' => 4, 28 | * 'time_cost' => 4, 29 | * ]); 30 | * 31 | * $this->hash->needsRehash('hashed_string', [ 32 | * 'memory_cost' => 2046, 33 | * 'threads' => 4, 34 | * 'time_cost' => 4, 35 | * ]); 36 | * 37 | */ 38 | class HashServiceProvider extends ServiceProvider { 39 | 40 | public function register() { 41 | $this->container->set('hash', function($container) { 42 | return new HashManager($container); 43 | }); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /slimork/Providers/Hash/Hasher/Argon2Hasher.php: -------------------------------------------------------------------------------- 1 | memory_cost = $this->settings['memory_cost'] ?? $this->memory_cost; 17 | $this->threads = $this->settings['threads'] ?? $this->threads; 18 | $this->time_cost = $this->settings['time_cost'] ?? $this->time_cost; 19 | } 20 | 21 | public function make($value, array $options = []) { 22 | $hash = password_hash($value, PASSWORD_ARGON2I, array_merge([ 23 | 'memory_cost' => $this->memory_cost, 24 | 'threads' => $this->threads, 25 | 'time_cost' => $this->time_cost, 26 | ], $options)); 27 | 28 | if ($hash === false) { 29 | throw new RuntimeException('Cannot using the Argon2 hashing methods'); 30 | } 31 | 32 | return $hash; 33 | } 34 | 35 | public function check($value, $hashed_value) { 36 | $password_info = $this->password_info($hashed_value); 37 | 38 | if ($password_info['algoName'] !== 'argon2i') { 39 | throw new RuntimeException('This password is not encrypt by Argon2 algorithm'); 40 | } 41 | 42 | if (strlen($hashed_value) === 0) { 43 | return false; 44 | }else{ 45 | return password_verify($value, $hashed_value); 46 | } 47 | } 48 | 49 | public function needsRehash($hashed_value, array $options = []) { 50 | return password_needs_rehash($hashed_value, PASSWORD_ARGON2I, array_merge([ 51 | 'memory_cost' => $this->memory_cost, 52 | 'threads' => $this->threads, 53 | 'time_cost' => $this->time_cost, 54 | ], $options)); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /slimork/Providers/Hash/Hasher/BCryptHasher.php: -------------------------------------------------------------------------------- 1 | rounds = $this->settings['rounds'] ?? $this->rounds; 15 | } 16 | 17 | public function make($value, array $options = []) { 18 | $hash = password_hash($value, PASSWORD_BCRYPT, array_merge([ 19 | 'cost' => $this->rounds, 20 | ], $options)); 21 | 22 | if ($hash === false) { 23 | throw new RuntimeException('Cannot using the bcrypt hashing methods'); 24 | } 25 | 26 | return $hash; 27 | } 28 | 29 | public function check($value, $hashed_value) { 30 | $password_info = $this->password_info($hashed_value); 31 | 32 | if ($password_info['algoName'] !== 'bcrypt') { 33 | throw new RuntimeException('This password is not encrypt by Bcrypt algorithm'); 34 | } 35 | 36 | if (strlen($hashed_value) === 0) { 37 | return false; 38 | }else{ 39 | return password_verify($value, $hashed_value); 40 | } 41 | } 42 | 43 | public function needsRehash($hashed_value, array $options = []) { 44 | return password_needs_rehash($hashed_value, PASSWORD_BCRYPT, array_merge([ 45 | 'cost' => $this->rounds, 46 | ], $options)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /slimork/Providers/Log/Handlers/LogHandler.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->settings = $settings; 14 | 15 | // Make sure the level is correct 16 | $monolog_levels = array_keys(MonoLogger::getLevels()); 17 | $settings_level = strtoupper($this->settings['level']); 18 | 19 | if (in_array($settings_level, $monolog_levels) === false) { 20 | $this->settings['level'] = MonoLogger::DEBUG; 21 | } 22 | } 23 | 24 | public function getLevel() { 25 | return $this->settings['level']; 26 | } 27 | 28 | public function getFilename() { 29 | throw new \RuntimeException('The log handler object must implement getFilename method.'); 30 | } 31 | 32 | public function getHandler() { 33 | throw new \RuntimeException('The log handler object must implement getHandler method.'); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /slimork/Providers/Log/Handlers/RotatingFileHandler.php: -------------------------------------------------------------------------------- 1 | settings['path'].'/'.$this->name.'.log'; 12 | } 13 | 14 | public function getHandler() { 15 | $max_file = $this->settings['max_file']; 16 | 17 | $handler = new MonologRotatingFileHandler($this->getFilename(), $max_file, $this->getLevel()); 18 | $handler->setFormatter(new LineFormatter( 19 | LineFormatter::SIMPLE_FORMAT, NormalizerFormatter::SIMPLE_DATE, true, true 20 | )); 21 | 22 | return $handler; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /slimork/Providers/Log/LogServiceProvider.php: -------------------------------------------------------------------------------- 1 | log->debug('message'); 13 | * echo $this->log->info('message'); 14 | * echo $this->log->notice('message'); 15 | * echo $this->log->warn('message'); 16 | * echo $this->log->warning('message'); 17 | * echo $this->log->error('message'); 18 | * echo $this->log->critical('message'); 19 | * echo $this->log->alert('message'); 20 | * echo $this->log->emergency('message'); 21 | * 22 | */ 23 | class LogServiceProvider extends ServiceProvider { 24 | 25 | public function register() { 26 | $this->container->set('log', function($container) { 27 | $settings = $container->get('settings'); 28 | 29 | return new Logger('slimork', $settings['logger']); 30 | }); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /slimork/Providers/Log/Logger.php: -------------------------------------------------------------------------------- 1 | pushProcessor(new $processor); 14 | } 15 | 16 | // Set log handler 17 | foreach($settings['handlers'] as $key => $info) { 18 | $handler_name = $info['handler']; 19 | $handler_options = array_merge($settings, $info['options']); 20 | 21 | $handler = new $handler_name($name.'.'.$key, $handler_options); 22 | 23 | $this->pushHandler($handler->getHandler()); 24 | } 25 | 26 | return $this; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /slimork/Providers/Mail/Mail.php: -------------------------------------------------------------------------------- 1 | get('settings')['mail']; 22 | $services = $container->get('settings')['services']; 23 | 24 | $transport = null; 25 | switch($mail['driver']) { 26 | case 'smtp': 27 | $transport = new Swift_SmtpTransport($mail['host'], $mail['port']); 28 | $transport->setEncryption($mail['encryption']); 29 | $transport->setUsername($mail['username']); 30 | $transport->setPassword($mail['password']); 31 | break; 32 | case 'mailgun': 33 | $transport = new Transport\MailgunTransport( 34 | $services['mailgun']['secret'], 35 | $services['mailgun']['domain'], 36 | $services['mailgun']['endpoint'] ?? null 37 | ); 38 | break; 39 | default: 40 | $transport = new Swift_SendmailTransport($mail['sendmail']); 41 | break; 42 | } 43 | 44 | $this->transport = $transport; 45 | } 46 | 47 | public function subject($subject) { 48 | $this->subject = $subject; 49 | 50 | return $this; 51 | } 52 | 53 | public function from($emails) { 54 | $this->from_emails = $emails; 55 | 56 | return $this; 57 | } 58 | 59 | public function to($emails) { 60 | $this->to_emails = $emails; 61 | 62 | return $this; 63 | } 64 | 65 | public function body($body, $format = 'text/html') { 66 | $this->body = $body; 67 | $this->body_format = $format; 68 | 69 | return $this; 70 | } 71 | 72 | public function attach(array $attachments = []) { 73 | $this->attachments = $attachments; 74 | 75 | return $this; 76 | } 77 | 78 | public function send() { 79 | $message = new Swift_Message($this->subject); 80 | $message->setFrom($this->from_emails); 81 | $message->setTo($this->to_emails); 82 | $message->setBody($this->body, $this->body_format); 83 | 84 | if (empty($this->attachments) === false) { 85 | foreach($this->attachments as $attachment) { 86 | $message->attach( 87 | Swift_Attachment::fromPath($attachment) 88 | ); 89 | } 90 | } 91 | 92 | $mailer = new Swift_Mailer($this->transport); 93 | $result = $mailer->send($message); 94 | 95 | return $result; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /slimork/Providers/Mail/MailServiceProvider.php: -------------------------------------------------------------------------------- 1 | mail->subject('subject')->from('email')->to('email')->body('content')->send(); 13 | * 14 | * $this->mail->subject('subject')->from('email')->to('email')->body('content')->attach('[file_paths]')->send(); 15 | * 16 | * $this->mail->subject('subject')->from('[emails]')->to('[emails]')->body('content')->attach('[file_paths]')->send(); 17 | * 18 | */ 19 | class MailServiceProvider extends ServiceProvider { 20 | 21 | public function register() { 22 | $this->container->set('mail', function($container) { 23 | return new Mail($container); 24 | }); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /slimork/Providers/Mail/Transport/MailgunTransport.php: -------------------------------------------------------------------------------- 1 | key = $key; 15 | $this->domain = $domain; 16 | $this->endpoint = $endpoint ?? 'https://api.mailgun.net'; 17 | } 18 | 19 | protected function formatEmailAddress(array $to_emails) { 20 | return collect($to_emails)->map(function($username, $address) { 21 | return empty($username) === false ? "$username <{$address}>" : $address; 22 | })->values()->implode(','); 23 | } 24 | 25 | // Reference to new doc: https://github.com/mailgun/mailgun-php/blob/master/doc/attachments.md 26 | protected function formatAttachments(array $attachments) { 27 | return collect($attachments)->map(function($attachment) { 28 | return [ 29 | 'filename' => $attachment->getFilename(), 30 | 'fileContent' => $attachment->getBody() 31 | ]; 32 | })->toArray(); 33 | } 34 | 35 | // Implementation 36 | public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) { 37 | if (empty($this->key) === true) { 38 | throw new \RuntimeException('Mailgun secret key cannot be empty'); 39 | } 40 | 41 | $from = $this->formatEmailAddress($message->getFrom()); 42 | $to = $this->formatEmailAddress($message->getTo()); 43 | $subject = $message->getSubject(); 44 | $body = $message->getBody(); 45 | $attachments = $this->formatAttachments($message->getChildren()); 46 | 47 | $params = [ 48 | 'from' => $from, 49 | 'to' => $to, 50 | 'subject' => $subject, 51 | 'text' => $body, 52 | 'html' => $body, 53 | 'attachment' => $attachments, 54 | ]; 55 | 56 | $mailgun = Mailgun::create($this->key, $this->endpoint); 57 | $response = $mailgun->messages()->send($this->domain, $params); 58 | 59 | return $response->getId(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /slimork/Providers/Mail/Transport/Transport.php: -------------------------------------------------------------------------------- 1 | plugins, $plugin); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /slimork/Providers/Pagination/DefaultPaginatorView.php: -------------------------------------------------------------------------------- 1 | get('settings'); 14 | 15 | $loader = new \Twig_Loader_Filesystem(RESOURCES_ROOT.'/views/paginations'); 16 | $twig = new \Twig_Environment($loader, [ 17 | 'charset' => 'utf-8', 18 | 'cache' => false, 19 | 'auto_reload' => true, 20 | 'strict_variables' => false, 21 | 'autoescape' => 'html', 22 | ]); 23 | 24 | if (array_key_exists('view', $settings) === true) { 25 | foreach($settings['view']['extensions'] as $extension) { 26 | $twig->addExtension(new $extension($container)); 27 | } 28 | }else{ 29 | $twig->addTest(new \Twig_SimpleTest('string', function($value) { 30 | return is_string($value); 31 | })); 32 | 33 | $twig->addTest(new \Twig_SimpleTest('array', function($value) { 34 | return is_array($value); 35 | })); 36 | } 37 | 38 | $this->view = $twig; 39 | } 40 | 41 | public function make($view, $data = [], $merge_data = []) { 42 | $this->template = $this->view->load($view); 43 | $this->variables = array_merge($data, $merge_data); 44 | 45 | return $this; 46 | } 47 | 48 | public function render() { 49 | return $this->template->render($this->variables); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /slimork/Providers/Pagination/PaginationServiceProvider.php: -------------------------------------------------------------------------------- 1 | paginator->items('[items]')->perPage(1)->currentPage(1)->simple(); 15 | * 16 | * $paginator->render(); 17 | * 18 | * Create default paginator 19 | * 20 | * $paginator = $this->paginator->items('[items]')->total(5)->perPage(1)->currentPage(1)->default(); 21 | * 22 | * $paginator->render(); 23 | * 24 | * Directly create simple paginaor 25 | * 26 | * $paginator = $this->paginator->createSimplePaginator('[items]', 'per_page', 'current_page'); 27 | * 28 | * $paginator->render(); 29 | * 30 | * Directly create default paginaor 31 | * 32 | * $paginator = $this->paginator->createDefaultPaginator('[items]', 'total_items', 'per_page', 'current_page'); 33 | * 34 | * $paginator->render(); 35 | * 36 | * Other methods like 37 | * 38 | * $paginator->render('custom_view.html', '[data]'); 39 | * $paginator->nextPageUrl(); 40 | * 41 | * Full example 42 | * 43 | * // Define the pagination related variables 44 | * $per_page = 1; 45 | * $current_page = isset($_GET['page']) ? $_GET['page'] : 1; 46 | * 47 | * // Find the offset by pagination variables 48 | * $offset = $this->paginator->findOffset($per_page, $current_page); 49 | * 50 | * // Get total records of the admin table 51 | * $total = $this->db->table('admins')->count(); 52 | * 53 | * // Get the admin records within range 54 | * // - generate the default paginator 55 | * // - generate the simple paginator 56 | * $page_default_admins = $this->db->table('admins')->skip($offset)->take($per_page)->get(); 57 | * $page_default_paginate_admins = $this->paginator->items($page_default_admins)->total($total)->perPage($per_page)->currentPage($current_page)->default(); 58 | * 59 | * $page_simple_admins = $this->db->table('admins')->skip($offset)->take($per_page + 1)->get(); 60 | * $page_simple_paginate_admins = $this->paginator->items($page_simple_admins)->perPage($per_page)->currentPage($current_page)->simple(); 61 | * 62 | * // But you can simplify the above code like this, it will automatically calculate the range value 63 | * $page_default_admins = $this->db->table('admins'); 64 | * $page_default_paginator = $this->paginator->items($page_default_admins)->total($total)->perPage($per_page)->currentPage($current_page)->default(); 65 | * 66 | * $page_simple_admins = $this->db->table('admins'); 67 | * $page_simple_paginator = $this->paginator->items($page_simple_admins)->perPage($per_page)->currentPage($current_page)->simple(); 68 | * 69 | * // Finally, you can reading records with loop and render the paginator 70 | * foreach($page_default_paginator as $admin) { 71 | * print_r($admin); 72 | * } 73 | * 74 | * echo $page_default_paginator->render(); 75 | * 76 | */ 77 | class PaginationServiceProvider extends ServiceProvider { 78 | 79 | public function register() { 80 | $this->container->set('paginator', function($container) { 81 | return new PaginatorManager(); 82 | }); 83 | } 84 | 85 | public function boot() { 86 | $settings = $this->container->get('settings'); 87 | $request = $this->container->get('request'); 88 | 89 | // Get current full url but without &page=xx / ?page=xx keyword 90 | $query_pairs = []; 91 | 92 | parse_str($request->getUri()->getQuery(), $query_pairs); 93 | 94 | if (array_key_exists('page', $query_pairs) === true) { 95 | unset($query_pairs['page']); 96 | } 97 | 98 | $query_string = http_build_query($query_pairs); 99 | $current_url = (string) $request->getUri()->withQuery($query_string); 100 | $current_page = $request->getParam('page'); 101 | 102 | // Setup paginator 103 | PaginatorManager::setDefaultTemplate($settings['pagination']['views']); 104 | PaginatorManager::setDefaultResolver( 105 | new $settings['pagination']['paginator']($this->container), 106 | $current_url, 107 | $current_page 108 | ); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /slimork/Providers/Pagination/Paginator/DefaultPaginator.php: -------------------------------------------------------------------------------- 1 | items = $items; 17 | 18 | return $this; 19 | } 20 | 21 | public function perPage($per_page) { 22 | $this->per_page = $per_page; 23 | 24 | return $this; 25 | } 26 | 27 | public function currentPage($current_page) { 28 | $this->current_page = $current_page; 29 | 30 | return $this; 31 | } 32 | 33 | public function options($options) { 34 | $this->options = $options; 35 | 36 | return $this; 37 | } 38 | 39 | public function total($total) { 40 | $this->total = $total; 41 | 42 | return $this; 43 | } 44 | 45 | // Create default or simple pagiantor 46 | public function default() { 47 | // Calculate the items range when this item is builder object 48 | if ($this->items instanceof Builder) { 49 | $this->items = $this->items->skip( 50 | $this->findOffset($this->per_page, $this->current_page) 51 | )->take($this->per_page)->get(); 52 | } 53 | 54 | return $this->createDefaultPaginator($this->items, $this->total, $this->per_page, $this->current_page, $this->options); 55 | } 56 | 57 | public function simple() { 58 | // Calculate the items range when this item is builder object (+1 for first page can show the next links) 59 | if ($this->items instanceof Builder) { 60 | $this->items = $this->items->skip( 61 | $this->findOffset($this->per_page, $this->current_page) 62 | )->take($this->per_page + 1)->get(); 63 | } 64 | 65 | return $this->createSimplePaginator($this->items, $this->per_page, $this->current_page, $this->options); 66 | } 67 | 68 | // Initial default or simple paginator 69 | public function createDefaultPaginator($items, $total, $per_page, $current_page = null, array $options = []) { 70 | return new Paginator\DefaultPaginator($items, $total, $per_page, $current_page, array_merge([ 71 | 'path' => BasePaginator::resolveCurrentPath(), 72 | ], $options)); 73 | } 74 | 75 | public function createSimplePaginator($items, $per_page, $current_page = null, array $options = []) { 76 | return new Paginator\SimplePaginator($items, $per_page, $current_page, array_merge([ 77 | 'path' => BasePaginator::resolveCurrentPath(), 78 | ], $options)); 79 | } 80 | 81 | // Other helpers 82 | public function findOffset($per_page, $current_page) { 83 | return ($current_page - 1) * $per_page; 84 | } 85 | 86 | // Initial parent paginator default views and resolver 87 | public static function setDefaultTemplate($views) { 88 | BasePaginator::defaultView($views['default']); 89 | BasePaginator::defaultSimpleView($views['simple']); 90 | } 91 | 92 | public static function setDefaultResolver($viewFactory, $currentPath, $currentPage) { 93 | BasePaginator::viewFactoryResolver(function() use ($viewFactory) { 94 | return $viewFactory; 95 | }); 96 | 97 | BasePaginator::currentPathResolver(function() use ($currentPath) { 98 | return $currentPath; 99 | }); 100 | 101 | BasePaginator::currentPageResolver(function() use ($currentPage) { 102 | return $currentPage; 103 | }); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /slimork/Providers/Pagination/Traits/PaginatorOffset.php: -------------------------------------------------------------------------------- 1 | currentPage - 1) * $this->perPage; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/Http/Response.php: -------------------------------------------------------------------------------- 1 | redirector = $redirector; 14 | 15 | return $this; 16 | } 17 | 18 | public function setRequest($request) { 19 | $this->request = $request; 20 | 21 | return $this; 22 | } 23 | 24 | public function setFlash($flash) { 25 | $this->flash = $flash; 26 | 27 | return $this; 28 | } 29 | 30 | public function withRequestParams($params = []) { 31 | $this->redirector->setRequestParams( 32 | empty($params) === false ? $params : $this->request->getParams() 33 | ); 34 | 35 | return $this; 36 | } 37 | 38 | public function withError($error) { 39 | $this->flash->setError($error); 40 | 41 | return $this; 42 | } 43 | 44 | public function withSuccess($message) { 45 | $this->flash->setSuccess($message); 46 | 47 | return $this; 48 | } 49 | 50 | public function withTypeMessage($type, $message) { 51 | $this->flash->setTypeMessage($type, $message); 52 | 53 | return $this; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/Middleware/Session.php: -------------------------------------------------------------------------------- 1 | redirect = $this->container->get('redirect'); 16 | } 17 | 18 | public function __invoke(Request $request, Response $response, $next) { 19 | $current_route = $request->getUri()->getPath(); 20 | $current_url = (string) $request->getUri(); 21 | 22 | if ($request->isGet() === true && is_string($current_route) === true && $request->isXhr() === false) { 23 | $this->redirect->setPreviousUrl($current_url); 24 | } 25 | 26 | return $next($request, $response); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/RedirectionServiceProvider.php: -------------------------------------------------------------------------------- 1 | redirect->to('path'); 14 | * 15 | * # Redirect to any url like https://google.com/ 16 | * $this->redirect->away('path'); 17 | * 18 | * # Redirect to route home.index 19 | * $this->redirect->route('name'); 20 | * 21 | * # Redirect back to previous page 22 | * $this->redirect->back(); 23 | * 24 | * # Redirect back to previous page with input data 25 | * # - Controller 26 | * $this->redirect->back()->withRequestParams(); 27 | * $this->redirect->back()->withRequestParams()->withHeader('X-Hello', 'Params included'); 28 | * 29 | * # - View 30 | * {{ old_param(key, default = null) }} 31 | * 32 | * # Redirect with flash message 33 | * $this->redirect->{to,route,back}()->withError('message') 34 | * $this->redirect->{to,route,back}()->withMessage('message') 35 | * $this->redirect->{to,route,back}()->withTypeMessage('erorr|success', 'message') 36 | * 37 | */ 38 | class RedirectionServiceProvider extends ServiceProvider { 39 | 40 | public function register() { 41 | $this->container->set('redirect', function($container) { 42 | return new Redirector($container); 43 | }); 44 | } 45 | 46 | public function boot() { 47 | $this->app->add(new Middleware\Session($this->app)); 48 | 49 | if ($this->container->has('view') === true) { 50 | $this->container->get('view')->addExtension(new ViewExtension($this->container)); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/Redirector.php: -------------------------------------------------------------------------------- 1 | container = $container; 19 | 20 | if ($this->container->has('session') === false) { 21 | throw new RuntimeException('The session service provider does exists'); 22 | } 23 | 24 | $this->request = $this->container->get('request'); 25 | $this->response = $this->container->get('response'); 26 | $this->router = $this->container->get('router'); 27 | $this->session = $this->container->get('session'); 28 | } 29 | 30 | // 31 | public function to($path, $status = 302, $headers = null) { 32 | return $this->createRedirect($path, $status, $hreaders); 33 | } 34 | 35 | public function away($path, $status = 302, $hreaders = null) { 36 | return $this->createRedirect($path, $status, $hreaders); 37 | } 38 | 39 | public function route($name, $data = [], $query_parameters = [], $status = 302, $headers = null) { 40 | return $this->away( 41 | $this->router->pathFor($name, $data, $query_parameters), 42 | $status, 43 | $headers 44 | ); 45 | } 46 | 47 | public function createRedirect($path, $status = 302, $headers = null) { 48 | $response = new Http\Response($status, $headers); 49 | $response = $response->setRedirector($this); 50 | 51 | if ($this->container->has('flash') === true) { 52 | $response = $response->setFlash($this->container->get('flash')); 53 | } 54 | 55 | return $response->setRequest($this->request)->withRedirect($path); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/Traits/RedirectorBackRequest.php: -------------------------------------------------------------------------------- 1 | getHttpReferer(); 8 | $back_url = empty($referer_url) === false ? $referer_url : $this->getPreviousUrlFromSession(); 9 | 10 | return $this->createRedirect( 11 | empty($back_url) === false ? $back_url : '/', 12 | $status 13 | ); 14 | } 15 | 16 | public function getHttpReferer() { 17 | $headers = $this->request->getHeaders(); 18 | $referers = array_key_exists('HTTP_REFERER', $headers) === true ? $headers['HTTP_REFERER'] : []; 19 | $referer = empty($referers) === true ? '' : current($referers); 20 | 21 | return $referer; 22 | } 23 | 24 | public function getPreviousUrlFromSession() { 25 | if ($this->container->has('session') === true) { 26 | return $this->session->previousUrl(); 27 | }else{ 28 | return ''; 29 | } 30 | } 31 | 32 | public function setPreviousUrl($url) { 33 | $this->session->set('_redirector.form.previous_url', $url); 34 | } 35 | 36 | public function previousUrl() { 37 | return $this->session->get('_redirector.form.previous_url'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/Traits/RedirectorFormRequest.php: -------------------------------------------------------------------------------- 1 | session->set('_redirector.form.request_params', $params); 8 | } 9 | 10 | public function getRequestParam($key, $default = null) { 11 | if ($this->session->has('_redirector.form.request_params') === true) { 12 | $params = $this->session->get('_redirector.form.request_params'); 13 | 14 | if (array_key_exists($key, $params) === true) { 15 | $value = $params[$key]; 16 | 17 | unset($params[$key]); 18 | 19 | $this->setRequestParams($params); 20 | 21 | return $value; 22 | }else{ 23 | return $default; 24 | } 25 | }else{ 26 | return ""; 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /slimork/Providers/Redirection/ViewExtension.php: -------------------------------------------------------------------------------- 1 | container->get('redirect'); 27 | 28 | return $redirect->getRequestParam($key, $default); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /slimork/Providers/Session/Middleware/Session.php: -------------------------------------------------------------------------------- 1 | container->get('session'); 16 | 17 | if ($session->isStarted() === false) { 18 | $session->start(); 19 | } 20 | 21 | $this->session = $session; 22 | } 23 | 24 | public function __invoke(Request $request, Response $response, $next) { 25 | return $next($request, $response); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /slimork/Providers/Session/Segment.php: -------------------------------------------------------------------------------- 1 | name = $name; 11 | 12 | // Initial the name scope in session 13 | if (isset($_SESSION[$name]) === false) { 14 | $_SESSION[$name] = []; 15 | } 16 | 17 | // Make the alias variable point to the name scope 18 | $this->session_box = &$_SESSION[$name]; 19 | } 20 | 21 | public function set($key, $name) { 22 | $this->session_box[$key] = $name; 23 | } 24 | 25 | public function get($key, $default = null) { 26 | return $this->has($key) === true ? $this->session_box[$key] : $default; 27 | } 28 | 29 | public function has($key) { 30 | return array_key_exists($key, $this->session_box) === true; 31 | } 32 | 33 | public function remove($key) { 34 | if ($this->has($key) === true) { 35 | unset($this->session_box[$key]); 36 | } 37 | 38 | return $this; 39 | } 40 | 41 | public function pop($key) { 42 | if ($this->has($key) === true) { 43 | $value = $this->session_box[$key]; 44 | 45 | $this->remove($key); 46 | 47 | return $value; 48 | } 49 | 50 | return null; 51 | } 52 | 53 | public function push($key, $value) { 54 | $this->session_box[$key][] = $value; 55 | 56 | return $this->get($key); 57 | } 58 | 59 | public function pull($key) { 60 | $items = $this->get($key); 61 | $item = is_array($items) === true ? array_pop($this->session_box[$key]) : null; 62 | 63 | if ($this->isEmpty($key) === true) { 64 | $this->remove($key); 65 | } 66 | 67 | return $item; 68 | } 69 | 70 | public function isEmpty($key) { 71 | return empty($this->get($key)) === true; 72 | } 73 | 74 | public function all() { 75 | return $this->session_box; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /slimork/Providers/Session/Session.php: -------------------------------------------------------------------------------- 1 | 'PHPSESSID', 14 | 'lifetime' => 7200, 15 | 'path' => null, 16 | 'domain' => null, 17 | 'secure' => false, 18 | 'httponly' => true, 19 | 'handler' => null, 20 | 'ini_sets' => [] 21 | ]; 22 | 23 | public function __construct($container) { 24 | $this->settings = array_merge($this->options, $container->get('settings')['session']); 25 | 26 | // Set ini settings 27 | foreach($this->settings['ini_sets'] as $name => $value) { 28 | ini_set("session.".$name, $value); 29 | } 30 | } 31 | 32 | public function isStarted() { 33 | return session_status() !== PHP_SESSION_NONE; 34 | } 35 | 36 | public function start() { 37 | session_set_cookie_params( 38 | $this->settings['lifetime'], 39 | $this->settings['path'], 40 | $this->settings['domain'], 41 | $this->settings['secure'], 42 | $this->settings['httponly'] 43 | ); 44 | 45 | session_name($this->settings['name']); 46 | 47 | if ($this->isStarted() === false) { 48 | session_start(); 49 | } 50 | 51 | if ($this->settings['handler'] !== null) { 52 | if ($this->settings['handler'] instanceof SessionHandlerInterface) { 53 | session_set_save_handler(new $this->settings['handler'], true); 54 | }else{ 55 | throw new RuntimeException('The session handler must be instance of SessionHandlerInterface'); 56 | } 57 | } 58 | 59 | $this->segment = new Segment($this->segment); 60 | } 61 | 62 | public function segment($name) { 63 | return new Segment($name); 64 | } 65 | 66 | public function __call($name, array $arguments) { 67 | if (method_exists($this->segment, $name) === false) { 68 | throw new BadMethodCallException(sprintf( 69 | 'Method %s::%s does not exist.', static::class, $name 70 | )); 71 | } 72 | 73 | return call_user_func_array([$this->segment, $name], $arguments); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /slimork/Providers/Session/SessionServiceProvider.php: -------------------------------------------------------------------------------- 1 | session->set('key', 'value') 14 | * 15 | * # Get value 16 | * $this->session->get('key') 17 | * 18 | * # Is value exists or not 19 | * $this->session->has('key2') 20 | * 21 | * # Remove value 22 | * $this->session->remove('key') 23 | * 24 | * # Pop value 25 | * $this->session->pop('key'); 26 | * 27 | * # Push value to array item (the key must not exists) 28 | * $this->session->push('key3', 'a'); // ['a'] 29 | * $this->session->push('key3', 'b'); // ['a', 'b'] 30 | * $this->session->push('key3', 'c'); // ['a', 'b', 'c'] 31 | * 32 | * # Pull value from array item 33 | * $this->session->pull('key3'); // c 34 | * $this->session->pull('key3'); // b 35 | * $this->session->pull('key3'); // a 36 | */ 37 | class SessionServiceProvider extends ServiceProvider { 38 | 39 | public function register() { 40 | $this->container->set('session', function($container) { 41 | return new Session($container); 42 | }); 43 | } 44 | 45 | public function boot() { 46 | $this->app->add(new Middleware\Session($this->app)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /slimork/Providers/Validation/Rule.php: -------------------------------------------------------------------------------- 1 | validator; 17 | * 18 | * $validator->validators($request->getParams(), [ 19 | * 'username' => Rule::notEmpty()->noWhitespace()->length(4, 30), 20 | * 'password' => Rule::notEmpty()->length(8, 30), 21 | * ]); 22 | * 23 | * # Make validator with request paramters, related rules and translations 24 | * $validator = $this->validator; 25 | * 26 | * $validator->validators($request->getParams(), [ 27 | * 'username' => Rule::notEmpty()->noWhitespace()->length(4, 30), 28 | * 'password' => Rule::notEmpty()->length(8, 30), 29 | * ], [ 30 | * 'username.notEmpty' => "The {{name}} is empty", 31 | * "username.length" => "The {{name}} must have a length between {{minValue}} and {{maxValue}}" 32 | * ]); 33 | * 34 | * # Trigger validator and retrieve errors 35 | * if ($validator->fails() === true) { 36 | * 37 | * # All errors [ 'username' => ['notEmpty' => 'message', ...] , 'password' => ['notEmpty' => 'message', ...] ] 38 | * $errors = $validator->errors(); 39 | * 40 | * # All username errors ['notEmpty' => 'message', 'length' => 'message'] 41 | * $errors = $validator->errors('username'); 42 | * 43 | * # The top of error in errors stack 44 | * $errors = $validator->firstError(); 45 | * 46 | * }else{ 47 | * ... 48 | * ... 49 | * } 50 | */ 51 | class ValidationServiceProvider extends ServiceProvider { 52 | 53 | public function register() { 54 | $this->container->set('validator', function() { 55 | return new Validator(); 56 | }); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /slimork/Providers/Validation/Validator.php: -------------------------------------------------------------------------------- 1 | parameters = $parameters; 17 | $this->validators = $validators; 18 | $this->translations = $translations; 19 | 20 | $this->check(); 21 | 22 | return $this; 23 | } 24 | 25 | public function check() { 26 | foreach ($this->validators as $key => $validator) { 27 | $parameter = array_key_exists($key, $this->parameters) ? $this->parameters[$key] : ""; 28 | 29 | try { 30 | $validator->setName($key)->assert($parameter); 31 | }catch(NestedValidationException $exception) { 32 | foreach ($exception as $e) { 33 | $exception_id = $e->getId(); 34 | $translation_name = $key.'.'.$exception_id; 35 | 36 | if (array_key_exists($translation_name, $this->translations) === true) { 37 | $e->setTemplate($this->translations[$translation_name]); 38 | } 39 | 40 | $this->errors[$key][$exception_id] = $e->getMessage(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | public function fails() { 47 | return empty($this->errors) === false; 48 | } 49 | 50 | public function errors($parameter = "") { 51 | if (empty($parameter) === true) { 52 | return $this->errors; 53 | }else{ 54 | return array_key_exists($parameter, $this->errors) ? $this->errors[$parameter] : null; 55 | } 56 | } 57 | 58 | public function firstError() { 59 | $errors = $this->errors(); 60 | 61 | return current(array_shift($errors)); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /slimork/Providers/View/DefaultViewExtension.php: -------------------------------------------------------------------------------- 1 | container = $container; 14 | 15 | $this->setupView(); 16 | } 17 | 18 | public function setupView() { 19 | $settings = $this->container->get('settings'); 20 | $request = $this->container->get('request'); 21 | $router = $this->container->get('router'); 22 | 23 | $view_path = RESOURCES_ROOT.'/views'; 24 | $cache_path = STORAGE_ROOT.'/cache/views'; 25 | $base_path = rtrim(str_ireplace('index.php', '', $request->getUri()->getBasePath()), '/'); 26 | 27 | $view = new Twig($view_path, array_merge([ 28 | 'charset' => 'utf-8', 29 | 'auto_reload' => true, 30 | 'strict_variables' => false, 31 | 'autoescape' => 'html', 32 | 33 | 'cache' => $cache_path, 34 | ], $settings['view']['default'])); 35 | 36 | $view->addExtension(new TwigExtension($router, $base_path)); 37 | 38 | foreach($settings['view']['extensions'] as $extension) { 39 | $view->addExtension(new $extension($this->container)); 40 | } 41 | 42 | $this->view = $view; 43 | } 44 | 45 | // Custom the render methods to replace the original render($response, $view_file, $data) methods 46 | public function render($view, array $arguments = []) { 47 | $response = $this->container->get('response'); 48 | $response = $this->view->render($response, $view, $arguments); 49 | 50 | return $response; 51 | } 52 | 53 | public function __call($method, $arguments) { 54 | return $this->view->$method(...$arguments); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /slimork/Providers/View/ViewServiceProvider.php: -------------------------------------------------------------------------------- 1 | view->render('view.html', compact('variable')); 13 | */ 14 | class ViewServiceProvider extends ServiceProvider { 15 | 16 | public function register() { 17 | $this->container->set('view', function($container) { 18 | return new ViewManager($container); 19 | }); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /slimork/helpers.php: -------------------------------------------------------------------------------- 1 | 'utf-8', 27 | 'cache' => false, 28 | 'auto_reload' => true, 29 | 'strict_variables' => false, 30 | 'autoescape' => 'html', 31 | ]); 32 | 33 | $template = $twig->load($template_name); 34 | 35 | return $template->render($variables); 36 | } 37 | } 38 | 39 | if (function_exists('render_error') === false) { 40 | function render_error($template_name, $variables = []) { 41 | return render_template(resources_path('/views/errors'), $template_name, $variables); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /storage/cache/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | --------------------------------------------------------------------------------