Add new font files, images, and initial index.php for CakePHP setup

- Added new font files: Cakedingbats (TTF, WOFF, WOFF2) and Raleway (various styles and encodings).
- Included new images: cake-logo.png, cake.icon.png, cake.logo.svg, and cake.power.gif.
- Created initial index.php file for handling requests in CakePHP framework.
- Added .gitkeep file in the js directory to maintain the folder structure.
This commit is contained in:
2025-11-25 14:28:51 +01:00
commit 895cbddf06
123 changed files with 11437 additions and 0 deletions

26
.editorconfig Normal file
View File

@@ -0,0 +1,26 @@
; This file is for unifying the coding style for different editors and IDEs.
; More information at https://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.bat]
end_of_line = crlf
[*.yml]
indent_size = 2
[*.twig]
insert_final_newline = false
[*.neon]
indent_style = tab
[Makefile]
indent_style = tab

36
.gitattributes vendored Normal file
View File

@@ -0,0 +1,36 @@
# Define the line ending behavior of the different file extensions
# Set default behavior, in case users don't have core.autocrlf set.
* text text=auto eol=lf
# Declare files that will always have CRLF line endings on checkout.
*.bat eol=crlf
# Declare files that will always have LF line endings on checkout.
*.pem eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.webp binary
*.avif binary
*.ico binary
*.mo binary
*.pdf binary
*.xls binary
*.xlsx binary
*.phar binary
*.woff binary
*.woff2 binary
*.ttc binary
*.ttf binary
*.otf binary
*.eot binary
*.gz binary
*.bz2 binary
*.7z binary
*.zip binary
*.webm binary
*.mp4 binary
*.ogv binary

23
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,23 @@
This is a (multiple allowed):
* [x] bug
* [ ] enhancement
* [ ] feature-discussion (RFC)
* CakePHP Application Skeleton Version: EXACT RELEASE VERSION OR COMMIT HASH, HERE.
* Platform and Target: YOUR WEB-SERVER, DATABASE AND OTHER RELEVANT INFO AND HOW THE REQUEST IS BEING MADE, HERE.
### What you did
EXPLAIN WHAT YOU DID, PREFERABLY WITH CODE EXAMPLES, HERE.
### What happened
EXPLAIN WHAT IS ACTUALLY HAPPENING, HERE.
### What you expected to happen
EXPLAIN WHAT IS TO BE EXPECTED, HERE.
P.S. Remember, an issue is not the place to ask questions. You can use [Stack Overflow](https://stackoverflow.com/questions/tagged/cakephp)
for that or join the #cakephp channel on irc.freenode.net, where we will be more
than happy to help answer your questions.
Before you open an issue, please check if a similar issue already exists or has been closed before.

14
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,14 @@
<!---
**PLEASE NOTE:**
This is only a issue tracker for issues related to the CakePHP Application Skeleton.
For CakePHP Framework issues please use this [issue tracker](https://github.com/cakephp/cakephp/issues).
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
The best way to propose a feature is to open an issue first and discuss your ideas there before implementing them.
Always follow the [contribution guidelines](https://github.com/cakephp/cakephp/blob/master/.github/CONTRIBUTING.md) guidelines when submitting a pull request. In particular, make sure existing tests still pass, and add tests for all new behavior. When fixing a bug, you may want to add a test to verify the fix.
-->

12
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10

79
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: CI
on:
push:
branches:
- '5.x'
- '5.next'
- '6.x'
pull_request:
branches:
- '*'
workflow_dispatch:
permissions:
contents: read
jobs:
testsuite:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- php-version: '8.1'
dependencies: 'lowest'
- php-version: '8.4'
dependencies: 'highest'
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, intl, pdo_sqlite
ini-values: zend.assertions=1
coverage: none
- name: Composer install
uses: ramsey/composer-install@v3
with:
dependency-versions: ${{ matrix.dependencies }}
composer-options: ${{ matrix.composer-options }}
- name: Composer post install
run: composer run-script post-install-cmd --no-interaction
- name: Run PHPUnit
run: vendor/bin/phpunit
env:
DATABASE_TEST_URL: sqlite://./testdb.sqlite
coding-standard:
name: Coding Standard & Static Analysis
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mbstring, intl
coverage: none
tools: cs2pr, phpstan:1.12
- name: Composer install
uses: ramsey/composer-install@v3
- name: Run PHP CodeSniffer
run: vendor/bin/phpcs --report=checkstyle | cs2pr
- name: Run phpstan
if: always()
run: phpstan
env:
SECURITY_SALT: f76f1c8475585c46c6acd3ddcb8f5e0f15de524637bb4080a08c4afe7cfc9144

29
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Mark stale issues and pull requests
on:
schedule:
- cron: "0 0 * * *"
permissions:
contents: read
jobs:
stale:
permissions:
issues: write # for actions/stale to close stale issues
pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open for 120 days with no activity. Remove the `stale` label or comment or this will be closed in 15 days'
stale-pr-message: 'This pull request is stale because it has been open 30 days with no activity. Remove the `stale` label or comment on this issue, or it will be closed in 15 days'
stale-issue-label: 'stale'
stale-pr-label: 'stale'
days-before-stale: 120
days-before-close: 15
exempt-issue-labels: 'pinned'
exempt-pr-labels: 'pinned'

52
.gitignore vendored Normal file
View File

@@ -0,0 +1,52 @@
# CakePHP specific files #
##########################
/config/app_local.php
/config/.env
/logs/*
/tmp/*
/vendor/*
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
# Icon must end with two \r
Icon
ehthumbs.db
Thumbs.db
.directory
# Tool specific files #
#######################
# PHPUnit
.phpunit.cache
tests.sqlite
# vim
*~
*.swp
*.swo
# sublime text & textmate
*.sublime-*
*.stTheme.cache
*.tmlanguage.cache
*.tmPreferences.cache
# Eclipse
.settings/*
# JetBrains, aka PHPStorm, IntelliJ IDEA
.idea/*
# NetBeans
nbproject/*
# Visual Studio Code
.vscode
# nova
.nova
# Sass preprocessor
.sass-cache/
# node
/node_modules/*
# yarn
yarn-debug.log

12
.htaccess Normal file
View File

@@ -0,0 +1,12 @@
# Uncomment the following to prevent the httpoxy vulnerability
# See: https://httpoxy.org/
#<IfModule mod_headers.c>
# RequestHeader unset Proxy
#</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(\.well-known/.*)$ $1 [L]
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>

29
Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
# Minimalny Dockerfile dla aplikacji CakePHP
FROM php:8.2-apache
# Instalacja rozszerzeń PHP wymaganych przez CakePHP
RUN docker-php-ext-install pdo pdo_mysql mbstring intl
# Skopiuj pliki aplikacji do katalogu serwera
COPY . /var/www/html/
# Ustaw katalog roboczy
WORKDIR /var/www/html
# Ustaw uprawnienia
RUN chown -R www-data:www-data /var/www/html
# Włącz mod_rewrite dla CakePHP
RUN a2enmod rewrite
# Skonfiguruj Apache dla CakePHP
RUN echo '<Directory /var/www/html>
AllowOverride All
</Directory>' > /etc/apache2/conf-available/cakephp.conf \
&& a2enconf cakephp
# Domyślny port
EXPOSE 80
# Uruchom Apache
CMD ["apache2-foreground"]

53
README.md Normal file
View File

@@ -0,0 +1,53 @@
# CakePHP Application Skeleton
![Build Status](https://github.com/cakephp/app/actions/workflows/ci.yml/badge.svg?branch=5.x)
[![Total Downloads](https://img.shields.io/packagist/dt/cakephp/app.svg?style=flat-square)](https://packagist.org/packages/cakephp/app)
[![PHPStan](https://img.shields.io/badge/PHPStan-level%208-brightgreen.svg?style=flat-square)](https://github.com/phpstan/phpstan)
A skeleton for creating applications with [CakePHP](https://cakephp.org) 5.x.
The framework source code can be found here: [cakephp/cakephp](https://github.com/cakephp/cakephp).
## Installation
1. Download [Composer](https://getcomposer.org/doc/00-intro.md) or update `composer self-update`.
2. Run `php composer.phar create-project --prefer-dist cakephp/app [app_name]`.
If Composer is installed globally, run
```bash
composer create-project --prefer-dist cakephp/app
```
In case you want to use a custom app dir name (e.g. `/myapp/`):
```bash
composer create-project --prefer-dist cakephp/app myapp
```
You can now either use your machine's webserver to view the default home page, or start
up the built-in webserver with:
```bash
bin/cake server -p 8765
```
Then visit `http://localhost:8765` to see the welcome page.
## Update
Since this skeleton is a starting point for your application and various files
would have been modified as per your needs, there isn't a way to provide
automated upgrades, so you have to do any updates manually.
## Configuration
Read and edit the environment specific `config/app_local.php` and set up the
`'Datasources'` and any other configuration relevant for your application.
Other environment agnostic settings can be changed in `config/app.php`.
## Layout
The app skeleton uses [Milligram](https://milligram.io/) (v1.3) minimalist CSS
framework by default. You can, however, replace it with any other library or
custom styles.

47
bin/bash_completion.sh Normal file
View File

@@ -0,0 +1,47 @@
#
# Bash completion file for CakePHP console.
# Copy this file to a file named `cake` under `/etc/bash_completion.d/`.
# For more info check https://book.cakephp.org/5/en/console-commands/completion.html#how-to-enable-bash-autocompletion-for-the-cakephp-console
#
_cake()
{
local cur prev opts cake
COMPREPLY=()
cake="${COMP_WORDS[0]}"
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ "$cur" == -* ]] ; then
if [[ ${COMP_CWORD} = 1 ]] ; then
opts=$(${cake} completion options)
elif [[ ${COMP_CWORD} = 2 ]] ; then
opts=$(${cake} completion options "${COMP_WORDS[1]}")
else
opts=$(${cake} completion options "${COMP_WORDS[1]}" "${COMP_WORDS[2]}")
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
if [[ ${COMP_CWORD} = 1 ]] ; then
opts=$(${cake} completion commands)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
if [[ ${COMP_CWORD} = 2 ]] ; then
opts=$(${cake} completion subcommands $prev)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
if [[ $COMPREPLY = "" ]] ; then
_filedir
return 0
fi
return 0
fi
return 0
}
complete -F _cake cake bin/cake

75
bin/cake Normal file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env sh
################################################################################
#
# Cake is a shell script for invoking CakePHP shell commands
#
# CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
#
# Licensed under The MIT License
# For full copyright and license information, please see the LICENSE.txt
# Redistributions of files must retain the above copyright notice.
#
# @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
# @link https://cakephp.org CakePHP(tm) Project
# @since 1.2.0
# @license https://opensource.org/licenses/mit-license.php MIT License
#
################################################################################
# Canonicalize by following every symlink of the given name recursively
canonicalize() {
NAME="$1"
if [ -f "$NAME" ]
then
DIR=$(dirname -- "$NAME")
NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME")
fi
while [ -h "$NAME" ]; do
DIR=$(dirname -- "$NAME")
SYM=$(readlink "$NAME")
NAME=$(cd "$DIR" > /dev/null && cd "$(dirname -- "$SYM")" > /dev/null && pwd)/$(basename -- "$SYM")
done
echo "$NAME"
}
# Find a CLI version of PHP
findCliPhp() {
for TESTEXEC in php php-cli /usr/local/bin/php
do
SAPI=$(echo "<?= PHP_SAPI ?>" | $TESTEXEC 2>/dev/null)
if [ "$SAPI" = "cli" ]
then
echo $TESTEXEC
return
fi
done
echo "Failed to find a CLI version of PHP; falling back to system standard php executable" >&2
echo "php";
}
# If current path is a symlink, resolve to real path
realname="$0"
if [ -L "$realname" ]
then
realname=$(readlink -f "$0")
fi
CONSOLE=$(dirname -- "$(canonicalize "$realname")")
APP=$(dirname "$CONSOLE")
# If your CLI PHP is somewhere that this doesn't find, you can define a PHP environment
# variable with the correct path in it.
if [ -z "$PHP" ]
then
PHP=$(findCliPhp)
fi
if [ "$(basename "$realname")" != 'cake' ]
then
exec "$PHP" "$CONSOLE"/cake.php "$(basename "$realname")" "$@"
else
exec "$PHP" "$CONSOLE"/cake.php "$@"
fi
exit

27
bin/cake.bat Normal file
View File

@@ -0,0 +1,27 @@
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Cake is a Windows batch script for invoking CakePHP shell commands
::
:: CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
:: Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
::
:: Licensed under The MIT License
:: Redistributions of files must retain the above copyright notice.
::
:: @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
:: @link https://cakephp.org CakePHP(tm) Project
:: @since 2.0.0
:: @license https://opensource.org/licenses/mit-license.php MIT License
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
SET app=%0
SET lib=%~dp0
php "%lib%cake.php" %*
echo.
exit /B %ERRORLEVEL%

10
bin/cake.php Normal file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/php -q
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use App\Application;
use Cake\Console\CommandRunner;
// Build the runner with an application and root executable name.
$runner = new CommandRunner(new Application(dirname(__DIR__) . '/config'), 'cake');
exit($runner->run($argv));

58
composer.json Normal file
View File

@@ -0,0 +1,58 @@
{
"name": "cakephp/app",
"description": "CakePHP skeleton app",
"license": "MIT",
"type": "project",
"homepage": "https://cakephp.org",
"require": {
"php": ">=8.1",
"cakephp/authentication": "^3.3",
"cakephp/cakephp": "5.2.*",
"cakephp/migrations": "^4.0.0",
"cakephp/plugin-installer": "^2.0",
"mobiledetect/mobiledetectlib": "^4.8.03"
},
"require-dev": {
"cakephp/bake": "^3.0.0",
"cakephp/cakephp-codesniffer": "^5.0",
"cakephp/debug_kit": "^5.0.0",
"josegonzalez/dotenv": "^4.0",
"phpunit/phpunit": "^10.5.5 || ^11.1.3 || ^12.1"
},
"suggest": {
"cakephp/repl": "Console tools for a REPL interface for CakePHP applications.",
"dereuromark/cakephp-ide-helper": "After baking your code, this keeps your annotations in sync with the code evolving from there on for maximum IDE and PHPStan/Psalm compatibility.",
"markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.",
"phpstan/phpstan": "PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code."
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
}
},
"config": {
"allow-plugins": {
"cakephp/plugin-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
},
"platform-check": true,
"sort-packages": true
},
"scripts": {
"post-install-cmd": "App\\Console\\Installer::postInstall",
"post-create-project-cmd": "App\\Console\\Installer::postInstall",
"check": [
"@test",
"@cs-check"
],
"cs-check": "phpcs --colors -p",
"cs-fix": "phpcbf --colors -p",
"test": "phpunit --colors=always"
}
}

6328
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

38
config/.env.example Normal file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Used as a default to seed config/.env which
# enables you to use environment variables to configure
# the aspects of your application that vary by
# environment.
#
# Having this file in production is considered a **SECURITY RISK** and also decreases
# the bootstrap performance of your application.
#
# To use this file, first copy it into `config/.env`. Also ensure the related
# code block for loading this file is uncommented in `config/bootstrap.php`
#
# In development .env files are parsed by PHP
# and set into the environment. This provides a simpler
# development workflow over standard environment variables.
export APP_NAME="__APP_NAME__"
export DEBUG="true"
export APP_ENCODING="UTF-8"
export APP_DEFAULT_LOCALE="en_US"
export APP_DEFAULT_TIMEZONE="UTC"
export SECURITY_SALT="__SALT__"
# Uncomment these to define cache configuration via environment variables.
#export CACHE_DURATION="+2 minutes"
#export CACHE_DEFAULT_URL="file:///path/to/tmp/cache/?prefix=${APP_NAME}_default_&duration=${CACHE_DURATION}"
#export CACHE_CAKECORE_URL="file:///path/to/tmp/cache/persistent?prefix=${APP_NAME}_cake_translations_&serialize=true&duration=${CACHE_DURATION}"
#export CACHE_CAKEMODEL_URL="file:///path/to/tmp/cache/models?prefix=${APP_NAME}_cake_model_&serialize=true&duration=${CACHE_DURATION}"
# Uncomment these to define email transport configuration via environment variables.
#export EMAIL_TRANSPORT_DEFAULT_URL=""
# Uncomment these to define database configuration via environment variables.
#export DATABASE_URL="mysql://my_app:secret@localhost/${APP_NAME}?encoding=utf8&timezone=UTC&cacheMetadata=true&quoteIdentifiers=false&persistent=false"
#export DATABASE_TEST_URL="mysql://my_app:secret@localhost/test_${APP_NAME}?encoding=utf8&timezone=UTC&cacheMetadata=true&quoteIdentifiers=false&persistent=false"
# Uncomment these to define logging configuration via environment variables.
#export LOG_DEBUG_URL="file:///path/to/logs/?levels[]=notice&levels[]=info&levels[]=debug&file=debug"
#export LOG_ERROR_URL="file:///path/to/logs/?levels[]=warning&levels[]=error&levels[]=critical&levels[]=alert&levels[]=emergency&file=error"

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
use Migrations\BaseMigration;
class CreateTools extends BaseMigration
{
public function change(): void
{
$table = $this->table('tools')
->addColumn('name', 'string', ['limit' => 150])
->addColumn('description', 'text', ['null' => true])
->addColumn('quantity', 'integer', ['default' => 1])
->addColumn('active', 'boolean', ['default' => true])
->addColumn('created', 'datetime')
->addColumn('modified', 'datetime', ['null' => true])
->create();
}
public function down(): void
{
$this->table('tools')->drop()->save();
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
use Migrations\BaseMigration;
class CreateUsers extends BaseMigration
{
public function change(): void {
$table = $this->table('users')
->addColumn('name', 'string', ['limit' => 150])
->addColumn('email', 'string', ['limit' => 255])
->addColumn('password', 'string', ['limit' => 255])
->addColumn('created', 'datetime')
->addColumn('modified', 'datetime', ['null' => true]);
$table->create();
}
}

Binary file not shown.

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
use Migrations\BaseSeed;
use Authentication\PasswordHasher\DefaultPasswordHasher;
class UsersSeed extends BaseSeed
{
public function run(): void
{
$hasher = new DefaultPasswordHasher();
$data = [
[
'name' => 'Administrator',
'email' => 'admin@example.com',
// UWAGA: haslo haszujemy tutaj:
'password' => $hasher->hash('Admin123!'),
'created' => date('Y-m-d H:i:s'),
'modified' => date('Y-m-d H:i:s'),
],
];
$table = $this->table('users');
$table->insert($data)->save();
}
}

458
config/app.php Normal file
View File

@@ -0,0 +1,458 @@
<?php
use Cake\Cache\Engine\FileEngine;
use Cake\Database\Connection;
use Cake\Database\Driver\Mysql;
use Cake\Log\Engine\FileLog;
use Cake\Mailer\Transport\MailTransport;
use function Cake\Core\env;
return [
/*
* Debug Level:
*
* Production Mode:
* false: No error messages, errors, or warnings shown.
*
* Development Mode:
* true: Errors and warnings shown.
*/
'debug' => filter_var(env('DEBUG', false), FILTER_VALIDATE_BOOLEAN),
/*
* Configure basic information about the application.
*
* - namespace - The namespace to find app classes under.
* - defaultLocale - The default locale for translation, formatting currencies and numbers, date and time.
* - encoding - The encoding used for HTML + database connections.
* - base - The base directory the app resides in. If false this
* will be auto-detected.
* - dir - Name of app directory.
* - webroot - The webroot directory.
* - wwwRoot - The file path to webroot.
* - baseUrl - To configure CakePHP to *not* use mod_rewrite and to
* use CakePHP pretty URLs, remove these .htaccess
* files:
* /.htaccess
* /webroot/.htaccess
* And uncomment the baseUrl key below.
* - fullBaseUrl - A base URL to use for absolute links. When set to false (default)
* CakePHP generates required value based on `HTTP_HOST` environment variable.
* However, you can define it manually to optimize performance or if you
* are concerned about people manipulating the `Host` header.
* - imageBaseUrl - Web path to the public images/ directory under webroot.
* - cssBaseUrl - Web path to the public css/ directory under webroot.
* - jsBaseUrl - Web path to the public js/ directory under webroot.
* - paths - Configure paths for non class-based resources. Supports the
* `plugins`, `templates`, `locales` subkeys, which allow the definition of
* paths for plugins, view templates and locale files respectively.
*/
'App' => [
'namespace' => 'App',
'encoding' => env('APP_ENCODING', 'UTF-8'),
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'),
'base' => false,
'dir' => 'src',
'webroot' => 'webroot',
'wwwRoot' => WWW_ROOT,
//'baseUrl' => env('SCRIPT_NAME'),
'fullBaseUrl' => false,
'imageBaseUrl' => 'img/',
'cssBaseUrl' => 'css/',
'jsBaseUrl' => 'js/',
'paths' => [
'plugins' => [ROOT . DS . 'plugins' . DS],
'templates' => [ROOT . DS . 'templates' . DS],
'locales' => [RESOURCES . 'locales' . DS],
],
],
/*
* Security and encryption configuration
*
* - salt - A random string used in security hashing methods.
* The salt value is also used as the encryption key.
* You should treat it as extremely sensitive data.
*/
'Security' => [
'salt' => env('SECURITY_SALT'),
],
/*
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a querystring parameter containing the time the file was modified.
* This is useful for busting browser caches.
*
* Set to true to apply timestamps when debug is true. Set to 'force' to always
* enable timestamping regardless of debug value.
*/
'Asset' => [
//'timestamp' => true,
// 'cacheTime' => '+1 year'
],
/*
* Configure the cache adapters.
*/
'Cache' => [
'default' => [
'className' => FileEngine::class,
'path' => CACHE,
'url' => env('CACHE_DEFAULT_URL', null),
],
/*
* Configure the cache used for general framework caching.
* Translation cache files are stored with this configuration.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
* If you set 'className' => 'Null' core cache will be disabled.
*/
'_cake_translations_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_translations_',
'path' => CACHE . 'persistent' . DS,
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKECORE_URL', null),
],
/*
* Configure the cache for model and datasource caches. This cache
* configuration is used to store schema descriptions, and table listings
* in connections.
* Duration will be set to '+2 minutes' in bootstrap.php when debug = true
*/
'_cake_model_' => [
'className' => FileEngine::class,
'prefix' => 'myapp_cake_model_',
'path' => CACHE . 'models' . DS,
'serialize' => true,
'duration' => '+1 years',
'url' => env('CACHE_CAKEMODEL_URL', null),
],
],
/*
* Configure the Error and Exception handlers used by your application.
*
* By default errors are displayed using Debugger, when debug is true and logged
* by Cake\Log\Log when debug is false.
*
* In CLI environments exceptions will be printed to stderr with a backtrace.
* In web environments an HTML page will be displayed for the exception.
* With debug true, framework errors like Missing Controller will be displayed.
* When debug is false, framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `errorLevel` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Whether backtraces should be included in
* logged errors/exceptions.
* - `log` - boolean - Whether you want exceptions logged.
* - `exceptionRenderer` - string - The class responsible for rendering uncaught exceptions.
* The chosen class will be used for both CLI and web environments. If you want different
* classes used in CLI and web environments you'll need to write that conditional logic as well.
* The conventional location for custom renderers is in `src/Error`. Your exception renderer needs to
* implement the `render()` method and return either a string or Http\Response.
* `errorRenderer` - string - The class responsible for rendering PHP errors. The selected
* class will be used for both web and CLI contexts. If you want different classes for each environment
* you'll need to write that conditional logic as well. Error renderers need to
* to implement the `Cake\Error\ErrorRendererInterface`.
* - `skipLog` - array - List of exceptions to skip for logging. Exceptions that
* extend one of the listed exceptions will also be skipped for logging.
* E.g.:
* `'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException']`
* - `extraFatalErrorMemory` - int - The number of megabytes to increase the memory limit by
* when a fatal error is encountered. This allows
* breathing room to complete logging or error handling.
* - `ignoredDeprecationPaths` - array - A list of glob-compatible file paths that deprecations
* should be ignored in. Use this to ignore deprecations for plugins or parts of
* your application that still emit deprecations.
*/
'Error' => [
'errorLevel' => E_ALL,
'skipLog' => [],
'log' => true,
'trace' => true,
'ignoredDeprecationPaths' => [],
],
/*
* Debugger configuration
*
* Define development error values for Cake\Error\Debugger
*
* - `editor` Set the editor URL format you want to use.
* By default atom, emacs, macvim, phpstorm, sublime, textmate, and vscode are
* available. You can add additional editor link formats using
* `Debugger::addEditor()` during your application bootstrap.
* - `outputMask` A mapping of `key` to `replacement` values that
* `Debugger` should replace in dumped data and logs generated by `Debugger`.
*/
'Debugger' => [
'editor' => 'phpstorm',
],
/*
* Email configuration.
*
* By defining transports separately from delivery profiles you can easily
* re-use transport configuration across multiple profiles.
*
* You can specify multiple configurations for production, development and
* testing.
*
* Each transport needs a `className`. Valid options are as follows:
*
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to src/Mailer/Transport. Transports should be named
* 'YourTransport.php', where 'Your' is the name of the transport.
*/
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The keys host, port, timeout, username, password, client and tls
* are used in SMTP transports
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
/*
* It is recommended to set these options through your environment or app_local.php
*/
//'username' => null,
//'password' => null,
'client' => null,
'tls' => false,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
/*
* Email delivery profiles
*
* Delivery profiles allow you to predefine various properties about email
* messages from your application and give the settings a name. This saves
* duplication across your application and makes maintenance and development
* easier. Each profile accepts a number of keys. See `Cake\Mailer\Mailer`
* for more information.
*/
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you@localhost',
/*
* Will by default be set to config value of App.encoding, if that exists otherwise to UTF-8.
*/
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
/*
* Connection information used by the ORM to connect
* to your application's datastores.
*
* ### Notes
* - Drivers include Mysql Postgres Sqlite Sqlserver
* See vendor\cakephp\cakephp\src\Database\Driver for the complete list
* - Do not use periods in database name - it may lead to errors.
* See https://github.com/cakephp/cakephp/issues/6471 for details.
* - 'encoding' is recommended to be set to full UTF-8 4-Byte support.
* E.g set it to 'utf8mb4' in MariaDB and MySQL and 'utf8' for any
* other RDBMS.
*/
'Datasources' => [
/*
* These configurations should contain permanent settings used
* by all environments.
*
* The values in app_local.php will override any values set here
* and should be used for local and per-environment configurations.
*
* Environment variable-based configurations can be loaded here or
* in app_local.php depending on the application's needs.
*/
'default' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'timezone' => 'UTC',
/*
* For MariaDB/MySQL the internal default changed from utf8 to utf8mb4, aka full utf-8 support
*/
'encoding' => 'utf8mb4',
/*
* If your MySQL server is configured with `skip-character-set-client-handshake`
* then you MUST use the `flags` config to set your charset encoding.
* For e.g. `'flags' => [\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4']`
*/
'flags' => [],
'cacheMetadata' => true,
'log' => false,
/*
* Set identifier quoting to true if you are using reserved words or
* special characters in your table or column names. Enabling this
* setting will result in queries built using the Query Builder having
* identifiers quoted when creating SQL. It should be noted that this
* decreases performance because each query needs to be traversed and
* manipulated before being executed.
*/
'quoteIdentifiers' => false,
/*
* During development, if using MySQL < 5.6, uncommenting the
* following line could boost the speed at which schema metadata is
* fetched from the database. It can also be set directly with the
* mysql configuration directive 'innodb_stats_on_metadata = 0'
* which is the recommended value in production environments
*/
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
],
/*
* The test connection is used during the test suite.
*/
'test' => [
'className' => Connection::class,
'driver' => Mysql::class,
'persistent' => false,
'timezone' => 'UTC',
'encoding' => 'utf8mb4',
'flags' => [],
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
],
],
/*
* Configures logging options
*/
'Log' => [
'debug' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'debug',
'url' => env('LOG_DEBUG_URL', null),
'scopes' => null,
'levels' => ['notice', 'info', 'debug'],
],
'error' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'error',
'url' => env('LOG_ERROR_URL', null),
'scopes' => null,
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
],
// To enable this dedicated query log, you need to set your datasource's log flag to true
'queries' => [
'className' => FileLog::class,
'path' => LOGS,
'file' => 'queries',
'url' => env('LOG_QUERIES_URL', null),
'scopes' => ['cake.database.queries'],
],
],
/*
* Session configuration.
*
* Contains an array of settings to use for session configuration. The
* `defaults` key is used to define a default preset to use for sessions, any
* settings declared here will override the settings of the default config.
*
* ## Options
*
* - `cookie` - The name of the cookie to use. Defaults to value set for `session.name` php.ini config.
* Avoid using `.` in cookie names, as PHP will drop sessions from cookies with `.` in the name.
* - `cookiePath` - The url path for which session cookie is set. Maps to the
* `session.cookie_path` php.ini config. Defaults to base path of app.
* - `timeout` - The time in minutes a session can be 'idle'. If no request is received in
* this duration, the session will be expired and rotated. Pass 0 to disable idle timeout checks.
* - `defaults` - The default configuration set to use as a basis for your session.
* There are four built-in options: php, cake, cache, database.
* - `handler` - Can be used to enable a custom session handler. Expects an
* array with at least the `engine` key, being the name of the Session engine
* class to use for managing the session. CakePHP bundles the `CacheSession`
* and `DatabaseSession` engines.
* - `ini` - An associative array of additional 'session.*` ini values to set.
*
* Within the `ini` key, you will likely want to define:
*
* - `session.cookie_lifetime` - The number of seconds that cookies are valid for. This
* should be longer than `Session.timeout`.
* - `session.gc_maxlifetime` - The number of seconds after which a session is considered 'garbage'
* that can be deleted by PHP's session cleanup behavior. This value should be greater than both
* `Sesssion.timeout` and `session.cookie_lifetime`.
*
* The built-in `defaults` options are:
*
* - 'php' - Uses settings defined in your php.ini.
* - 'cake' - Saves session files in CakePHP's /tmp directory.
* - 'database' - Uses CakePHP's database sessions.
* - 'cache' - Use the Cache class to save sessions.
*
* To define a custom session handler, save it at src/Http/Session/<name>.php.
* Make sure the class implements PHP's `SessionHandlerInterface` and set
* Session.handler to <name>
*
* To use database sessions, load the SQL file located at config/schema/sessions.sql
*/
'Session' => [
'defaults' => 'php',
],
/**
* DebugKit configuration.
*
* Contains an array of configurations to apply to the DebugKit plugin, if loaded.
* Documentation: https://book.cakephp.org/debugkit/5/en/index.html#configuration
*
* ## Options
*
* - `panels` - Enable or disable panels. The key is the panel name, and the value is true to enable,
* or false to disable.
* - `includeSchemaReflection` - Set to true to enable logging of schema reflection queries. Disabled by default.
* - `safeTld` - Set an array of whitelisted TLDs for local development.
* - `forceEnable` - Force DebugKit to display. Careful with this, it is usually safer to simply whitelist
* your local TLDs.
* - `ignorePathsPattern` - Regex pattern (including delimiter) to ignore paths.
* DebugKit wont save data for request URLs that match this regex.
* - `ignoreAuthorization` - Set to true to ignore Cake Authorization plugin for DebugKit requests.
* Disabled by default.
* - `maxDepth` - Defines how many levels of nested data should be shown in general for debug output.
* Default is 5. WARNING: Increasing the max depth level can lead to an out of memory error.
* - `variablesPanelMaxDepth` - Defines how many levels of nested data should be shown in the variables tab.
* Default is 5. WARNING: Increasing the max depth level can lead to an out of memory error.
*/
'DebugKit' => [
'forceEnable' => filter_var(env('DEBUG_KIT_FORCE_ENABLE', false), FILTER_VALIDATE_BOOLEAN),
'safeTld' => env('DEBUG_KIT_SAFE_TLD', null),
'ignoreAuthorization' => env('DEBUG_KIT_IGNORE_AUTHORIZATION', false),
],
/**
* TestSuite configuration.
*
* ## Options
*
* - `errorLevel` - Defaults to `E_ALL`. Can be set to `false` to disable overwrite error level.
* - `fixtureStrategy` - Defaults to TruncateStrategy. Can be set to any class implementing FixtureStrategyInterface.
*/
'TestSuite' => [
'errorLevel' => null,
'fixtureStrategy' => null,
],
];

View File

@@ -0,0 +1,97 @@
<?php
use function Cake\Core\env;
/*
* Local configuration file to provide any overrides to your app.php configuration.
* Copy and save this file as app_local.php and make changes as required.
* Note: It is not recommended to commit files with credentials such as app_local.php
* into source code version control.
*/
return [
/*
* Debug Level:
*
* Production Mode:
* false: No error messages, errors, or warnings shown.
*
* Development Mode:
* true: Errors and warnings shown.
*/
'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),
/*
* Security and encryption configuration
*
* - salt - A random string used in security hashing methods.
* The salt value is also used as the encryption key.
* You should treat it as extremely sensitive data.
*/
'Security' => [
'salt' => env('SECURITY_SALT', '__SALT__'),
],
/*
* Connection information used by the ORM to connect
* to your application's datastores.
*
* See app.php for more configuration options.
*/
'Datasources' => [
'default' => [
'host' => 'localhost',
/*
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
* the following line and set the port accordingly
*/
//'port' => 'non_standard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'my_app',
/*
* If not using the default 'public' schema with the PostgreSQL driver
* set it here.
*/
//'schema' => 'myapp',
/*
* You can use a DSN string to set the entire configuration
*/
'url' => env('DATABASE_URL', null),
],
/*
* The test connection is used during the test suite.
*/
'test' => [
'host' => 'localhost',
//'port' => 'non_standard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'test_myapp',
//'schema' => 'myapp',
'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tmp/tests.sqlite'),
],
],
/*
* Email configuration.
*
* Host and credential configuration in case you are using SmtpTransport
*
* See app.php for more configuration options.
*/
'EmailTransport' => [
'default' => [
'host' => 'localhost',
'port' => 25,
'username' => null,
'password' => null,
'client' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
];

234
config/bootstrap.php Normal file
View File

@@ -0,0 +1,234 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.8
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
/*
* This file is loaded by your src/Application.php bootstrap method.
* Feel free to extend/extract parts of the bootstrap process into your own files
* to suit your needs/preferences.
*/
/*
* Configure paths required to find CakePHP + general filepath constants
*/
require __DIR__ . DIRECTORY_SEPARATOR . 'paths.php';
/*
* Bootstrap CakePHP
* Currently all this does is initialize the router (without loading your routes)
*/
require CORE_PATH . 'config' . DS . 'bootstrap.php';
use Cake\Cache\Cache;
use Cake\Core\Configure;
use Cake\Core\Configure\Engine\PhpConfig;
use Cake\Datasource\ConnectionManager;
use Cake\Error\ErrorTrap;
use Cake\Error\ExceptionTrap;
use Cake\Http\ServerRequest;
use Cake\Log\Log;
use Cake\Mailer\Mailer;
use Cake\Mailer\TransportFactory;
use Cake\Routing\Router;
use Cake\Utility\Security;
use function Cake\Core\env;
/*
* Load global functions for collections, translations, debugging etc.
*/
require CAKE . 'functions.php';
/*
* See https://github.com/josegonzalez/php-dotenv for API details.
*
* Uncomment block of code below if you want to use `.env` file during development.
* You should copy `config/.env.example` to `config/.env` and set/modify the
* variables as required.
*
* The purpose of the .env file is to emulate the presence of the environment
* variables like they would be present in production.
*
* If you use .env files, be careful to not commit them to source control to avoid
* security risks. See https://github.com/josegonzalez/php-dotenv#general-security-information
* for more information for recommended practices.
*/
// if (!env('APP_NAME') && file_exists(CONFIG . '.env')) {
// $dotenv = new \josegonzalez\Dotenv\Loader([CONFIG . '.env']);
// $dotenv->parse()
// ->putenv()
// ->toEnv()
// ->toServer();
// }
/*
* Initializes default Config store and loads the main configuration file (app.php)
*
* CakePHP contains 2 configuration files after project creation:
* - `config/app.php` for the default application configuration.
* - `config/app_local.php` for environment specific configuration.
*/
try {
Configure::config('default', new PhpConfig());
Configure::load('app', 'default', false);
} catch (\Exception $e) {
exit($e->getMessage() . "\n");
}
/*
* Load an environment local configuration file to provide overrides to your configuration.
* Notice: For security reasons app_local.php **should not** be included in your git repo.
*/
if (file_exists(CONFIG . 'app_local.php')) {
Configure::load('app_local', 'default');
}
/*
* When debug = true the metadata cache should only last for a short time.
*/
if (Configure::read('debug')) {
Configure::write('Cache._cake_model_.duration', '+2 minutes');
Configure::write('Cache._cake_translations_.duration', '+2 minutes');
}
/*
* Set the default server timezone. Using UTC makes time calculations / conversions easier.
* Check https://php.net/manual/en/timezones.php for list of valid timezone strings.
*/
date_default_timezone_set(Configure::read('App.defaultTimezone'));
/*
* Configure the mbstring extension to use the correct encoding.
*/
mb_internal_encoding(Configure::read('App.encoding'));
/*
* Set the default locale. This controls how dates, number and currency is
* formatted and sets the default language to use for translations.
*/
ini_set('intl.default_locale', Configure::read('App.defaultLocale'));
/*
* Register application error and exception handlers.
*/
(new ErrorTrap(Configure::read('Error')))->register();
(new ExceptionTrap(Configure::read('Error')))->register();
/*
* CLI/Command specific configuration.
*/
if (PHP_SAPI === 'cli') {
// Set the fullBaseUrl to allow URLs to be generated in commands.
// This is useful when sending email from commands.
// Configure::write('App.fullBaseUrl', php_uname('n'));
// Set logs to different files so they don't have permission conflicts.
if (Configure::check('Log.debug')) {
Configure::write('Log.debug.file', 'cli-debug');
}
if (Configure::check('Log.error')) {
Configure::write('Log.error.file', 'cli-error');
}
}
/*
* Set the full base URL.
* This URL is used as the base of all absolute links.
* Can be very useful for CLI/Commandline applications.
*/
$fullBaseUrl = Configure::read('App.fullBaseUrl');
if (!$fullBaseUrl) {
/*
* When using proxies or load balancers, SSL/TLS connections might
* get terminated before reaching the server. If you trust the proxy,
* you can enable `$trustProxy` to rely on the `X-Forwarded-Proto`
* header to determine whether to generate URLs using `https`.
*
* See also https://book.cakephp.org/5/en/controllers/request-response.html#trusting-proxy-headers
*/
$trustProxy = false;
$s = null;
if (env('HTTPS') || ($trustProxy && env('HTTP_X_FORWARDED_PROTO') === 'https')) {
$s = 's';
}
$httpHost = env('HTTP_HOST');
if ($httpHost) {
$fullBaseUrl = 'http' . $s . '://' . $httpHost;
}
unset($httpHost, $s);
}
if ($fullBaseUrl) {
Router::fullBaseUrl($fullBaseUrl);
}
unset($fullBaseUrl);
/*
* Apply the loaded configuration settings to their respective systems.
* This will also remove the loaded config data from memory.
*/
Cache::setConfig(Configure::consume('Cache'));
ConnectionManager::setConfig(Configure::consume('Datasources'));
TransportFactory::setConfig(Configure::consume('EmailTransport'));
Mailer::setConfig(Configure::consume('Email'));
Log::setConfig(Configure::consume('Log'));
Security::setSalt(Configure::consume('Security.salt'));
/*
* Setup detectors for mobile and tablet.
* If you don't use these checks you can safely remove this code
* and the mobiledetect package from composer.json.
*/
ServerRequest::addDetector('mobile', function ($request) {
$detector = new \Detection\MobileDetect();
return $detector->isMobile();
});
ServerRequest::addDetector('tablet', function ($request) {
$detector = new \Detection\MobileDetect();
return $detector->isTablet();
});
/*
* You can enable default locale format parsing by adding calls
* to `useLocaleParser()`. This enables the automatic conversion of
* locale specific date formats when processing request data. For details see
* @link https://book.cakephp.org/5/en/core-libraries/internationalization-and-localization.html#parsing-localized-datetime-data
*/
// \Cake\Database\TypeFactory::build('time')->useLocaleParser();
// \Cake\Database\TypeFactory::build('date')->useLocaleParser();
// \Cake\Database\TypeFactory::build('datetime')->useLocaleParser();
// \Cake\Database\TypeFactory::build('timestamp')->useLocaleParser();
// \Cake\Database\TypeFactory::build('datetimefractional')->useLocaleParser();
// \Cake\Database\TypeFactory::build('timestampfractional')->useLocaleParser();
// \Cake\Database\TypeFactory::build('datetimetimezone')->useLocaleParser();
// \Cake\Database\TypeFactory::build('timestamptimezone')->useLocaleParser();
/*
* Custom Inflector rules, can be set to correctly pluralize or singularize
* table, model, controller names or whatever other string is passed to the
* inflection functions.
*/
// \Cake\Utility\Inflector::rules('plural', ['/^(inflect)or$/i' => '\1ables']);
// \Cake\Utility\Inflector::rules('irregular', ['red' => 'redlings']);
// \Cake\Utility\Inflector::rules('uninflected', ['dontinflectme']);
// set a custom date and time format
// see https://book.cakephp.org/5/en/core-libraries/time.html#setting-the-default-locale-and-format-string
// and https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax
// \Cake\I18n\Date::setToStringFormat('dd.MM.yyyy');
// \Cake\I18n\Time::setToStringFormat('dd.MM.yyyy HH:mm');

94
config/paths.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license MIT License (https://opensource.org/licenses/mit-license.php)
*/
/*
* Use the DS to separate the directories in other defines
*/
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
/*
* These definitions should only be edited if you have cake installed in
* a directory layout other than the way it is distributed.
* When using custom settings be sure to use the DS and do not add a trailing DS.
*/
/*
* The full path to the directory which holds "src", WITHOUT a trailing DS.
*/
define('ROOT', dirname(__DIR__));
/*
* The actual directory name for the application directory. Normally
* named 'src'.
*/
define('APP_DIR', 'src');
/*
* Path to the application's directory.
*/
define('APP', ROOT . DS . APP_DIR . DS);
/*
* Path to the config directory.
*/
define('CONFIG', ROOT . DS . 'config' . DS);
/*
* File path to the webroot directory.
*
* To derive your webroot from your webserver change this to:
*
* `define('WWW_ROOT', rtrim($_SERVER['DOCUMENT_ROOT'], DS) . DS);`
*/
define('WWW_ROOT', ROOT . DS . 'webroot' . DS);
/*
* Path to the tests directory.
*/
define('TESTS', ROOT . DS . 'tests' . DS);
/*
* Path to the temporary files directory.
*/
define('TMP', ROOT . DS . 'tmp' . DS);
/*
* Path to the logs directory.
*/
define('LOGS', ROOT . DS . 'logs' . DS);
/*
* Path to the cache files directory. It can be shared between hosts in a multi-server setup.
*/
define('CACHE', TMP . 'cache' . DS);
/*
* Path to the resources directory.
*/
define('RESOURCES', ROOT . DS . 'resources' . DS);
/*
* The absolute path to the "cake" directory, WITHOUT a trailing DS.
*
* CakePHP should always be installed with composer, so look there.
*/
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'vendor' . DS . 'cakephp' . DS . 'cakephp');
/*
* Path to the cake directory.
*/
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
define('CAKE', CORE_PATH . 'src' . DS);

36
config/plugins.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
/**
* Plugin configuration.
*
* In this file, you configure which plugins are loaded in the different states your app can be.
* It's loaded via the `parent::bootstrap();` call inside your `Application::bootstrap()` method.
* For more information see https://book.cakephp.org/5/en/plugins.html#loading-plugins-via-configuration-array
*
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 5.0.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
/*
* List of plugins to load in the form `PluginName` => `[configuration options]`.
*
* Available options:
* - onlyDebug: Load the plugin only in debug mode. Default false.
* - onlyCli: Load the plugin only in CLI mode. Default false.
* - optional: Do not throw an exception if the plugin is not found. Default false.
*/
return [
'DebugKit' => ['onlyDebug' => true],
'Bake' => ['onlyCli' => true, 'optional' => true],
'Migrations' => ['onlyCli' => true],
// Additional plugins here
];

96
config/routes.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
/**
* Routes configuration.
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different URLs to chosen controllers and their actions (functions).
*
* It's loaded within the context of `Application::routes()` method which
* receives a `RouteBuilder` instance `$routes` as method argument.
*
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/*
* This file is loaded in the context of the `Application` class.
* So you can use `$this` to reference the application class instance
* if required.
*/
return function (RouteBuilder $routes): void {
/*
* The default class to use for all routes
*
* The following route classes are supplied with CakePHP and are appropriate
* to set as the default:
*
* - Route
* - InflectedRoute
* - DashedRoute
*
* If no call is made to `Router::defaultRouteClass()`, the class used is
* `Route` (`Cake\Routing\Route\Route`)
*
* Note that `Route` does not do any inflections on URLs which will result in
* inconsistently cased URLs when used with `{plugin}`, `{controller}` and
* `{action}` markers.
*/
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/', function (RouteBuilder $builder): void {
/*
* Here, we are connecting '/' (base path) to a controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, templates/Pages/home.php)...
*/
$builder->connect('/', ['controller' => 'Tools','action' => 'index']);
/*
* ...and connect the rest of 'Pages' controller's URLs.
*/
$builder->connect('/pages/*', 'Pages::display');
/*
* Connect catchall routes for all controllers.
*
* The `fallbacks` method is a shortcut for
*
* ```
* $builder->connect('/{controller}', ['action' => 'index']);
* $builder->connect('/{controller}/{action}/*', []);
* ```
*
* It is NOT recommended to use fallback routes after your initial prototyping phase!
* See https://book.cakephp.org/5/en/development/routing.html#fallbacks-method for more information
*/
$builder->fallbacks();
});
/*
* If you need a different set of middleware or none at all,
* open new scope and define routes there.
*
* ```
* $routes->scope('/api', function (RouteBuilder $builder): void {
* // No $builder->applyMiddleware() here.
*
* // Parse specified extensions from URLs
* // $builder->setExtensions(['json', 'xml']);
*
* // Connect API actions here.
* });
* ```
*/
};

18
config/schema/i18n.sql Normal file
View File

@@ -0,0 +1,18 @@
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
#
# Licensed under The MIT License
# For full copyright and license information, please see the LICENSE.txt
# Redistributions of files must retain the above copyright notice.
# MIT License (https://opensource.org/licenses/mit-license.php)
CREATE TABLE i18n (
id int NOT NULL auto_increment,
locale varchar(6) NOT NULL,
model varchar(255) NOT NULL,
foreign_key int(10) NOT NULL,
field varchar(255) NOT NULL,
content text,
PRIMARY KEY (id),
UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
INDEX I18N_FIELD(model, foreign_key, field)
);

View File

@@ -0,0 +1,15 @@
# Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
#
# Licensed under The MIT License
# For full copyright and license information, please see the LICENSE.txt
# Redistributions of files must retain the above copyright notice.
# MIT License (https://opensource.org/licenses/mit-license.php)
CREATE TABLE `sessions` (
`id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
`modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
`data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
`expires` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

BIN
database/app.sqlite Normal file

Binary file not shown.

16
index.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';

12
phpcs.xml Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<ruleset name="App">
<config name="installed_paths" value="../../cakephp/cakephp-codesniffer"/>
<rule ref="CakePHP"/>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
<exclude-pattern>*/src/Controller/*</exclude-pattern>
</rule>
<file>src/</file>
<file>tests/</file>
</ruleset>

8
phpstan.neon Normal file
View File

@@ -0,0 +1,8 @@
parameters:
level: 8
treatPhpDocTypesAsCertain: false
checkGenericClassInNonGenericObjectType: false
bootstrapFiles:
- config/bootstrap.php
paths:
- src/

37
phpunit.xml.dist Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
colors="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="tests/bootstrap.php"
cacheDirectory=".phpunit.cache"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.1/phpunit.xsd">
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>
<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="app">
<directory>tests/TestCase/</directory>
</testsuite>
<!-- Add plugin test suites here. -->
</testsuites>
<!-- Load extension for fixtures -->
<extensions>
<bootstrap class="Cake\TestSuite\Fixture\Extension\PHPUnitExtension"/>
</extensions>
<!-- Ignore vendor tests in code coverage reports -->
<source>
<include>
<directory suffix=".php">src/</directory>
<directory suffix=".php">plugins/*/src/</directory>
</include>
<exclude>
<file>src/Console/Installer.php</file>
</exclude>
</source>
</phpunit>

0
plugins/.gitkeep Normal file
View File

15
psalm.xml Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src/"/>
<ignoreFiles>
<directory name="vendor/"/>
</ignoreFiles>
</projectFiles>
</psalm>

0
resources/.gitkeep Normal file
View File

94
src/Application.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace App;
use Cake\Core\Configure;
use Cake\Core\ContainerInterface;
use Cake\Datasource\FactoryLocator;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\BaseApplication;
use Cake\Http\Middleware\BodyParserMiddleware;
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\ORM\Locator\TableLocator;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
// dodaj
use Authentication\AuthenticationService;
use Authentication\Identifier\AbstractIdentifier;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ServerRequestInterface;
use Authentication\Identifier\IdentifierInterface;
use Cake\Routing\Router;
// Zmodyfikuj deklaracje klasy poprzez implements
class Application extends BaseApplication
implements AuthenticationServiceProviderInterface {
public function bootstrap(): void
{
parent::bootstrap();
$this->addPlugin('Authentication'); // zaladuj
if (PHP_SAPI !== 'cli') {
FactoryLocator::add('Table', (
new TableLocator())->allowFallbackClass(false));
}
}
public function middleware(MiddlewareQueue $middlewareQueue):
MiddlewareQueue
{
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error'), $this))
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime'),
]))
->add(new RoutingMiddleware($this))
->add(new BodyParserMiddleware())
->add(new CsrfProtectionMiddleware(['httponly' => true]))
// Dodaj AuthenticationMiddleware
// za routing i body parser.
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
public function services(ContainerInterface $container): void
{
}
// Dodaj metod˛e
public function getAuthenticationService(ServerRequestInterface $request):
AuthenticationServiceInterface
{
$service = new AuthenticationService();
$service->setConfig([
'unauthenticatedRedirect' => [
'prefix' => false,
'plugin' => false,
'controller' => 'Users',
'action' => 'login',
],
'queryParam' => 'redirect',
]);
// login i haslo
$fields = [
AbstractIdentifier::CREDENTIAL_USERNAME => 'email',
AbstractIdentifier::CREDENTIAL_PASSWORD => 'password'
];
$passwordIdentifier = [
'Authentication.Password' => [
'fields' => $fields,
],
];
$service->loadAuthenticator('Authentication.Session', [
'identifier' => $passwordIdentifier,
]);
$service->loadAuthenticator('Authentication.Form', [
'identifier' => $passwordIdentifier,
'fields' => $fields,
'loginUrl' => Router::url([
'prefix' => false,
'plugin' => null,
'controller' => 'Users',
'action' => 'login',
]),
]);
return $service;
}
}

260
src/Console/Installer.php Normal file
View File

@@ -0,0 +1,260 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\Console;
if (!defined('STDIN')) {
define('STDIN', fopen('php://stdin', 'r'));
}
use Cake\Codeception\Console\Installer as CodeceptionInstaller;
use Cake\Utility\Security;
use Composer\IO\IOInterface;
use Composer\Script\Event;
use Exception;
/**
* Provides installation hooks for when this application is installed through
* composer. Customize this class to suit your needs.
*/
class Installer
{
/**
* An array of directories to be made writable
*
* @var list<string>
*/
public const WRITABLE_DIRS = [
'logs',
'tmp',
'tmp/cache',
'tmp/cache/models',
'tmp/cache/persistent',
'tmp/cache/views',
'tmp/sessions',
'tmp/tests',
];
/**
* Does some routine installation tasks so people don't have to.
*
* @param \Composer\Script\Event $event The composer event object.
* @throws \Exception Exception raised by validator.
* @return void
*/
public static function postInstall(Event $event): void
{
$io = $event->getIO();
$rootDir = dirname(__DIR__, 2);
static::createAppLocalConfig($rootDir, $io);
static::createWritableDirectories($rootDir, $io);
static::setFolderPermissions($rootDir, $io);
static::setSecuritySalt($rootDir, $io);
if (class_exists(CodeceptionInstaller::class)) {
CodeceptionInstaller::customizeCodeceptionBinary($event);
}
}
/**
* Create config/app_local.php file if it does not exist.
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @return void
*/
public static function createAppLocalConfig(string $dir, IOInterface $io): void
{
$appLocalConfig = $dir . '/config/app_local.php';
$appLocalConfigTemplate = $dir . '/config/app_local.example.php';
if (!file_exists($appLocalConfig)) {
copy($appLocalConfigTemplate, $appLocalConfig);
$io->write('Created `config/app_local.php` file');
}
}
/**
* Create the `logs` and `tmp` directories.
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @return void
*/
public static function createWritableDirectories(string $dir, IOInterface $io): void
{
foreach (static::WRITABLE_DIRS as $path) {
$path = $dir . '/' . $path;
if (!file_exists($path)) {
mkdir($path);
$io->write('Created `' . $path . '` directory');
}
}
}
/**
* Set globally writable permissions on the "tmp" and "logs" directory.
*
* This is not the most secure default, but it gets people up and running quickly.
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @return void
*/
public static function setFolderPermissions(string $dir, IOInterface $io): void
{
// ask if the permissions should be changed
if ($io->isInteractive()) {
$validator = function (string $arg): string {
if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
return $arg;
}
throw new Exception('This is not a valid answer. Please choose Y or n.');
};
$setFolderPermissions = $io->askAndValidate(
'<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
$validator,
10,
'Y',
);
if (in_array($setFolderPermissions, ['n', 'N'])) {
return;
}
}
// Change the permissions on a path and output the results.
$changePerms = function (string $path) use ($io): void {
$currentPerms = fileperms($path) & 0777;
$worldWritable = $currentPerms | 0007;
if ($worldWritable == $currentPerms) {
return;
}
$res = chmod($path, $worldWritable);
if ($res) {
$io->write('Permissions set on ' . $path);
} else {
$io->write('Failed to set permissions on ' . $path);
}
};
$walker = function (string $dir) use (&$walker, $changePerms): void {
$files = array_diff(scandir($dir) ?: [], ['.', '..']);
foreach ($files as $file) {
$path = $dir . '/' . $file;
if (!is_dir($path)) {
continue;
}
$changePerms($path);
$walker($path);
}
};
$walker($dir . '/tmp');
$changePerms($dir . '/tmp');
$changePerms($dir . '/logs');
}
/**
* Set the security.salt value in the application's config file.
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @return void
*/
public static function setSecuritySalt(string $dir, IOInterface $io): void
{
$newKey = hash('sha256', Security::randomBytes(64));
static::setSecuritySaltInFile($dir, $io, $newKey, 'app_local.php');
}
/**
* Set the security.salt value in a given file
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @param string $newKey key to set in the file
* @param string $file A path to a file relative to the application's root
* @return void
*/
public static function setSecuritySaltInFile(string $dir, IOInterface $io, string $newKey, string $file): void
{
$config = $dir . '/config/' . $file;
$content = file_get_contents($config);
if ($content === false) {
$io->write('Config file not readable or not found: config/' . $file);
return;
}
$content = str_replace('__SALT__', $newKey, $content, $count);
if ($count == 0) {
$io->write('No Security.salt placeholder to replace.');
return;
}
$result = file_put_contents($config, $content);
if ($result) {
$io->write('Updated Security.salt value in config/' . $file);
return;
}
$io->write('Unable to update Security.salt value.');
}
/**
* Set the APP_NAME value in a given file
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @param string $appName app name to set in the file
* @param string $file A path to a file relative to the application's root
* @return void
*/
public static function setAppNameInFile(string $dir, IOInterface $io, string $appName, string $file): void
{
$config = $dir . '/config/' . $file;
$content = file_get_contents($config);
if ($content === false) {
$io->write('Config file not readable or not found: config/' . $file);
return;
}
$content = str_replace('__APP_NAME__', $appName, $content, $count);
if ($count == 0) {
$io->write('No __APP_NAME__ placeholder to replace.');
return;
}
$result = file_put_contents($config, $content);
if ($result) {
$io->write('Updated __APP_NAME__ value in config/' . $file);
return;
}
$io->write('Unable to update __APP_NAME__ value.');
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use Cake\Controller\Controller;
class AppController extends Controller
{
public function initialize(): void
{
parent::initialize();
$this->loadComponent('Flash');
// dopisz poni˙zsz ˛a lini˛e
$this->loadComponent('Authentication.Authentication');
//$this->loadComponent('FormProtection');
}
}

View File

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.3.4
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\Controller;
use Cake\Event\EventInterface;
/**
* Error Handling Controller
*
* Controller used by ExceptionRenderer to render error responses.
*/
class ErrorController extends AppController
{
/**
* Initialization hook method.
*
* @return void
*/
public function initialize(): void
{
// Only add parent::initialize() if you are confident your `AppController` is safe.
}
/**
* beforeFilter callback.
*
* @param \Cake\Event\EventInterface<\Cake\Controller\Controller> $event Event.
* @return void
*/
public function beforeFilter(EventInterface $event): void
{
}
/**
* beforeRender callback.
*
* @param \Cake\Event\EventInterface<\Cake\Controller\Controller> $event Event.
* @return void
*/
public function beforeRender(EventInterface $event): void
{
parent::beforeRender($event);
$this->viewBuilder()->setTemplatePath('Error');
}
/**
* afterFilter callback.
*
* @param \Cake\Event\EventInterface<\Cake\Controller\Controller> $event Event.
* @return void
*/
public function afterFilter(EventInterface $event): void
{
}
}

View File

@@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.2.9
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\Controller;
use Cake\Core\Configure;
use Cake\Http\Exception\ForbiddenException;
use Cake\Http\Exception\NotFoundException;
use Cake\Http\Response;
use Cake\View\Exception\MissingTemplateException;
/**
* Static content controller
*
* This controller will render views from templates/Pages/
*
* @link https://book.cakephp.org/5/en/controllers/pages-controller.html
*/
class PagesController extends AppController
{
/**
* Displays a view
*
* @param string ...$path Path segments.
* @return \Cake\Http\Response|null
* @throws \Cake\Http\Exception\ForbiddenException When a directory traversal attempt.
* @throws \Cake\View\Exception\MissingTemplateException When the view file could not
* be found and in debug mode.
* @throws \Cake\Http\Exception\NotFoundException When the view file could not
* be found and not in debug mode.
* @throws \Cake\View\Exception\MissingTemplateException In debug mode.
*/
public function display(string ...$path): ?Response
{
if (!$path) {
return $this->redirect('/');
}
if (in_array('..', $path, true) || in_array('.', $path, true)) {
throw new ForbiddenException();
}
$page = $subpage = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
$this->set(compact('page', 'subpage'));
try {
return $this->render(implode('/', $path));
} catch (MissingTemplateException $exception) {
if (Configure::read('debug')) {
throw $exception;
}
throw new NotFoundException();
}
}
}

View File

@@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace App\Controller;
/**
* Tools Controller
*
* @property \App\Model\Table\ToolsTable $Tools
*/
class ToolsController extends AppController
{
/**
* Index method
*
* @return \Cake\Http\Response|null|void Renders view
*/
public function index()
{
$query = $this->Tools->find();
$tools = $this->paginate($query);
$this->set(compact('tools'));
}
/**
* View method
*
* @param string|null $id Tool id.
* @return \Cake\Http\Response|null|void Renders view
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$tool = $this->Tools->get($id, contain: []);
$this->set(compact('tool'));
}
/**
* Add method
*
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$tool = $this->Tools->newEmptyEntity();
if ($this->request->is('post')) {
$tool = $this->Tools->patchEntity($tool, $this->request->getData());
if ($this->Tools->save($tool)) {
$this->Flash->success(__('The tool has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The tool could not be saved. Please, try again.'));
}
$this->set(compact('tool'));
}
/**
* Edit method
*
* @param string|null $id Tool id.
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null)
{
$tool = $this->Tools->get($id, contain: []);
if ($this->request->is(['patch', 'post', 'put'])) {
$tool = $this->Tools->patchEntity($tool, $this->request->getData());
if ($this->Tools->save($tool)) {
$this->Flash->success(__('The tool has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The tool could not be saved. Please, try again.'));
}
$this->set(compact('tool'));
}
/**
* Delete method
*
* @param string|null $id Tool id.
* @return \Cake\Http\Response|null Redirects to index.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$tool = $this->Tools->get($id);
if ($this->Tools->delete($tool)) {
$this->Flash->success(__('The tool has been deleted.'));
} else {
$this->Flash->error(__('The tool could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
}

View File

@@ -0,0 +1,135 @@
<?php
declare(strict_types=1);
namespace App\Controller;
/**
* Users Controller
*
* @property \App\Model\Table\UsersTable $Users
*/
class UsersController extends AppController
{
/**
* Index method
*
* @return \Cake\Http\Response|null|void Renders view
*/
public function index()
{
$query = $this->Users->find();
$users = $this->paginate($query);
$this->set(compact('users'));
}
/**
* View method
*
* @param string|null $id User id.
* @return \Cake\Http\Response|null|void Renders view
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$user = $this->Users->get($id, contain: []);
$this->set(compact('user'));
}
/**
* Add method
*
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$user = $this->Users->newEmptyEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
}
/**
* Edit method
*
* @param string|null $id User id.
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null)
{
$user = $this->Users->get($id, contain: []);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
}
/**
* Delete method
*
* @param string|null $id User id.
* @return \Cake\Http\Response|null Redirects to index.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success(__('The user has been deleted.'));
} else {
$this->Flash->error(__('The user could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
public function initialize(): void
{
parent::initialize();
$this->Authentication->allowUnauthenticated(['login']);
}
public function login()
{
$this->request->allowMethod(['get', 'post']);
$result = $this->Authentication->getResult();
if ($result->isValid()) {
$this->Flash->success(__('Zalogowano poprawnie'));
$redirect = $this->Authentication->getLoginRedirect();
if ($redirect) {
return $this->redirect($redirect);
}
}
if ($this->request->is('post')) {
$this->Flash->error(__('Błędna nazwa użytkownika lub hasło'));
}
}
public function logout()
{
$result = $this->Authentication->getResult();
if ($result && $result->isValid()) {
$this->Authentication->logout();
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
}
}

View File

38
src/Model/Entity/Tool.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* Tool Entity
*
* @property int $id
* @property string $name
* @property string|null $description
* @property int $quantity
* @property bool $active
* @property \Cake\I18n\DateTime $created
* @property \Cake\I18n\DateTime|null $modified
*/
class Tool extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array<string, bool>
*/
protected array $_accessible = [
'name' => true,
'description' => true,
'quantity' => true,
'active' => true,
'created' => true,
'modified' => true,
];
}

24
src/Model/Entity/User.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Authentication\PasswordHasher\DefaultPasswordHasher;
class User extends Entity
{
protected array $_accessible = [
'name' => true,
'email' => true,
'password' => true,
'created' => true,
'modified' => true,
];
protected array $_hidden = [
'password',
];
// Automatycznie hastuje hasło, gdy go zmienisz.
protected function _setPassword(string $password)
{
$hasher = new DefaultPasswordHasher();
return $hasher->hash($password);
}
}

View File

@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Query\SelectQuery;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Tools Model
*
* @method \App\Model\Entity\Tool newEmptyEntity()
* @method \App\Model\Entity\Tool newEntity(array $data, array $options = [])
* @method array<\App\Model\Entity\Tool> newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Tool get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
* @method \App\Model\Entity\Tool findOrCreate($search, ?callable $callback = null, array $options = [])
* @method \App\Model\Entity\Tool patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method array<\App\Model\Entity\Tool> patchEntities(iterable $entities, array $data, array $options = [])
* @method \App\Model\Entity\Tool|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
* @method \App\Model\Entity\Tool saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
* @method iterable<\App\Model\Entity\Tool>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tool>|false saveMany(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\Tool>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tool> saveManyOrFail(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\Tool>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tool>|false deleteMany(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\Tool>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tool> deleteManyOrFail(iterable $entities, array $options = [])
*
* @mixin \Cake\ORM\Behavior\TimestampBehavior
*/
class ToolsTable extends Table
{
/**
* Initialize method
*
* @param array<string, mixed> $config The configuration for the Table.
* @return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('tools');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator
->scalar('name')
->maxLength('name', 150)
->requirePresence('name', 'create')
->notEmptyString('name');
$validator
->scalar('description')
->allowEmptyString('description');
$validator
->integer('quantity')
->notEmptyString('quantity');
$validator
->boolean('active')
->notEmptyString('active');
return $validator;
}
}

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Query\SelectQuery;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Users Model
*
* @method \App\Model\Entity\User newEmptyEntity()
* @method \App\Model\Entity\User newEntity(array $data, array $options = [])
* @method array<\App\Model\Entity\User> newEntities(array $data, array $options = [])
* @method \App\Model\Entity\User get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args)
* @method \App\Model\Entity\User findOrCreate($search, ?callable $callback = null, array $options = [])
* @method \App\Model\Entity\User patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method array<\App\Model\Entity\User> patchEntities(iterable $entities, array $data, array $options = [])
* @method \App\Model\Entity\User|false save(\Cake\Datasource\EntityInterface $entity, array $options = [])
* @method \App\Model\Entity\User saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = [])
* @method iterable<\App\Model\Entity\User>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\User>|false saveMany(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\User>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\User> saveManyOrFail(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\User>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\User>|false deleteMany(iterable $entities, array $options = [])
* @method iterable<\App\Model\Entity\User>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\User> deleteManyOrFail(iterable $entities, array $options = [])
*
* @mixin \Cake\ORM\Behavior\TimestampBehavior
*/
class UsersTable extends Table
{
/**
* Initialize method
*
* @param array<string, mixed> $config The configuration for the Table.
* @return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator
->scalar('name')
->maxLength('name', 150)
->requirePresence('name', 'create')
->notEmptyString('name');
$validator
->email('email')
->requirePresence('email', 'create')
->notEmptyString('email');
$validator
->scalar('password')
->maxLength('password', 255)
->requirePresence('password', 'create')
->notEmptyString('password');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['email']), ['errorField' => 'email']);
return $rules;
}
}

46
src/View/AjaxView.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.0.4
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\View;
/**
* A view class that is used for AJAX responses.
* Currently only switches the default layout and sets the response type -
* which just maps to text/html by default.
*/
class AjaxView extends AppView
{
/**
* The name of the layout file to render the view inside of. The name
* specified is the filename of the layout in /templates/Layout without
* the .php extension.
*
* @var string
*/
protected string $layout = 'ajax';
/**
* Initialization hook method.
*
* @return void
*/
public function initialize(): void
{
parent::initialize();
$this->response = $this->response->withType('ajax');
}
}

41
src/View/AppView.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\View;
use Cake\View\View;
/**
* Application View
*
* Your application's default view class
*
* @link https://book.cakephp.org/5/en/views.html#the-app-view
*/
class AppView extends View
{
/**
* Initialization hook method.
*
* Use this method to add common initialization code like adding helpers.
*
* e.g. `$this->addHelper('Html');`
*
* @return void
*/
public function initialize(): void
{
}
}

0
src/View/Cell/.gitkeep Normal file
View File

0
src/View/Helper/.gitkeep Normal file
View File

View File

@@ -0,0 +1,10 @@
@echo off
REM Uruchom serwer CakePHP z Dockera na porcie 8765
docker run -d --name wmt_cake_server -p 8765:80 wmt_cake
REM Uruchom tunel Cloudflare w tym samym oknie
cloudflared tunnel run 28d34607-3035-4448-8cf8-17821539f59c
pause

View File

@@ -0,0 +1,15 @@
<?php
/**
* @var \App\View\AppView $this
* @var string $message
* @var string $url
*/
use Cake\Core\Configure;
// ...existing code...
?>
<h2><?= h($message) ?></h2>
<p class="error">
<strong>Błąd: </strong>
Żądany adres <?= "<strong>'{$url}'</strong>" ?> nie został odnaleziony na tym serwerze.
</p>

View File

@@ -0,0 +1,16 @@
<?php
/**
* @var \App\View\AppView $this
* @var string $message
* @var string $url
*/
use Cake\Core\Configure;
use Cake\Error\Debugger;
// ...existing code...
?>
<h2>Wystąpił błąd wewnętrzny.</h2>
<p class="error">
<strong>Błąd: </strong>
<?= h($message) ?>
</p>

241
templates/Pages/home.php Normal file
View File

@@ -0,0 +1,241 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
use Cake\Cache\Cache;
use Cake\Core\Configure;
use Cake\Core\Plugin;
use Cake\Datasource\ConnectionManager;
use Cake\Error\Debugger;
use Cake\Http\Exception\NotFoundException;
$this->disableAutoLayout();
$checkConnection = function (string $name) {
$error = null;
$connected = false;
try {
ConnectionManager::get($name)->getDriver()->connect();
// No exception means success
$connected = true;
} catch (Exception $connectionError) {
$error = $connectionError->getMessage();
if (method_exists($connectionError, 'getAttributes')) {
$attributes = $connectionError->getAttributes();
if (isset($attributes['message'])) {
$error .= '<br />' . $attributes['message'];
}
}
if ($name === 'debug_kit') {
$error = 'Try adding your current <b>top level domain</b> to the
<a href="https://book.cakephp.org/debugkit/5/en/index.html#configuration" target="_blank">DebugKit.safeTld</a>
config and reload.';
if (!in_array('sqlite', \PDO::getAvailableDrivers())) {
$error .= '<br />You need to install the PHP extension <code>pdo_sqlite</code> so DebugKit can work properly.';
}
}
}
return compact('connected', 'error');
};
if (!Configure::read('debug')) :
throw new NotFoundException(
'Please replace templates/Pages/home.php with your own version or re-enable debug mode.'
);
endif;
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
CakePHP: the rapid development PHP framework:
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
<?= $this->Html->css(['normalize.min', 'milligram.min', 'fonts', 'cake', 'home']) ?>
<?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
</head>
<body>
<header>
<div class="container text-center">
<a href="https://cakephp.org/" target="_blank" rel="noopener">
<img alt="CakePHP" src="https://cakephp.org/v2/img/logos/CakePHP_Logo.svg" width="350" />
</a>
<h1>
Welcome to CakePHP <?= h(Configure::version()) ?> Chiffon (🍰)
</h1>
</div>
</header>
<main class="main">
<div class="container">
<div class="content">
<div class="row">
<div class="column">
<div class="message default text-center">
<small>Please be aware that this page will not be shown if you turn off debug mode unless you replace templates/Pages/home.php with your own version.</small>
</div>
<div id="url-rewriting-warning" style="padding: 1rem; background: #fcebea; color: #cc1f1a; border-color: #ef5753;">
<ul>
<li class="bullet problem">
URL rewriting is not properly configured on your server.<br />
1) <a target="_blank" rel="noopener" href="https://book.cakephp.org/5/en/installation.html#url-rewriting">Help me configure it</a><br />
2) <a target="_blank" rel="noopener" href="https://book.cakephp.org/5/en/development/configuration.html#general-configuration">I don't / can't use URL rewriting</a>
</li>
</ul>
</div>
<?php Debugger::checkSecurityKeys(); ?>
</div>
</div>
<div class="row">
<div class="column">
<h4>Environment</h4>
<ul>
<?php if (version_compare(PHP_VERSION, '8.1.0', '>=')) : ?>
<li class="bullet success">Your version of PHP is 8.1.0 or higher (detected <?= PHP_VERSION ?>).</li>
<?php else : ?>
<li class="bullet problem">Your version of PHP is too low. You need PHP 8.1.0 or higher to use CakePHP (detected <?= PHP_VERSION ?>).</li>
<?php endif; ?>
<?php if (extension_loaded('mbstring')) : ?>
<li class="bullet success">Your version of PHP has the mbstring extension loaded.</li>
<?php else : ?>
<li class="bullet problem">Your version of PHP does NOT have the mbstring extension loaded.</li>
<?php endif; ?>
<?php if (extension_loaded('openssl')) : ?>
<li class="bullet success">Your version of PHP has the openssl extension loaded.</li>
<?php else : ?>
<li class="bullet problem">Your version of PHP does NOT have the openssl extension loaded.</li>
<?php endif; ?>
<?php if (extension_loaded('intl')) : ?>
<li class="bullet success">Your version of PHP has the intl extension loaded.</li>
<?php else : ?>
<li class="bullet problem">Your version of PHP does NOT have the intl extension loaded.</li>
<?php endif; ?>
<?php if (ini_get('zend.assertions') !== '1') : ?>
<li class="bullet problem">You should set <code>zend.assertions</code> to <code>1</code> in your <code>php.ini</code> for your development environment.</li>
<?php endif; ?>
</ul>
</div>
<div class="column">
<h4>Filesystem</h4>
<ul>
<?php if (is_writable(TMP)) : ?>
<li class="bullet success">Your tmp directory is writable.</li>
<?php else : ?>
<li class="bullet problem">Your tmp directory is NOT writable.</li>
<?php endif; ?>
<?php if (is_writable(LOGS)) : ?>
<li class="bullet success">Your logs directory is writable.</li>
<?php else : ?>
<li class="bullet problem">Your logs directory is NOT writable.</li>
<?php endif; ?>
<?php $settings = Cache::getConfig('_cake_translations_'); ?>
<?php if (!empty($settings)) : ?>
<li class="bullet success">The <em><?= h($settings['className']) ?></em> is being used for core caching. To change the config edit config/app.php</li>
<?php else : ?>
<li class="bullet problem">Your cache is NOT working. Please check the settings in config/app.php</li>
<?php endif; ?>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="column">
<h4>Database</h4>
<?php
$result = $checkConnection('default');
?>
<ul>
<?php if ($result['connected']) : ?>
<li class="bullet success">CakePHP is able to connect to the database.</li>
<?php else : ?>
<li class="bullet problem">CakePHP is NOT able to connect to the database.<br /><?= h($result['error']) ?></li>
<?php endif; ?>
</ul>
</div>
<div class="column">
<h4>DebugKit</h4>
<ul>
<?php if (Plugin::isLoaded('DebugKit')) : ?>
<li class="bullet success">DebugKit is loaded.</li>
<?php
$result = $checkConnection('debug_kit');
?>
<?php if ($result['connected']) : ?>
<li class="bullet success">DebugKit can connect to the database.</li>
<?php else : ?>
<li class="bullet problem">There are configuration problems present which need to be fixed:<br /><?= $result['error'] ?></li>
<?php endif; ?>
<?php else : ?>
<li class="bullet problem">DebugKit is <strong>not</strong> loaded.</li>
<?php endif; ?>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="column links">
<h3>Getting Started</h3>
<a target="_blank" rel="noopener" href="https://book.cakephp.org/5/en/">CakePHP Documentation</a>
<a target="_blank" rel="noopener" href="https://book.cakephp.org/5/en/tutorials-and-examples/cms/installation.html">The 20 min CMS Tutorial</a>
</div>
</div>
<hr>
<div class="row">
<div class="column links">
<h3>Help and Bug Reports</h3>
<a target="_blank" rel="noopener" href="https://slack-invite.cakephp.org/">Slack</a>
<a target="_blank" rel="noopener" href="https://github.com/cakephp/cakephp/issues">CakePHP Issues</a>
<a target="_blank" rel="noopener" href="https://discourse.cakephp.org/">CakePHP Forum</a>
</div>
</div>
<hr>
<div class="row">
<div class="column links">
<h3>Docs and Downloads</h3>
<a target="_blank" rel="noopener" href="https://api.cakephp.org/">CakePHP API</a>
<a target="_blank" rel="noopener" href="https://bakery.cakephp.org">The Bakery</a>
<a target="_blank" rel="noopener" href="https://book.cakephp.org/5/en/">CakePHP Documentation</a>
<a target="_blank" rel="noopener" href="https://plugins.cakephp.org">CakePHP plugins repo</a>
<a target="_blank" rel="noopener" href="https://github.com/cakephp/">CakePHP Code</a>
<a target="_blank" rel="noopener" href="https://github.com/FriendsOfCake/awesome-cakephp">CakePHP Awesome List</a>
<a target="_blank" rel="noopener" href="https://www.cakephp.org">CakePHP</a>
</div>
</div>
<hr>
<div class="row">
<div class="column links">
<h3>Training and Certification</h3>
<a target="_blank" rel="noopener" href="https://cakefoundation.org/">Cake Software Foundation</a>
<a target="_blank" rel="noopener" href="https://training.cakephp.org/">CakePHP Training</a>
</div>
</div>
</div>
</div>
</main>
</body>
</html>

40
templates/Tools/add.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Tool $tool
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading"><?= __('Operacje') ?></h4>
<?= $this->Html->link(__('Powrót'),
['action' => 'index'],
['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="tools form content">
<?= $this->Form->create($tool) ?>
<fieldset>
<legend><?= __('Dodawanie narzędzia') ?></legend>
<?php
echo $this->Form->control('name',
['label'=>'Nazwa',
'placeholder'=>'Wpisz nazwę']);
echo $this->Form->control('description',
['label'=>'Opis',
'placeholder'=>'Dowolny opis']);
echo $this->Form->control('quantity',
['label'=>'Ilość',
'default'=>1]);
echo $this->Form->control('active',
['label'=>'Aktywny',
'default'=>true]);
?>
</fieldset>
<?= $this->Form->button(__('Zapisz')) ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>

40
templates/Tools/edit.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Tool $tool
*/
?>
<<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading"><?= __('Operacje') ?></h4>
<?= $this->Html->link(__('Powrót'),
['action' => 'index'],
['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="tools form content">
<?= $this->Form->create($tool) ?>
<fieldset>
<legend><?= __('Dodawanie narzędzia') ?></legend>
<?php
echo $this->Form->control('name',
['label' => 'Nazwa',
'placeholder' => 'Wpisz nazwę']);
echo $this->Form->control('description',
['label'=>'Opis',
'placeholder'=>'Dowolny opis']);
echo $this->Form->control('quantity',
['label'=>'Ilość',
'default'=>1]);
echo $this->Form->control('active',
['label'=>'Aktywny',
'default'=>true]);
?>
</fieldset>
<?= $this->Form->button(__('Zapisz')) ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>

62
templates/Tools/index.php Normal file
View File

@@ -0,0 +1,62 @@
<?php
/**
* @var \App\View\AppView $this
* @var iterable<\App\Model\Entity\Tool> $tools
*/
?>
<div class="tools index content">
<?= $this->Html->link(__('Dodaj nowe'),
['action' => 'add'],
['class' => 'button float-right'])
?>
<h3><?= __('Lista narzedzi') ?></h3>
<div class="table-responsive">
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('id') ?></th>
<th><?= $this->Paginator->sort('name','Nazwa') ?></th>
<th><?= $this->Paginator->sort('quantity','Ilość') ?></th>
<th><?= $this->Paginator->sort('active','Aktywne') ?></th>
<th><?= $this->Paginator->sort('created','Utworzono') ?></th>
<th><?= $this->Paginator->sort('modified','Zmodyfikowano') ?></th>
<th class="actions"><?= __('Operacje') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($tools as $tool): ?>
<tr>
<td><?= $this->Number->format($tool->id) ?></td>
<td><?= h($tool->name) ?></td>
<td><?= $this->Number->format($tool->quantity) ?></td>
<td><?= h($tool->active) ?></td>
<td><?= $tool->created ? $tool->created->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
<td><?= $tool->modified ? $tool->modified->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
<td class="actions">
<?= $this->Html->link(__('Podgląd'),
['action' => 'view', $tool->id]) ?>
<?= $this->Html->link(__('Edytuj'),
['action' => 'edit', $tool->id]) ?>
<?= $this->Form->postLink( __('Usuń'),
['action' => 'delete', $tool->id],
['method' => 'delete',
'confirm' => __('Na pewno usunąć {0}?', $tool->name),])
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('pierwszy')) ?>
<?= $this->Paginator->prev('< ' . __('poprzedni')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('następny') . ' >') ?>
<?= $this->Paginator->last(__('ostatni') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(__('Strona {{page}} z {{pages}},
widok {{current}} rekordów z {{count}}')) ?></p>
</div>
</div>

58
templates/Tools/view.php Normal file
View File

@@ -0,0 +1,58 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Tool $tool
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading"><?= __('Operacje') ?></h4>
<?= $this->Html->link(__('Edytuj narzędzie'),
['action' => 'edit', $tool->id],
['class' => 'side-nav-item']) ?>
<?= $this->Form->postLink(__('Usuń'),
['action' => 'delete', $tool->id],
['confirm' => __('Na pewno usunąć {0}?', $tool->name), 'class' => 'side-nav-item']) ?>
<?= $this->Html->link(__('Powrót'),
['action' => 'index'],
['class' => 'side-nav-item']) ?>
<?= $this->Html->link(__('Dodaj'),
['action' => 'add'],
['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="tools view content">
<h3><?= h($tool->name) ?></h3>
<table>
<tr>
<th><?= __('Nazwa') ?></th>
<td><?= h($tool->name) ?></td>
</tr>
<tr>
<th><?= __('Ilość') ?></th>
<td><?= $this->Number->format($tool->quantity) ?></td>
</tr>
<tr>
<th><?= __('Utworzono') ?></th>
<td><?= $tool->created ? $tool->created->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
</tr>
<tr>
<th><?= __('Zmodyfikowano') ?></th>
<td><?= $tool->modified ? $tool->modified->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
</tr>
<tr>
<th><?= __('Aktywne') ?></th>
<td><?= $tool->active ? __('Tak') : __('Nie'); ?></td>
</tr>
</table>
<div class="text">
<strong><?= __('Opis') ?></strong>
<blockquote>
<?= $this->Text->autoParagraph(h($tool->description)); ?>
</blockquote>
</div>
</div>
</div>
</div>

29
templates/Users/add.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\User $user
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading">Operacje</h4>
<?= $this->Html->link('Lista użytkowników', ['action' => 'index'], ['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="users form content">
<?= $this->Form->create($user) ?>
<fieldset>
<legend>Dodaj użytkownika</legend>
<?php
echo $this->Form->control('name', ['label' => 'Nazwa']);
echo $this->Form->control('email', ['label' => 'Email']);
echo $this->Form->control('password', ['label' => 'Hasło']);
?>
</fieldset>
<?= $this->Form->button('Zapisz') ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>

34
templates/Users/edit.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\User $user
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading">Operacje</h4>
<?= $this->Form->postLink(
'Usuń',
['action' => 'delete', $user->id],
['confirm' => 'Czy na pewno chcesz usunąć użytkownika nr {0}?', 'class' => 'side-nav-item']
) ?>
<?= $this->Html->link('Lista użytkowników', ['action' => 'index'], ['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="users form content">
<?= $this->Form->create($user) ?>
<fieldset>
<legend>Edytuj użytkownika</legend>
<?php
echo $this->Form->control('name', ['label' => 'Nazwa']);
echo $this->Form->control('email', ['label' => 'Email']);
echo $this->Form->control('password', ['label' => 'Hasło']);
?>
</fieldset>
<?= $this->Form->button('Zapisz') ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>

57
templates/Users/index.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
/**
* @var \App\View\AppView $this
* @var iterable<\App\Model\Entity\User> $users
*/
?>
<div class="users index content">
<?= $this->Html->link('Dodaj użytkownika', ['action' => 'add'], ['class' => 'button float-right']) ?>
<h3>Użytkownicy</h3>
<div class="table-responsive">
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('id', 'Id') ?></th>
<th><?= $this->Paginator->sort('name', 'Nazwa') ?></th>
<th><?= $this->Paginator->sort('email', 'Email') ?></th>
<th><?= $this->Paginator->sort('created', 'Utworzono') ?></th>
<th><?= $this->Paginator->sort('modified', 'Zmodyfikowano') ?></th>
<th class="actions">Operacje</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?= $this->Number->format($user->id) ?></td>
<td><?= h($user->name) ?></td>
<td><?= h($user->email) ?></td>
<td><?= $user->created ? $user->created->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
<td><?= $user->modified ? $user->modified->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
<td class="actions">
<?= $this->Html->link('Podgląd', ['action' => 'view', $user->id]) ?>
<?= $this->Html->link('Edytuj', ['action' => 'edit', $user->id]) ?>
<?= $this->Form->postLink(
'Usuń',
['action' => 'delete', $user->id],
[
'method' => 'delete',
'confirm' => 'Czy na pewno chcesz usunąć użytkownika nr {0}?',
]
) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< pierwszy') ?>
<?= $this->Paginator->prev('< poprzedni') ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next('następny >') ?>
<?= $this->Paginator->last('ostatni >>') ?>
</ul>
<p><?= $this->Paginator->counter('Strona {{page}} z {{pages}}, wyświetlono {{current}} rekordów z {{count}} wszystkich') ?></p>
</div>
</div>

15
templates/Users/login.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
/**
* @var \App\View\AppView $this
*/
?>
<div class="users form content">
<?= $this->Form->create() ?>
<fieldset>
<legend>Strona logowania</legend>
<?= $this->Form->control('email',['label'=>'Email']) ?>
<?= $this->Form->control('password',['label'=>'Hasło']) ?>
</fieldset>
<?= $this->Form->button('Zaloguj'); ?>
<?= $this->Form->end() ?>
</div>

44
templates/Users/view.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\User $user
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading">Operacje</h4>
<?= $this->Html->link('Edytuj użytkownika', ['action' => 'edit', $user->id], ['class' => 'side-nav-item']) ?>
<?= $this->Form->postLink('Usuń użytkownika', ['action' => 'delete', $user->id], ['confirm' => 'Czy na pewno chcesz usunąć użytkownika nr {0}?', 'class' => 'side-nav-item']) ?>
<?= $this->Html->link('Lista użytkowników', ['action' => 'index'], ['class' => 'side-nav-item']) ?>
<?= $this->Html->link('Dodaj użytkownika', ['action' => 'add'], ['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column column-80">
<div class="users view content">
<h3><?= h($user->name) ?></h3>
<table>
<tr>
<th>Nazwa</th>
<td><?= h($user->name) ?></td>
</tr>
<tr>
<th>Email</th>
<td><?= h($user->email) ?></td>
</tr>
<tr>
<th>Id</th>
<td><?= $this->Number->format($user->id) ?></td>
</tr>
<tr>
<th>Utworzono</th>
<td><?= $user->created ? $user->created->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
</tr>
<tr>
<th>Zmodyfikowano</th>
<td><?= $user->modified ? $user->modified->i18nFormat('dd.MM.yyyy HH:mm') : '' ?></td>
</tr>
</table>
</div>
</div>
</div>

1
templates/cell/.gitkeep Normal file
View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,15 @@
<?php
/**
* @var \App\View\AppView $this
* @var array $params
* @var string $message
*/
$class = 'message';
if (!empty($params['class'])) {
$class .= ' ' . $params['class'];
}
if (!isset($params['escape']) || $params['escape'] !== false) {
$message = h($message);
}
?>
<div class="<?= h($class) ?>" onclick="this.classList.add('hidden');"><?= $message ?></div>

View File

@@ -0,0 +1,11 @@
<?php
/**
* @var \App\View\AppView $this
* @var array $params
* @var string $message
*/
if (!isset($params['escape']) || $params['escape'] !== false) {
$message = h($message);
}
?>
<div class="message error" onclick="this.classList.add('hidden');"><?= $message ?></div>

View File

@@ -0,0 +1,11 @@
<?php
/**
* @var \App\View\AppView $this
* @var array $params
* @var string $message
*/
if (!isset($params['escape']) || $params['escape'] !== false) {
$message = h($message);
}
?>
<div class="message" onclick="this.classList.add('hidden');"><?= $message ?></div>

View File

@@ -0,0 +1,11 @@
<?php
/**
* @var \App\View\AppView $this
* @var array $params
* @var string $message
*/
if (!isset($params['escape']) || $params['escape'] !== false) {
$message = h($message);
}
?>
<div class="message success" onclick="this.classList.add('hidden')"><?= $message ?></div>

View File

@@ -0,0 +1,11 @@
<?php
/**
* @var \App\View\AppView $this
* @var array $params
* @var string $message
*/
if (!isset($params['escape']) || $params['escape'] !== false) {
$message = h($message);
}
?>
<div class="message warning" onclick="this.classList.add('hidden');"><?= $message ?></div>

View File

@@ -0,0 +1,22 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \Cake\View\View $this
* @var string $content
*/
$lines = explode("\n", $content);
foreach ($lines as $line) :
echo '<p> ' . $line . "</p>\n";
endforeach;

View File

@@ -0,0 +1,18 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \Cake\View\View $this
* @var string $content
*/
echo $content;

17
templates/layout/ajax.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
echo $this->fetch('content');

View File

@@ -0,0 +1,41 @@
<?php
$cakeDescription = 'NarzędziaWMT';
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
<?= $cakeDescription ?>:
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
<?= $this->Html->css(['normalize.min', 'milligram.min', 'fonts', 'cake']) ?><?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
</head>
<body>
<nav class="top-nav">
<div class="top-nav-title">
<a href="<?= $this->Url->build('/') ?>"><span>Narzędzia</span>WMT</a>
</div>
<div class="top-nav-links">
<a href="<?= $this->Url->build('/users') ?>">Użytkownicy</a>
<?php if ($this->request->getAttribute('identity')): ?>
<a href="<?= $this->Url->build('/users/logout') ?>">Wyloguj</a>
<?php else: ?>
<a href="<?= $this->Url->build('/users/login') ?>">Zaloguj</a>
<?php endif; ?>
</div>
</nav>
<main class="main">
<div class="container">
<?= $this->Flash->render() ?>
<?= $this->fetch('content') ?>
</div>
</main>
<footer>
</footer>
</body>
</html>

View File

@@ -0,0 +1,25 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title><?= $this->fetch('title') ?></title>
</head>
<body>
<?= $this->fetch('content') ?>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
echo $this->fetch('content');

View File

@@ -0,0 +1,39 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<title>
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
<?= $this->Html->css(['normalize.min', 'milligram.min', 'fonts', 'cake']) ?>
<?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
</head>
<body>
<div class="error-container">
<?= $this->Flash->render() ?>
<?= $this->fetch('content') ?>
<?= $this->Html->link(__('Powrót'), 'javascript:history.back()') ?>
</div>
</body>
</html>

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace App\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
/**
* ToolsFixture
*/
class ToolsFixture extends TestFixture
{
/**
* Init method
*
* @return void
*/
public function init(): void
{
$this->records = [
[
'id' => 1,
'name' => 'Lorem ipsum dolor sit amet',
'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.',
'quantity' => 1,
'active' => 1,
'created' => '2025-11-20 19:49:28',
'modified' => '2025-11-20 19:49:28',
],
];
parent::init();
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace App\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
/**
* UsersFixture
*/
class UsersFixture extends TestFixture
{
/**
* Init method
*
* @return void
*/
public function init(): void
{
$this->records = [
[
'id' => 1,
'name' => 'Lorem ipsum dolor sit amet',
'email' => 'Lorem ipsum dolor sit amet',
'password' => 'Lorem ipsum dolor sit amet',
'created' => '2025-11-20 20:52:58',
'modified' => '2025-11-20 20:52:58',
],
];
parent::init();
}
}

View File

@@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.3.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\Test\TestCase;
use App\Application;
use Cake\Core\Configure;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* ApplicationTest class
*/
class ApplicationTest extends TestCase
{
use IntegrationTestTrait;
/**
* Test bootstrap in production.
*
* @return void
*/
public function testBootstrap()
{
Configure::write('debug', false);
$app = new Application(dirname(__DIR__, 2) . '/config');
$app->bootstrap();
$plugins = $app->getPlugins();
$this->assertTrue($plugins->has('Bake'), 'plugins has Bake?');
$this->assertFalse($plugins->has('DebugKit'), 'plugins has DebugKit?');
$this->assertTrue($plugins->has('Migrations'), 'plugins has Migrations?');
}
/**
* Test bootstrap add DebugKit plugin in debug mode.
*
* @return void
*/
public function testBootstrapInDebug()
{
Configure::write('debug', true);
$app = new Application(dirname(__DIR__, 2) . '/config');
$app->bootstrap();
$plugins = $app->getPlugins();
$this->assertTrue($plugins->has('DebugKit'), 'plugins has DebugKit?');
}
/**
* testMiddleware
*
* @return void
*/
public function testMiddleware()
{
$app = new Application(dirname(__DIR__, 2) . '/config');
$middleware = new MiddlewareQueue();
$middleware = $app->middleware($middleware);
$this->assertInstanceOf(ErrorHandlerMiddleware::class, $middleware->current());
$middleware->seek(1);
$this->assertInstanceOf(AssetMiddleware::class, $middleware->current());
$middleware->seek(2);
$this->assertInstanceOf(RoutingMiddleware::class, $middleware->current());
}
}

View File

@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 1.2.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace App\Test\TestCase\Controller;
use Cake\Core\Configure;
use Cake\TestSuite\Constraint\Response\StatusCode;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* PagesControllerTest class
*/
class PagesControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* testDisplay method
*
* @return void
*/
public function testDisplay()
{
Configure::write('debug', true);
$this->get('/pages/home');
$this->assertResponseOk();
$this->assertResponseContains('CakePHP');
$this->assertResponseContains('<html>');
}
/**
* Test that missing template renders 404 page in production
*
* @return void
*/
public function testMissingTemplate()
{
Configure::write('debug', false);
$this->get('/pages/not_existing');
$this->assertResponseError();
$this->assertResponseContains('Error');
}
/**
* Test that missing template in debug mode renders missing_template error page
*
* @return void
*/
public function testMissingTemplateInDebug()
{
Configure::write('debug', true);
$this->get('/pages/not_existing');
$this->assertResponseFailure();
$this->assertResponseContains('Missing Template');
$this->assertResponseContains('stack-frames');
$this->assertResponseContains('not_existing.php');
}
/**
* Test directory traversal protection
*
* @return void
*/
public function testDirectoryTraversalProtection()
{
$this->get('/pages/../Layout/ajax');
$this->assertResponseCode(403);
$this->assertResponseContains('Forbidden');
}
/**
* Test that CSRF protection is applied to page rendering.
*
* @return void
*/
public function testCsrfAppliedError()
{
$this->post('/pages/home', ['hello' => 'world']);
$this->assertResponseCode(403);
$this->assertResponseContains('CSRF');
}
/**
* Test that CSRF protection is applied to page rendering.
*
* @return void
*/
public function testCsrfAppliedOk()
{
$this->enableCsrfToken();
$this->post('/pages/home', ['hello' => 'world']);
$this->assertThat(403, $this->logicalNot(new StatusCode($this->_response)));
$this->assertResponseNotContains('CSRF');
}
}

View File

@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Controller;
use App\Controller\ToolsController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\ToolsController Test Case
*
* @link \App\Controller\ToolsController
*/
class ToolsControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array<string>
*/
protected array $fixtures = [
'app.Tools',
];
/**
* Test index method
*
* @return void
* @link \App\Controller\ToolsController::index()
*/
public function testIndex(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test view method
*
* @return void
* @link \App\Controller\ToolsController::view()
*/
public function testView(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test add method
*
* @return void
* @link \App\Controller\ToolsController::add()
*/
public function testAdd(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test edit method
*
* @return void
* @link \App\Controller\ToolsController::edit()
*/
public function testEdit(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test delete method
*
* @return void
* @link \App\Controller\ToolsController::delete()
*/
public function testDelete(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
}

View File

@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Controller;
use App\Controller\UsersController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\UsersController Test Case
*
* @link \App\Controller\UsersController
*/
class UsersControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array<string>
*/
protected array $fixtures = [
'app.Users',
];
/**
* Test index method
*
* @return void
* @link \App\Controller\UsersController::index()
*/
public function testIndex(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test view method
*
* @return void
* @link \App\Controller\UsersController::view()
*/
public function testView(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test add method
*
* @return void
* @link \App\Controller\UsersController::add()
*/
public function testAdd(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test edit method
*
* @return void
* @link \App\Controller\UsersController::edit()
*/
public function testEdit(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test delete method
*
* @return void
* @link \App\Controller\UsersController::delete()
*/
public function testDelete(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
}

View File

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Model\Table;
use App\Model\Table\ToolsTable;
use Cake\TestSuite\TestCase;
/**
* App\Model\Table\ToolsTable Test Case
*/
class ToolsTableTest extends TestCase
{
/**
* Test subject
*
* @var \App\Model\Table\ToolsTable
*/
protected $Tools;
/**
* Fixtures
*
* @var array<string>
*/
protected array $fixtures = [
'app.Tools',
];
/**
* setUp method
*
* @return void
*/
protected function setUp(): void
{
parent::setUp();
$config = $this->getTableLocator()->exists('Tools') ? [] : ['className' => ToolsTable::class];
$this->Tools = $this->getTableLocator()->get('Tools', $config);
}
/**
* tearDown method
*
* @return void
*/
protected function tearDown(): void
{
unset($this->Tools);
parent::tearDown();
}
/**
* Test validationDefault method
*
* @return void
* @link \App\Model\Table\ToolsTable::validationDefault()
*/
public function testValidationDefault(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
}

View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Model\Table;
use App\Model\Table\UsersTable;
use Cake\TestSuite\TestCase;
/**
* App\Model\Table\UsersTable Test Case
*/
class UsersTableTest extends TestCase
{
/**
* Test subject
*
* @var \App\Model\Table\UsersTable
*/
protected $Users;
/**
* Fixtures
*
* @var array<string>
*/
protected array $fixtures = [
'app.Users',
];
/**
* setUp method
*
* @return void
*/
protected function setUp(): void
{
parent::setUp();
$config = $this->getTableLocator()->exists('Users') ? [] : ['className' => UsersTable::class];
$this->Users = $this->getTableLocator()->get('Users', $config);
}
/**
* tearDown method
*
* @return void
*/
protected function tearDown(): void
{
unset($this->Users);
parent::tearDown();
}
/**
* Test validationDefault method
*
* @return void
* @link \App\Model\Table\UsersTable::validationDefault()
*/
public function testValidationDefault(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test buildRules method
*
* @return void
* @link \App\Model\Table\UsersTable::buildRules()
*/
public function testBuildRules(): void
{
$this->markTestIncomplete('Not implemented yet.');
}
}

View File

75
tests/bootstrap.php Normal file
View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
use Cake\Chronos\Chronos;
use Cake\Core\Configure;
use Cake\Datasource\ConnectionManager;
use Cake\TestSuite\ConnectionHelper;
use Migrations\TestSuite\Migrator;
/**
* Test runner bootstrap.
*
* Add additional configuration/setup your application needs when running
* unit tests in this file.
*/
require dirname(__DIR__) . '/vendor/autoload.php';
require dirname(__DIR__) . '/config/bootstrap.php';
if (empty($_SERVER['HTTP_HOST']) && !Configure::read('App.fullBaseUrl')) {
Configure::write('App.fullBaseUrl', 'http://localhost');
}
// DebugKit skips settings these connection config if PHP SAPI is CLI / PHPDBG.
// But since PagesControllerTest is run with debug enabled and DebugKit is loaded
// in application, without setting up these config DebugKit errors out.
ConnectionManager::setConfig('test_debug_kit', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Sqlite',
'database' => TMP . 'debug_kit.sqlite',
'encoding' => 'utf8',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
]);
ConnectionManager::alias('test_debug_kit', 'debug_kit');
// Fixate now to avoid one-second-leap-issues
Chronos::setTestNow(Chronos::now());
// Fixate sessionid early on, as php7.2+
// does not allow the sessionid to be set after stdout
// has been written to.
session_id('cli');
// Connection aliasing needs to happen before migrations are run.
// Otherwise, table objects inside migrations would use the default datasource
ConnectionHelper::addTestAliases();
// Use migrations to build test database schema.
//
// Will rebuild the database if the migration state differs
// from the migration history in files.
//
// If you are not using CakePHP's migrations you can
// hook into your migration tool of choice here or
// load schema from a SQL dump file with
// use Cake\TestSuite\Fixture\SchemaLoader;
// (new SchemaLoader())->loadSqlFiles('./tests/schema.sql', 'test');
(new Migrator())->run();

4
tests/schema.sql Normal file
View File

@@ -0,0 +1,4 @@
-- Test database schema.
--
-- If you are not using CakePHP migrations you can put
-- your application's schema in this file and use it in tests.

5
webroot/.htaccess Normal file
View File

@@ -0,0 +1,5 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

301
webroot/css/cake.css Normal file
View File

@@ -0,0 +1,301 @@
/* Milligram overrides */
:root {
/* The following are official CakePHP colors */
--color-cakephp-red: #d33c43;
--color-cakephp-gray: #404041;
--color-cakephp-blue: #2f85ae;
--color-cakephp-lightblue: #34bdd7;
/* These are additional colors */
--color-lightgray: #606c76;
--color-white: #fff;
--color-main-bg: #f5f7fa;
--color-links: var(--color-cakephp-blue);
--color-links-active: #2a6496;
--color-headings: #363637;
--color-message-success-bg: #e3fcec;
--color-message-success-text: #1f9d55;
--color-message-success-border: #51d88a;
--color-message-warning-bg: #fffabc;
--color-message-warning-text: #8d7b00;
--color-message-warning-border: #d3b800;
--color-message-error-bg: #fcebea;
--color-message-error-text: #cc1f1a;
--color-message-error-border: #ef5753;
--color-message-info-bg: #eff8ff;
--color-message-info-text: #2779bd;
--color-message-info-border: #6cb2eb;
}
.button, button, input[type='button'], input[type='reset'], input[type='submit'] {
background-color: var(--color-cakephp-red);
border-color: var(--color-cakephp-red);
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 400;
background: var(--color-main-bg);
}
.top-nav-links,
.side-nav,
h1, h2, h3, h4, h5, h6 {
font-family: "Raleway", sans-serif;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 400;
color: var(--color-headings);
}
a {
color: var(--color-links);
transition: color 0.2s linear;
}
a:hover,
a:focus,
a:active {
color: var(--color-links-active);
transition: color 0.2s ease-out;
}
.side-nav a,
.top-nav-links a,
th a,
.actions a {
color: var(--color-lightgray);
}
.side-nav a:hover,
.side-nav a:focus,
.actions a:hover,
.actions a:focus {
color: var(--color-links-active);
}
/* Utility */
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
/* Main */
.content {
padding: 2rem;
background: var(--color-white);
border-radius: 0.4rem;
/* Thanks Stripe */
box-shadow: 0 7px 14px 0 rgba(60, 66, 87, 0.1),
0 3px 6px 0 rgba(0, 0, 0, 0.07);
}
.content form {
margin: 0;
}
.actions a {
font-weight: bold;
padding: 0 0.4rem;
}
.actions a:first-child {
padding-left: 0;
}
th {
white-space: nowrap;
}
/* Nav bar */
.top-nav {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 112rem;
padding: 2rem;
margin: 0 auto;
}
.top-nav-title a {
font-size: 2.4rem;
color: var(--color-cakephp-red);
}
.top-nav-title span {
color: var(--color-cakephp-gray);
}
.top-nav-links a {
margin: 0 0.5rem;
}
.top-nav-title a,
.top-nav-links a {
font-weight: bold;
}
.side-nav-item {
display: block;
padding: 0.5rem 0;
}
/* View action */
.view.content .text {
margin-top: 1.2rem;
}
.related {
margin-top: 2rem;
}
/* Flash messages */
.message {
padding: .5rem 1rem;
background: var(--color-message-info-bg);
color: var(--color-message-info-text);
border-color: var(--color-message-info-border);
border-width: 1px;
border-style: solid;
border-radius: 4px;
margin-bottom: 1rem;
cursor: pointer;
}
.message.hidden {
display: none;
}
.message.success {
background: var(--color-message-success-bg);
color: var(--color-message-success-text);
border-color: var(--color-message-success-border);
}
.message.warning {
background: var(--color-message-warning-bg);
color: var(--color-message-warning-text);
border-color: var(--color-message-warning-border);
}
.message.error {
background: var(--color-message-error-bg);
color: var(--color-message-error-text);
border-color: var(--color-message-error-border);
}
/* Forms */
.input {
margin-bottom: 1.5rem;
}
.input input,
.input select,
.input textarea {
margin-bottom: 0;
}
.input label:has(input[type='checkbox']),
.input label:has(input[type='radio']) {
display: flex;
align-items: center;
}
.input label:has(~ label),
.input label:has(input[type='radio']) {
margin-bottom: 0;
}
.input label > input[type='checkbox'],
.input label > input[type='radio'] {
margin-right: 1.0rem;
}
input[type='color'] {
max-width: 4rem;
padding: 0.3rem .5rem 0.3rem;
}
.error-message {
color: var(--color-message-error-text);
}
/* Paginator */
.paginator {
text-align: right;
}
.paginator p {
margin-bottom: 0;
}
.pagination {
display: flex;
justify-content: center;
list-style: none;
margin: 0 0 1rem 0;
padding: 0;
}
.pagination li {
display: inline-block;
margin: 0.25em;
text-align: center;
}
.pagination a {
color: var(--color-cakephp-blue);
display: inline-block;
font-size: 1.25rem;
line-height: 3rem;
min-width: 3rem;
padding: 0;
position: relative;
text-decoration: none;
transition: background .3s,color .3s;
}
.pagination li.active a,
.pagination a:hover {
text-decoration: underline;
}
.pagination .disabled a {
cursor: not-allowed;
color: var(--color-lightgray);
text-decoration: none;
}
.first a,
.prev a,
.next a,
.last a {
padding: 0 .75rem;
}
.disabled a:hover {
background: initial;
color: initial;
}
.asc:after {
content: " \2193";
}
.desc:after {
content: " \2191";
}
/* Error in non debug mode */
.error-container {
align-items: center;
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
}
@media screen and (max-width: 640px) {
/* Fix milligram not having a responsive column system */
.row .column[class*='column-'] {
flex: 0 0 100%;
max-width: 100%
}
.top-nav {
margin: 0 auto;
}
.side-nav {
margin-bottom: 1rem;
}
.heading {
margin-bottom: 1rem;
}
.side-nav-item {
display: inline;
margin: 0 1.5rem 0 0;
}
.asc:after {
content: " \2192";
}
.desc:after {
content: " \2190";
}
}

80
webroot/css/fonts.css Normal file
View File

@@ -0,0 +1,80 @@
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url('../font/raleway-400-cyrillic-ext.woff2') format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url('../font/raleway-400-cyrillic.woff2') format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url('../font/raleway-400-vietnamese.woff2') format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url('../font/raleway-400-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url('../font/raleway-400-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('../font/raleway-700-cyrillic-ext.woff2') format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('../font/raleway-700-cyrillic.woff2') format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('../font/raleway-700-vietnamese.woff2') format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('../font/raleway-700-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('../font/raleway-700-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

75
webroot/css/home.css Normal file
View File

@@ -0,0 +1,75 @@
/* Home page styles */
@font-face {
font-family: 'cakefont';
src: url('../font/cakedingbats-webfont.eot');
src: url('../font/cakedingbats-webfont.eot?#iefix') format('embedded-opentype'),
url('../font/cakedingbats-webfont.woff2') format('woff2'),
url('../font/cakedingbats-webfont.woff') format('woff'),
url('../font/cakedingbats-webfont.ttf') format('truetype'),
url('../font/cakedingbats-webfont.svg#cake_dingbatsregular') format('svg');
font-weight: normal;
font-style: normal;
}
body {
padding: 60px 0;
}
header {
margin-bottom: 60px;
}
img {
margin-bottom: 30px;
}
h1 {
font-weight: bold;
}
ul {
list-style-type: none;
margin: 0 0 30px 0;
padding-left: 25px;
}
a {
color: #0071BC;
text-decoration: underline;
}
hr {
border-bottom: 1px solid #e7e7e7;
border-top: 0;
margin-bottom: 35px;
}
.text-center {
text-align: center;
}
.links a {
margin-right: 10px;
}
.release-name {
color: #D33C43;
font-weight: 400;
font-style: italic;
}
.bullet:before {
font-family: 'cakefont', sans-serif;
font-size: 18px;
display: inline-block;
margin-left: -1.3em;
width: 1.2em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: -1px;
}
.success:before {
color: #88c671;
content: "\0056";
}
.problem:before {
color: #d33d44;
content: "\0057";
}
.cake-error {
padding: 10px;
margin: 10px 0;
}
#url-rewriting-warning {
display: none;
}

9
webroot/css/milligram.min.css vendored Normal file

File diff suppressed because one or more lines are too long

8
webroot/css/normalize.min.css vendored Normal file
View File

@@ -0,0 +1,8 @@
/**
* Minified by jsDelivr using clean-css v4.2.1.
* Original file: /npm/normalize.css@8.0.1/normalize.css
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}

Some files were not shown because too many files have changed in this diff Show More