Initial commit

This commit is contained in:
Paul Nicoué 2021-10-29 18:05:46 +02:00
commit 1ff19bf38f
830 changed files with 159212 additions and 0 deletions

22
.editorconfig Normal file
View file

@ -0,0 +1,22 @@
[*.{css,scss,less,js,json,ts,sass,html,hbs,mustache,phtml,html.twig,md,yml}]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_size = 4
trim_trailing_whitespace = false
[site/templates/**.php]
indent_size = 2
[site/snippets/**.php]
indent_size = 2
[package.json,.{babelrc,editorconfig,eslintrc,lintstagedrc,stylelintrc}]
indent_style = space
indent_size = 2

43
.gitignore vendored Normal file
View file

@ -0,0 +1,43 @@
# --------------------------------------------------
# GENERAL
# --------------------------------------------------
# Dependencies
/vendor/
# Editors
*.sublime-project
*.sublime-workspace
/.vscode
/.idea
# System files
Icon
.DS_Store
# Temporary files
/media/*
!/media/index.html
# --------------------------------------------------
# SECURITY
# --------------------------------------------------
# Accounts
/site/accounts/*
!/site/accounts/index.html
# Cache Files
/site/cache/*
!/site/cache/index.html
# Configuration files
/site/config/config.xiaowang.fr.php
/site/config/config.xiaowang.test.php
# License
/site/config/.license
# Sessions
/site/sessions/*
!/site/sessions/index.html

57
.htaccess Normal file
View file

@ -0,0 +1,57 @@
# Kirby .htaccess
# revision 2020-06-15
# rewrite rules
<IfModule mod_rewrite.c>
# enable awesome urls. i.e.:
# http://yourdomain.com/about-us/team
RewriteEngine on
# make sure to set the RewriteBase correctly
# if you are running the site in a subfolder;
# otherwise links or the entire site will break.
#
# If your homepage is http://yourdomain.com/mysite,
# set the RewriteBase to:
#
# RewriteBase /mysite
# In some environments it's necessary to
# set the RewriteBase to:
#
# RewriteBase /
# block files and folders beginning with a dot, such as .git
# except for the .well-known folder, which is used for Let's Encrypt and security.txt
RewriteRule (^|/)\.(?!well-known\/) index.php [L]
# block all files in the content folder from being accessed directly
RewriteRule ^content/(.*) index.php [L]
# block all files in the site folder from being accessed directly
RewriteRule ^site/(.*) index.php [L]
# block direct access to Kirby and the Panel sources
RewriteRule ^kirby/(.*) index.php [L]
# make site links work
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php [L]
</IfModule>
# pass the Authorization header to PHP
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
# compress text file responses
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>

34
README.md Normal file
View file

@ -0,0 +1,34 @@
<img src="http://getkirby.com/assets/images/github/plainkit.jpg" width="300">
**Kirby: the CMS that adapts to any project, loved by developers and editors alike.**
The Plainkit is a minimal Kirby setup with the basics you need to start a project from scratch. It is the ideal choice if you are already familiar with Kirby and want to start step-by-step.
You can learn more about Kirby at [getkirby.com](https://getkirby.com).
### Try Kirby for free
You can try Kirby and the Plainkit on your local machine or on a test server as long as you need to make sure it is the right tool for your next project. … and when youre convinced, [buy your license](https://getkirby.com/buy).
### Get going
Read our guide on [how to get started with Kirby](https://getkirby.com/docs/guide/quickstart).
You can [download the latest version](https://github.com/getkirby/plainkit/archive/main.zip) of the Plainkit.
If you are familiar with Git, you can clone Kirby's Plainkit repository from Github.
git clone https://github.com/getkirby/plainkit.git
## What's Kirby?
- **[getkirby.com](https://getkirby.com)** Get to know the CMS.
- **[Try it](https://getkirby.com/try)** Take a test ride with our online demo. Or download one of our kits to get started.
- **[Documentation](https://getkirby.com/docs/guide)** Read the official guide, reference and cookbook recipes.
- **[Issues](https://github.com/getkirby/kirby/issues)** Report bugs and other problems.
- **[Feedback](https://feedback.getkirby.com)** You have an idea for Kirby? Share it.
- **[Forum](https://forum.getkirby.com)** Whenever you get stuck, don't hesitate to reach out for questions and support.
- **[Discord](https://chat.getkirby.com)** Hang out and meet the community.
- **[Twitter](https://twitter.com/getkirby)** Spread the word.
- **[Instagram](https://www.instagram.com/getkirby/)** Share your creations: #madewithkirby.
---
© 2009-2020 Bastian Allgeier (Bastian Allgeier GmbH)
[getkirby.com](https://getkirby.com) · [License agreement](https://getkirby.com/license)

34
composer.json Normal file
View file

@ -0,0 +1,34 @@
{
"name": "getkirby/plainkit",
"description": "Kirby Plainkit",
"type": "project",
"keywords": ["kirby", "cms", "starterkit"],
"homepage": "https://getkirby.com",
"authors": [
{
"name": "Bastian Allgeier",
"email": "bastian@getkirby.com",
"homepage": "https://getkirby.com"
}
],
"support": {
"email": "support@getkirby.com",
"issues": "https://github.com/getkirby/starterkit/issues",
"forum": "https://forum.getkirby.com",
"source": "https://github.com/getkirby/starterkit"
},
"require": {
"php": ">=7.3.0 <8.1.0",
"getkirby/cms": "^3.5",
"amteich/kirby-twig": "^4.1"
},
"scripts": {
"start": [
"Composer\\Config::disableProcessTimeout",
"@php -S localhost:8000 kirby/router.php"
]
},
"config": {
"optimize-autoloader": true
}
}

1003
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

1
content/error/error.txt Normal file
View file

@ -0,0 +1 @@
Title: Error

1
content/home/home.txt Normal file
View file

@ -0,0 +1 @@
Title: Home

1
content/site.txt Normal file
View file

@ -0,0 +1 @@
Title: Site Title

5
index.php Normal file
View file

@ -0,0 +1,5 @@
<?php
require 'kirby/bootstrap.php';
echo (new Kirby)->render();

15
kirby/.editorconfig Normal file
View file

@ -0,0 +1,15 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
# PHP PSR-2 Coding Standards
# http://www.php-fig.org/psr/psr-2/
root = true
[*.php]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

3
kirby/SECURITY.md Normal file
View file

@ -0,0 +1,3 @@
# Security Policy
Please see the [Security Policy on the Kirby website](https://getkirby.com/security) for a list of the currently supported Kirby versions and of past security incidents as well as for information on how to report security vulnerabilities in the Kirby core or in the Panel.

83
kirby/assets/whoops.css Normal file
View file

@ -0,0 +1,83 @@
body {
background: #efefef;
font: normal normal 400 12px/1.5 -apple-system, BlinkMacSystemFont, Segoe UI,
Roboto, Helvetica, Arial, sans-serif;
}
.left-panel {
background: transparent;
}
header {
background-color: #313740;
}
.exc-title-primary {
color: hsl(0, 71%, 55%);
}
.frame.active {
color: hsl(0, 71%, 55%);
box-shadow: inset -5px 0 0 0 #d16464;
}
.frame:not(.active):hover {
background: rgba(203, 215, 229, 0.5);
}
.rightButton {
color: #999;
box-shadow: inset 0 0 0 1px #777;
border-radius: 0;
}
.rightButton:hover {
box-shadow: inset 0 0 0 1px #555;
color: #777;
}
.details-heading {
color: #7e9abf;
font-weight: 500;
}
.frame-code {
background: #000;
}
pre.code-block,
code.code-block,
.frame-args.code-block,
.frame-args.code-block samp {
background: #16171a;
}
.linenums li.current {
background: transparent;
}
.linenums li.current.active {
background: rgba(209, 100, 100, 0.3);
}
pre .atv,
code .atv,
pre .str,
code .str {
color: #a7bd68;
}
pre .tag,
code .tag {
color: #d16464;
}
pre .kwd,
code .kwd {
color: #8abeb7;
}
pre .atn,
code .atn {
color: #de935f;
}

35
kirby/bootstrap.php Normal file
View file

@ -0,0 +1,35 @@
<?php
/**
* Validate the PHP version to already
* stop at older or too recent versions
*/
if (
version_compare(PHP_VERSION, '7.3.0', '>=') === false ||
version_compare(PHP_VERSION, '8.1.0', '<') === false
) {
die(include __DIR__ . '/views/php.php');
}
if (is_file($autoloader = dirname(__DIR__) . '/vendor/autoload.php')) {
/**
* Always prefer a site-wide Composer autoloader
* if it exists, it means that the user has probably
* installed additional packages
*/
include $autoloader;
} elseif (is_file($autoloader = __DIR__ . '/vendor/autoload.php')) {
/**
* Fall back to the local autoloader if that exists
*/
include $autoloader;
} else {
/**
* If neither one exists, don't bother searching;
* it's a custom directory setup and the users need to
* load the autoloader themselves
*/
}

3174
kirby/cacert.pem Normal file

File diff suppressed because it is too large Load diff

77
kirby/composer.json Normal file
View file

@ -0,0 +1,77 @@
{
"name": "getkirby/cms",
"type": "kirby-cms",
"description": "The Kirby 3 core",
"keywords": [
"kirby",
"cms",
"core"
],
"homepage": "https://getkirby.com",
"version": "3.5.7.1",
"license": "proprietary",
"authors": [
{
"name": "Kirby Team",
"email": "support@getkirby.com",
"homepage": "https://getkirby.com"
}
],
"require": {
"php": ">=7.3.0 <8.1.0",
"ext-ctype": "*",
"ext-mbstring": "*",
"claviska/simpleimage": "3.6.3",
"filp/whoops": "2.12.1",
"getkirby/composer-installer": "^1.2.0",
"laminas/laminas-escaper": "2.7.0",
"michelf/php-smartypants": "1.8.1",
"mustangostang/spyc": "0.6.3",
"phpmailer/phpmailer": "6.5.0",
"true/punycode": "2.1.1"
},
"config": {
"optimize-autoloader": true,
"platform-check": false
},
"autoload": {
"psr-4": {
"Kirby\\": "src/"
},
"classmap": [
"dependencies/"
],
"files": [
"config/setup.php",
"config/helpers.php"
]
},
"scripts": {
"post-update-cmd": "curl -o cacert.pem https://curl.se/ca/cacert.pem",
"analyze": [
"@analyze:composer",
"@analyze:psalm",
"@analyze:phpcpd",
"@analyze:phpmd"
],
"analyze:composer": "composer validate --strict --no-check-version --no-check-all",
"analyze:phpcpd": "phpcpd --fuzzy --exclude tests --exclude vendor .",
"analyze:phpmd": "phpmd . ansi phpmd.xml.dist --exclude 'dependencies/*,tests/*,vendor/*'",
"analyze:psalm": "psalm",
"build": "./scripts/build",
"ci": [
"@fix",
"@analyze",
"@test"
],
"fix": "php-cs-fixer fix",
"test": "phpunit --stderr --coverage-html=tests/coverage",
"zip": "composer archive --format=zip --file=dist"
},
"support": {
"email": "support@getkirby.com",
"issues": "https://github.com/getkirby/kirby/issues",
"forum": "https://forum.getkirby.com",
"source": "https://github.com/getkirby/kirby"
}
}

733
kirby/composer.lock generated Normal file
View file

@ -0,0 +1,733 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c087786719948c60e5d74492f70440a5",
"packages": [
{
"name": "claviska/simpleimage",
"version": "3.6.3",
"source": {
"type": "git",
"url": "https://github.com/claviska/SimpleImage.git",
"reference": "21b6f4bf4ef1927158b3e29bd0c2d99c6681c750"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/21b6f4bf4ef1927158b3e29bd0c2d99c6681c750",
"reference": "21b6f4bf4ef1927158b3e29bd0c2d99c6681c750",
"shasum": ""
},
"require": {
"ext-gd": "*",
"league/color-extractor": "0.3.*",
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-0": {
"claviska": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Cory LaViska",
"homepage": "http://www.abeautifulsite.net/",
"role": "Developer"
}
],
"description": "A PHP class that makes working with images as simple as possible.",
"support": {
"issues": "https://github.com/claviska/SimpleImage/issues",
"source": "https://github.com/claviska/SimpleImage/tree/3.6.3"
},
"funding": [
{
"url": "https://github.com/claviska",
"type": "github"
}
],
"time": "2021-04-20T12:18:18+00:00"
},
{
"name": "filp/whoops",
"version": "2.12.1",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd",
"shasum": ""
},
"require": {
"php": "^5.5.9 || ^7.0 || ^8.0",
"psr/log": "^1.0.1"
},
"require-dev": {
"mockery/mockery": "^0.9 || ^1.0",
"phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3",
"symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
},
"suggest": {
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
}
},
"autoload": {
"psr-4": {
"Whoops\\": "src/Whoops/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Filipe Dobreira",
"homepage": "https://github.com/filp",
"role": "Developer"
}
],
"description": "php error handling for cool kids",
"homepage": "https://filp.github.io/whoops/",
"keywords": [
"error",
"exception",
"handling",
"library",
"throwable",
"whoops"
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.12.1"
},
"funding": [
{
"url": "https://github.com/denis-sokolov",
"type": "github"
}
],
"time": "2021-04-25T12:00:00+00:00"
},
{
"name": "getkirby/composer-installer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/getkirby/composer-installer.git",
"reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getkirby/composer-installer/zipball/c98ece30bfba45be7ce457e1102d1b169d922f3d",
"reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0"
},
"require-dev": {
"composer/composer": "^1.8 || ^2.0"
},
"type": "composer-plugin",
"extra": {
"class": "Kirby\\ComposerInstaller\\Plugin"
},
"autoload": {
"psr-4": {
"Kirby\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins",
"homepage": "https://getkirby.com",
"support": {
"issues": "https://github.com/getkirby/composer-installer/issues",
"source": "https://github.com/getkirby/composer-installer/tree/1.2.1"
},
"funding": [
{
"url": "https://getkirby.com/buy",
"type": "custom"
}
],
"time": "2020-12-28T12:54:39+00:00"
},
{
"name": "laminas/laminas-escaper",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-escaper.git",
"reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/5e04bc5ae5990b17159d79d331055e2c645e5cc5",
"reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.3 || ~8.0.0"
},
"replace": {
"zendframework/zend-escaper": "^2.6.1"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^9.3",
"psalm/plugin-phpunit": "^0.12.2",
"vimeo/psalm": "^3.16"
},
"suggest": {
"ext-iconv": "*",
"ext-mbstring": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Laminas\\Escaper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs",
"homepage": "https://laminas.dev",
"keywords": [
"escaper",
"laminas"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-escaper/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-escaper/issues",
"rss": "https://github.com/laminas/laminas-escaper/releases.atom",
"source": "https://github.com/laminas/laminas-escaper"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2020-11-17T21:26:43+00:00"
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/13af2502d9bb6f7d33be2de4b51fb68c6cdb476e",
"reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"psalm/plugin-phpunit": "^0.15.1",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.6"
},
"type": "library",
"extra": {
"laminas": {
"module": "Laminas\\ZendFrameworkBridge"
}
},
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ZendFrameworkBridge\\": "src//"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
"keywords": [
"ZendFramework",
"autoloading",
"laminas",
"zf"
],
"support": {
"forum": "https://discourse.laminas.dev/",
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
"source": "https://github.com/laminas/laminas-zendframework-bridge"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-06-24T12:49:22+00:00"
},
{
"name": "league/color-extractor",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/color-extractor.git",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/color-extractor/zipball/837086ec60f50c84c611c613963e4ad2e2aec806",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": ">=5.4.0"
},
"replace": {
"matthecat/colorextractor": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
"phpunit/phpunit": "~5"
},
"type": "library",
"autoload": {
"psr-4": {
"": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathieu Lechat",
"email": "math.lechat@gmail.com",
"homepage": "http://matthecat.com",
"role": "Developer"
}
],
"description": "Extract colors from an image as a human would do.",
"homepage": "https://github.com/thephpleague/color-extractor",
"keywords": [
"color",
"extract",
"human",
"image",
"palette"
],
"support": {
"issues": "https://github.com/thephpleague/color-extractor/issues",
"source": "https://github.com/thephpleague/color-extractor/tree/master"
},
"time": "2016-12-15T09:30:02+00:00"
},
{
"name": "michelf/php-smartypants",
"version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-smartypants.git",
"reference": "47d17c90a4dfd0ccf1f87e25c65e6c8012415aad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-smartypants/zipball/47d17c90a4dfd0ccf1f87e25c65e6c8012415aad",
"reference": "47d17c90a4dfd0ccf1f87e25c65e6c8012415aad",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Michelf": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "https://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "https://daringfireball.net/"
}
],
"description": "PHP SmartyPants",
"homepage": "https://michelf.ca/projects/php-smartypants/",
"keywords": [
"dashes",
"quotes",
"spaces",
"typographer",
"typography"
],
"support": {
"issues": "https://github.com/michelf/php-smartypants/issues",
"source": "https://github.com/michelf/php-smartypants/tree/1.8.1"
},
"time": "2016-12-13T01:01:17+00:00"
},
{
"name": "mustangostang/spyc",
"version": "0.6.3",
"source": {
"type": "git",
"url": "git@github.com:mustangostang/spyc.git",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0",
"shasum": ""
},
"require": {
"php": ">=5.3.1"
},
"require-dev": {
"phpunit/phpunit": "4.3.*@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.5.x-dev"
}
},
"autoload": {
"files": [
"Spyc.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "mustangostang",
"email": "vlad.andersen@gmail.com"
}
],
"description": "A simple YAML loader/dumper class for PHP",
"homepage": "https://github.com/mustangostang/spyc/",
"keywords": [
"spyc",
"yaml",
"yml"
],
"time": "2019-09-10T13:16:29+00:00"
},
{
"name": "phpmailer/phpmailer",
"version": "v6.5.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-filter": "*",
"ext-hash": "*",
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPMailer\\PHPMailer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-only"
],
"authors": [
{
"name": "Marcus Bointon",
"email": "phpmailer@synchromedia.co.uk"
},
{
"name": "Jim Jagielski",
"email": "jimjag@gmail.com"
},
{
"name": "Andy Prevost",
"email": "codeworxtech@users.sourceforge.net"
},
{
"name": "Brent R. Matzelle"
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
},
"funding": [
{
"url": "https://github.com/Synchro",
"type": "github"
}
],
"time": "2021-06-16T14:33:43+00:00"
},
{
"name": "psr/log",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"time": "2021-05-03T11:20:27+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-27T09:27:20+00:00"
},
{
"name": "true/punycode",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/true/php-punycode.git",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "~4.7",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"TrueBV\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Renan Gonçalves",
"email": "renan.saddam@gmail.com"
}
],
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
"homepage": "https://github.com/true/php-punycode",
"keywords": [
"idna",
"punycode"
],
"support": {
"issues": "https://github.com/true/php-punycode/issues",
"source": "https://github.com/true/php-punycode/tree/master"
},
"time": "2016-11-16T10:37:54+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.3.0 <8.1.0",
"ext-ctype": "*",
"ext-mbstring": "*"
},
"platform-dev": [],
"plugin-api-version": "2.1.0"
}

62
kirby/config/aliases.php Normal file
View file

@ -0,0 +1,62 @@
<?php
// @codeCoverageIgnoreStart
return [
// cms classes
'asset' => 'Kirby\Cms\Asset',
'collection' => 'Kirby\Cms\Collection',
'dir' => 'Kirby\Cms\Dir',
'field' => 'Kirby\Cms\Field',
'file' => 'Kirby\Cms\File',
'files' => 'Kirby\Cms\Files',
'html' => 'Kirby\Cms\Html',
'kirby' => 'Kirby\Cms\App',
'page' => 'Kirby\Cms\Page',
'pages' => 'Kirby\Cms\Pages',
'pagination' => 'Kirby\Cms\Pagination',
'r' => 'Kirby\Cms\R',
'response' => 'Kirby\Cms\Response',
's' => 'Kirby\Cms\S',
'site' => 'Kirby\Cms\Site',
'structure' => 'Kirby\Cms\Structure',
'url' => 'Kirby\Cms\Url',
'user' => 'Kirby\Cms\User',
'users' => 'Kirby\Cms\Users',
'visitor' => 'Kirby\Cms\Visitor',
// data handler
'data' => 'Kirby\Data\Data',
'json' => 'Kirby\Data\Json',
'yaml' => 'Kirby\Data\Yaml',
// data classes
'database' => 'Kirby\Database\Database',
'db' => 'Kirby\Database\Db',
// exceptions
'errorpageexception' => 'Kirby\Exception\ErrorPageException',
// http classes
'cookie' => 'Kirby\Http\Cookie',
'header' => 'Kirby\Http\Header',
'remote' => 'Kirby\Http\Remote',
'server' => 'Kirby\Http\Server',
// image classes
'dimensions' => 'Kirby\Image\Dimensions',
// toolkit classes
'a' => 'Kirby\Toolkit\A',
'c' => 'Kirby\Toolkit\Config',
'config' => 'Kirby\Toolkit\Config',
'escape' => 'Kirby\Toolkit\Escape',
'f' => 'Kirby\Toolkit\F',
'i18n' => 'Kirby\Toolkit\I18n',
'mime' => 'Kirby\Toolkit\Mime',
'obj' => 'Kirby\Toolkit\Obj',
'str' => 'Kirby\Toolkit\Str',
'tpl' => 'Kirby\Toolkit\Tpl',
'v' => 'Kirby\Toolkit\V',
'xml' => 'Kirby\Toolkit\Xml'
];
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,24 @@
<?php
use Kirby\Exception\PermissionException;
return function () {
$auth = $this->kirby()->auth();
$allowImpersonation = $this->kirby()->option('api.allowImpersonation') ?? false;
// csrf token check
if ($auth->type($allowImpersonation) === 'session' && $auth->csrf() === false) {
throw new PermissionException('Unauthenticated');
}
// get user from session or basic auth
if ($user = $auth->user(null, $allowImpersonation)) {
if ($user->role()->permissions()->for('access', 'panel') === false) {
throw new PermissionException(['key' => 'access.panel']);
}
return $user;
}
throw new PermissionException('Unauthenticated');
};

View file

@ -0,0 +1,72 @@
<?php
/**
* Api Collection Definitions
*/
return [
/**
* Children
*/
'children' => [
'model' => 'page',
'type' => 'Kirby\Cms\Pages',
'view' => 'compact'
],
/**
* Files
*/
'files' => [
'model' => 'file',
'type' => 'Kirby\Cms\Files'
],
/**
* Languages
*/
'languages' => [
'model' => 'language',
'type' => 'Kirby\Cms\Languages'
],
/**
* Pages
*/
'pages' => [
'model' => 'page',
'type' => 'Kirby\Cms\Pages',
'view' => 'compact'
],
/**
* Roles
*/
'roles' => [
'model' => 'role',
'type' => 'Kirby\Cms\Roles',
'view' => 'compact'
],
/**
* Translations
*/
'translations' => [
'model' => 'translation',
'type' => 'Kirby\Cms\Translations',
'view' => 'compact'
],
/**
* Users
*/
'users' => [
'default' => function () {
return $this->users();
},
'model' => 'user',
'type' => 'Kirby\Cms\Users',
'view' => 'compact'
]
];

View file

@ -0,0 +1,20 @@
<?php
/**
* Api Model Definitions
*/
return [
'File' => include __DIR__ . '/models/File.php',
'FileBlueprint' => include __DIR__ . '/models/FileBlueprint.php',
'FileVersion' => include __DIR__ . '/models/FileVersion.php',
'Language' => include __DIR__ . '/models/Language.php',
'Page' => include __DIR__ . '/models/Page.php',
'PageBlueprint' => include __DIR__ . '/models/PageBlueprint.php',
'Role' => include __DIR__ . '/models/Role.php',
'Site' => include __DIR__ . '/models/Site.php',
'SiteBlueprint' => include __DIR__ . '/models/SiteBlueprint.php',
'System' => include __DIR__ . '/models/System.php',
'Translation' => include __DIR__ . '/models/Translation.php',
'User' => include __DIR__ . '/models/User.php',
'UserBlueprint' => include __DIR__ . '/models/UserBlueprint.php',
];

View file

@ -0,0 +1,166 @@
<?php
use Kirby\Cms\File;
use Kirby\Cms\Form;
/**
* File
*/
return [
'fields' => [
'blueprint' => function (File $file) {
return $file->blueprint();
},
'content' => function (File $file) {
return Form::for($file)->values();
},
'dimensions' => function (File $file) {
return $file->dimensions()->toArray();
},
'dragText' => function (File $file) {
return $file->dragText();
},
'exists' => function (File $file) {
return $file->exists();
},
'extension' => function (File $file) {
return $file->extension();
},
'filename' => function (File $file) {
return $file->filename();
},
'id' => function (File $file) {
return $file->id();
},
'link' => function (File $file) {
return $file->panelUrl(true);
},
'mime' => function (File $file) {
return $file->mime();
},
'modified' => function (File $file) {
return $file->modified('c');
},
'name' => function (File $file) {
return $file->name();
},
'next' => function (File $file) {
return $file->next();
},
'nextWithTemplate' => function (File $file) {
$files = $file->templateSiblings()->sort('sort', 'asc', 'filename', 'asc');
$index = $files->indexOf($file);
return $files->nth($index + 1);
},
'niceSize' => function (File $file) {
return $file->niceSize();
},
'options' => function (File $file) {
return $file->panelOptions();
},
'panelIcon' => function (File $file) {
return $file->panelIcon();
},
'panelImage' => function (File $file) {
return $file->panelImage();
},
'panelUrl' => function (File $file) {
return $file->panelUrl(true);
},
'prev' => function (File $file) {
return $file->prev();
},
'prevWithTemplate' => function (File $file) {
$files = $file->templateSiblings()->sort('sort', 'asc', 'filename', 'asc');
$index = $files->indexOf($file);
return $files->nth($index - 1);
},
'parent' => function (File $file) {
return $file->parent();
},
'parents' => function (File $file) {
return $file->parents()->flip();
},
'size' => function (File $file) {
return $file->size();
},
'template' => function (File $file) {
return $file->template();
},
'thumbs' => function ($file) {
if ($file->isResizable() === false) {
return null;
}
return [
'tiny' => $file->resize(128)->url(),
'small' => $file->resize(256)->url(),
'medium' => $file->resize(512)->url(),
'large' => $file->resize(768)->url(),
'huge' => $file->resize(1024)->url(),
];
},
'type' => function (File $file) {
return $file->type();
},
'url' => function (File $file) {
return $file->url(true);
},
],
'type' => 'Kirby\Cms\File',
'views' => [
'default' => [
'content',
'dimensions',
'exists',
'extension',
'filename',
'id',
'link',
'mime',
'modified',
'name',
'next' => 'compact',
'niceSize',
'parent' => 'compact',
'options',
'prev' => 'compact',
'size',
'template',
'type',
'url'
],
'compact' => [
'filename',
'id',
'link',
'type',
'url',
],
'panel' => [
'blueprint',
'content',
'dimensions',
'extension',
'filename',
'id',
'link',
'mime',
'modified',
'name',
'nextWithTemplate' => 'compact',
'niceSize',
'options',
'panelIcon',
'panelImage',
'parent' => 'compact',
'parents' => ['id', 'slug', 'title'],
'prevWithTemplate' => 'compact',
'template',
'type',
'url'
]
],
];

View file

@ -0,0 +1,26 @@
<?php
use Kirby\Cms\FileBlueprint;
/**
* FileBlueprint
*/
return [
'fields' => [
'name' => function (FileBlueprint $blueprint) {
return $blueprint->name();
},
'options' => function (FileBlueprint $blueprint) {
return $blueprint->options();
},
'tabs' => function (FileBlueprint $blueprint) {
return $blueprint->tabs();
},
'title' => function (FileBlueprint $blueprint) {
return $blueprint->title();
},
],
'type' => 'Kirby\Cms\FileBlueprint',
'views' => [
],
];

View file

@ -0,0 +1,83 @@
<?php
use Kirby\Cms\FileVersion;
/**
* FileVersion
*/
return [
'fields' => [
'dimensions' => function (FileVersion $file) {
return $file->dimensions()->toArray();
},
'exists' => function (FileVersion $file) {
return $file->exists();
},
'extension' => function (FileVersion $file) {
return $file->extension();
},
'filename' => function (FileVersion $file) {
return $file->filename();
},
'id' => function (FileVersion $file) {
return $file->id();
},
'mime' => function (FileVersion $file) {
return $file->mime();
},
'modified' => function (FileVersion $file) {
return $file->modified('c');
},
'name' => function (FileVersion $file) {
return $file->name();
},
'niceSize' => function (FileVersion $file) {
return $file->niceSize();
},
'size' => function (FileVersion $file) {
return $file->size();
},
'type' => function (FileVersion $file) {
return $file->type();
},
'url' => function (FileVersion $file) {
return $file->url(true);
},
],
'type' => 'Kirby\Cms\FileVersion',
'views' => [
'default' => [
'dimensions',
'exists',
'extension',
'filename',
'id',
'mime',
'modified',
'name',
'niceSize',
'size',
'type',
'url'
],
'compact' => [
'filename',
'id',
'type',
'url',
],
'panel' => [
'dimensions',
'extension',
'filename',
'id',
'mime',
'modified',
'name',
'niceSize',
'template',
'type',
'url'
]
],
];

View file

@ -0,0 +1,44 @@
<?php
use Kirby\Cms\Language;
/**
* Language
*/
return [
'fields' => [
'code' => function (Language $language) {
return $language->code();
},
'default' => function (Language $language) {
return $language->isDefault();
},
'direction' => function (Language $language) {
return $language->direction();
},
'locale' => function (Language $language) {
return $language->locale();
},
'name' => function (Language $language) {
return $language->name();
},
'rules' => function (Language $language) {
return $language->rules();
},
'url' => function (Language $language) {
return $language->url();
},
],
'type' => 'Kirby\Cms\Language',
'views' => [
'default' => [
'code',
'default',
'direction',
'locale',
'name',
'rules',
'url'
]
]
];

View file

@ -0,0 +1,157 @@
<?php
use Kirby\Cms\Form;
use Kirby\Cms\Page;
/**
* Page
*/
return [
'fields' => [
'blueprint' => function (Page $page) {
return $page->blueprint();
},
'blueprints' => function (Page $page) {
return $page->blueprints();
},
'children' => function (Page $page) {
return $page->children();
},
'content' => function (Page $page) {
return Form::for($page)->values();
},
'drafts' => function (Page $page) {
return $page->drafts();
},
'errors' => function (Page $page) {
return $page->errors();
},
'files' => function (Page $page) {
return $page->files()->sort('sort', 'asc', 'filename', 'asc');
},
'hasChildren' => function (Page $page) {
return $page->hasChildren();
},
'hasDrafts' => function (Page $page) {
return $page->hasDrafts();
},
'hasFiles' => function (Page $page) {
return $page->hasFiles();
},
'id' => function (Page $page) {
return $page->id();
},
'isSortable' => function (Page $page) {
return $page->isSortable();
},
'next' => function (Page $page) {
return $page
->nextAll()
->filter('intendedTemplate', $page->intendedTemplate())
->filter('status', $page->status())
->filter('isReadable', true)
->first();
},
'num' => function (Page $page) {
return $page->num();
},
'options' => function (Page $page) {
return $page->panelOptions(['preview']);
},
'panelIcon' => function (Page $page) {
return $page->panelIcon();
},
'panelImage' => function (Page $page) {
return $page->panelImage();
},
'parent' => function (Page $page) {
return $page->parent();
},
'parents' => function (Page $page) {
return $page->parents()->flip();
},
'prev' => function (Page $page) {
return $page
->prevAll()
->filter('intendedTemplate', $page->intendedTemplate())
->filter('status', $page->status())
->filter('isReadable', true)
->last();
},
'previewUrl' => function (Page $page) {
return $page->previewUrl();
},
'siblings' => function (Page $page) {
if ($page->isDraft() === true) {
return $page->parentModel()->children()->not($page);
} else {
return $page->siblings();
}
},
'slug' => function (Page $page) {
return $page->slug();
},
'status' => function (Page $page) {
return $page->status();
},
'template' => function (Page $page) {
return $page->intendedTemplate()->name();
},
'title' => function (Page $page) {
return $page->title()->value();
},
'url' => function (Page $page) {
return $page->url();
},
],
'type' => 'Kirby\Cms\Page',
'views' => [
'compact' => [
'id',
'title',
'url',
'num'
],
'default' => [
'content',
'id',
'status',
'num',
'options',
'parent' => 'compact',
'slug',
'template',
'title',
'url'
],
'panel' => [
'id',
'blueprint',
'content',
'status',
'options',
'next' => ['id', 'slug', 'title'],
'parents' => ['id', 'slug', 'title'],
'prev' => ['id', 'slug', 'title'],
'previewUrl',
'slug',
'title',
'url'
],
'selector' => [
'id',
'title',
'parent' => [
'id',
'title'
],
'children' => [
'hasChildren',
'id',
'panelIcon',
'panelImage',
'title',
],
]
],
];

View file

@ -0,0 +1,35 @@
<?php
use Kirby\Cms\PageBlueprint;
/**
* PageBlueprint
*/
return [
'fields' => [
'name' => function (PageBlueprint $blueprint) {
return $blueprint->name();
},
'num' => function (PageBlueprint $blueprint) {
return $blueprint->num();
},
'options' => function (PageBlueprint $blueprint) {
return $blueprint->options();
},
'preview' => function (PageBlueprint $blueprint) {
return $blueprint->preview();
},
'status' => function (PageBlueprint $blueprint) {
return $blueprint->status();
},
'tabs' => function (PageBlueprint $blueprint) {
return $blueprint->tabs();
},
'title' => function (PageBlueprint $blueprint) {
return $blueprint->title();
},
],
'type' => 'Kirby\Cms\PageBlueprint',
'views' => [
],
];

View file

@ -0,0 +1,31 @@
<?php
use Kirby\Cms\Role;
/**
* Role
*/
return [
'fields' => [
'description' => function (Role $role) {
return $role->description();
},
'name' => function (Role $role) {
return $role->name();
},
'permissions' => function (Role $role) {
return $role->permissions()->toArray();
},
'title' => function (Role $role) {
return $role->title();
},
],
'type' => 'Kirby\Cms\Role',
'views' => [
'compact' => [
'description',
'name',
'title'
]
]
];

View file

@ -0,0 +1,72 @@
<?php
use Kirby\Cms\Form;
use Kirby\Cms\Site;
/**
* Site
*/
return [
'default' => function () {
return $this->site();
},
'fields' => [
'blueprint' => function (Site $site) {
return $site->blueprint();
},
'children' => function (Site $site) {
return $site->children();
},
'content' => function (Site $site) {
return Form::for($site)->values();
},
'drafts' => function (Site $site) {
return $site->drafts();
},
'files' => function (Site $site) {
return $site->files()->sort('sort', 'asc', 'filename', 'asc');
},
'options' => function (Site $site) {
return $site->permissions()->toArray();
},
'previewUrl' => function (Site $site) {
return $site->previewUrl();
},
'title' => function (Site $site) {
return $site->title()->value();
},
'url' => function (Site $site) {
return $site->url();
},
],
'type' => 'Kirby\Cms\Site',
'views' => [
'compact' => [
'title',
'url'
],
'default' => [
'content',
'options',
'title',
'url'
],
'panel' => [
'title',
'blueprint',
'content',
'options',
'previewUrl',
'url'
],
'selector' => [
'title',
'children' => [
'id',
'title',
'panelIcon',
'hasChildren'
],
]
]
];

View file

@ -0,0 +1,26 @@
<?php
use Kirby\Cms\SiteBlueprint;
/**
* SiteBlueprint
*/
return [
'fields' => [
'name' => function (SiteBlueprint $blueprint) {
return $blueprint->name();
},
'options' => function (SiteBlueprint $blueprint) {
return $blueprint->options();
},
'tabs' => function (SiteBlueprint $blueprint) {
return $blueprint->tabs();
},
'title' => function (SiteBlueprint $blueprint) {
return $blueprint->title();
},
],
'type' => 'Kirby\Cms\SiteBlueprint',
'views' => [
],
];

View file

@ -0,0 +1,136 @@
<?php
use Kirby\Cms\System;
use Kirby\Toolkit\Str;
/**
* System
*/
return [
'fields' => [
'ascii' => function () {
return Str::$ascii;
},
'authStatus' => function () {
return $this->kirby()->auth()->status()->toArray();
},
'defaultLanguage' => function () {
return $this->kirby()->panelLanguage();
},
'isOk' => function (System $system) {
return $system->isOk();
},
'isInstallable' => function (System $system) {
return $system->isInstallable();
},
'isInstalled' => function (System $system) {
return $system->isInstalled();
},
'isLocal' => function (System $system) {
return $system->isLocal();
},
'multilang' => function () {
return $this->kirby()->option('languages', false) !== false;
},
'languages' => function () {
return $this->kirby()->languages();
},
'license' => function (System $system) {
return $system->license();
},
'locales' => function () {
$locales = [];
$translations = $this->kirby()->translations();
foreach ($translations as $translation) {
$locales[$translation->code()] = $translation->locale();
}
return $locales;
},
'loginMethods' => function (System $system) {
return array_keys($system->loginMethods());
},
'requirements' => function (System $system) {
return $system->toArray();
},
'site' => function () {
try {
return $this->site()->blueprint()->title();
} catch (Throwable $e) {
return $this->site()->title()->value();
}
},
'slugs' => function () {
return Str::$language;
},
'title' => function () {
return $this->site()->title()->value();
},
'translation' => function () {
if ($user = $this->user()) {
$translationCode = $user->language();
} else {
$translationCode = $this->kirby()->panelLanguage();
}
if ($translation = $this->kirby()->translation($translationCode)) {
return $translation;
} else {
return $this->kirby()->translation('en');
}
},
'kirbytext' => function () {
return $this->kirby()->option('panel.kirbytext') ?? true;
},
'user' => function () {
return $this->user();
},
'version' => function () {
$user = $this->user();
if ($user && $user->role()->permissions()->for('access', 'settings') === true) {
return $this->kirby()->version();
} else {
return null;
}
}
],
'type' => 'Kirby\Cms\System',
'views' => [
'login' => [
'authStatus',
'isOk',
'isInstallable',
'isInstalled',
'loginMethods',
'title',
'translation'
],
'troubleshooting' => [
'isOk',
'isInstallable',
'isInstalled',
'title',
'translation',
'requirements'
],
'panel' => [
'ascii',
'defaultLanguage',
'isOk',
'isInstalled',
'isLocal',
'kirbytext',
'languages',
'license',
'locales',
'multilang',
'requirements',
'site',
'slugs',
'title',
'translation',
'user' => 'auth',
'version'
]
],
];

View file

@ -0,0 +1,34 @@
<?php
use Kirby\Cms\Translation;
/**
* Translation
*/
return [
'fields' => [
'author' => function (Translation $translation) {
return $translation->author();
},
'data' => function (Translation $translation) {
return $translation->dataWithFallback();
},
'direction' => function (Translation $translation) {
return $translation->direction();
},
'id' => function (Translation $translation) {
return $translation->id();
},
'name' => function (Translation $translation) {
return $translation->name();
},
],
'type' => 'Kirby\Cms\Translation',
'views' => [
'compact' => [
'direction',
'id',
'name'
]
]
];

View file

@ -0,0 +1,108 @@
<?php
use Kirby\Cms\Form;
use Kirby\Cms\User;
/**
* User
*/
return [
'default' => function () {
return $this->user();
},
'fields' => [
'avatar' => function (User $user) {
return $user->avatar() ? $user->avatar()->crop(512) : null;
},
'blueprint' => function (User $user) {
return $user->blueprint();
},
'content' => function (User $user) {
return Form::for($user)->values();
},
'email' => function (User $user) {
return $user->email();
},
'files' => function (User $user) {
return $user->files()->sort('sort', 'asc', 'filename', 'asc');
},
'id' => function (User $user) {
return $user->id();
},
'language' => function (User $user) {
return $user->language();
},
'name' => function (User $user) {
return $user->name()->value();
},
'next' => function (User $user) {
return $user->next();
},
'options' => function (User $user) {
return $user->panelOptions();
},
'permissions' => function (User $user) {
return $user->role()->permissions()->toArray();
},
'prev' => function (User $user) {
return $user->prev();
},
'role' => function (User $user) {
return $user->role();
},
'roles' => function (User $user) {
return $user->roles();
},
'username' => function (User $user) {
return $user->username();
}
],
'type' => 'Kirby\Cms\User',
'views' => [
'default' => [
'avatar',
'content',
'email',
'id',
'language',
'name',
'next' => 'compact',
'options',
'prev' => 'compact',
'role',
'username'
],
'compact' => [
'avatar' => 'compact',
'id',
'email',
'language',
'name',
'role' => 'compact',
'username'
],
'auth' => [
'avatar' => 'compact',
'permissions',
'email',
'id',
'name',
'role',
'language'
],
'panel' => [
'avatar' => 'compact',
'blueprint',
'content',
'email',
'id',
'language',
'name',
'next' => ['id', 'name'],
'options',
'prev' => ['id', 'name'],
'role',
'username',
],
]
];

View file

@ -0,0 +1,26 @@
<?php
use Kirby\Cms\UserBlueprint;
/**
* UserBlueprint
*/
return [
'fields' => [
'name' => function (UserBlueprint $blueprint) {
return $blueprint->name();
},
'options' => function (UserBlueprint $blueprint) {
return $blueprint->options();
},
'tabs' => function (UserBlueprint $blueprint) {
return $blueprint->tabs();
},
'title' => function (UserBlueprint $blueprint) {
return $blueprint->title();
},
],
'type' => 'Kirby\Cms\UserBlueprint',
'views' => [
],
];

View file

@ -0,0 +1,26 @@
<?php
/**
* Api Routes Definitions
*/
return function ($kirby) {
$routes = array_merge(
include __DIR__ . '/routes/auth.php',
include __DIR__ . '/routes/pages.php',
include __DIR__ . '/routes/roles.php',
include __DIR__ . '/routes/site.php',
include __DIR__ . '/routes/users.php',
include __DIR__ . '/routes/files.php',
include __DIR__ . '/routes/lock.php',
include __DIR__ . '/routes/system.php',
include __DIR__ . '/routes/translations.php'
);
// only add the language routes if the
// multi language setup is activated
if ($kirby->option('languages', false) !== false) {
$routes = array_merge($routes, include __DIR__ . '/routes/languages.php');
}
return $routes;
};

View file

@ -0,0 +1,108 @@
<?php
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;
/**
* Authentication
*/
return [
[
'pattern' => 'auth',
'method' => 'GET',
'action' => function () {
if ($user = $this->kirby()->auth()->user()) {
return $this->resolve($user)->view('auth');
}
throw new NotFoundException('The user cannot be found');
}
],
[
'pattern' => 'auth/code',
'method' => 'POST',
'auth' => false,
'action' => function () {
$auth = $this->kirby()->auth();
// csrf token check
if ($auth->type() === 'session' && $auth->csrf() === false) {
throw new InvalidArgumentException('Invalid CSRF token');
}
$user = $auth->verifyChallenge($this->requestBody('code'));
return [
'code' => 200,
'status' => 'ok',
'user' => $this->resolve($user)->view('auth')->toArray()
];
}
],
[
'pattern' => 'auth/login',
'method' => 'POST',
'auth' => false,
'action' => function () {
$auth = $this->kirby()->auth();
$methods = $this->kirby()->system()->loginMethods();
// csrf token check
if ($auth->type() === 'session' && $auth->csrf() === false) {
throw new InvalidArgumentException('Invalid CSRF token');
}
$email = $this->requestBody('email');
$long = $this->requestBody('long');
$password = $this->requestBody('password');
if ($password) {
if (isset($methods['password']) !== true) {
throw new InvalidArgumentException('Login with password is not enabled');
}
if (
isset($methods['password']['2fa']) === true &&
$methods['password']['2fa'] === true
) {
$status = $auth->login2fa($email, $password, $long);
} else {
$user = $auth->login($email, $password, $long);
}
} else {
if (isset($methods['code']) === true) {
$mode = 'login';
} elseif (isset($methods['password-reset']) === true) {
$mode = 'password-reset';
} else {
throw new InvalidArgumentException('Login without password is not enabled');
}
$status = $auth->createChallenge($email, $long, $mode);
}
if (isset($user)) {
return [
'code' => 200,
'status' => 'ok',
'user' => $this->resolve($user)->view('auth')->toArray()
];
} else {
return [
'code' => 200,
'status' => 'ok',
'challenge' => $status->challenge()
];
}
}
],
[
'pattern' => 'auth/logout',
'method' => 'POST',
'auth' => false,
'action' => function () {
$this->kirby()->auth()->logout();
return true;
}
],
];

View file

@ -0,0 +1,123 @@
<?php
/**
* Files Routes
*/
return [
[
'pattern' => '(:all)/files/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $path, string $filename, string $sectionName) {
if ($section = $this->file($path, $filename)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
[
'pattern' => '(:all)/files/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $parent, string $filename, string $fieldName, string $path = null) {
if ($file = $this->file($parent, $filename)) {
return $this->fieldApi($file, $fieldName, $path);
}
}
],
[
'pattern' => '(:all)/files',
'method' => 'GET',
'action' => function (string $path) {
return $this->parent($path)->files()->sort('sort', 'asc', 'filename', 'asc');
}
],
[
'pattern' => '(:all)/files',
'method' => 'POST',
'action' => function (string $path) {
return $this->upload(function ($source, $filename) use ($path) {
return $this->parent($path)->createFile([
'source' => $source,
'template' => $this->requestBody('template'),
'filename' => $filename
]);
});
}
],
[
'pattern' => '(:all)/files/search',
'method' => 'GET|POST',
'action' => function (string $path) {
$files = $this->parent($path)->files();
if ($this->requestMethod() === 'GET') {
return $files->search($this->requestQuery('q'));
} else {
return $files->query($this->requestBody());
}
}
],
[
'pattern' => '(:all)/files/sort',
'method' => 'PATCH',
'action' => function (string $path) {
return $this->parent($path)->files()->changeSort(
$this->requestBody('files'),
$this->requestBody('index')
);
}
],
[
'pattern' => '(:all)/files/(:any)',
'method' => 'GET',
'action' => function (string $path, string $filename) {
return $this->file($path, $filename);
}
],
[
'pattern' => '(:all)/files/(:any)',
'method' => 'PATCH',
'action' => function (string $path, string $filename) {
return $this->file($path, $filename)->update($this->requestBody(), $this->language(), true);
}
],
[
'pattern' => '(:all)/files/(:any)',
'method' => 'POST',
'action' => function (string $path, string $filename) {
return $this->upload(function ($source) use ($path, $filename) {
return $this->file($path, $filename)->replace($source);
});
}
],
[
'pattern' => '(:all)/files/(:any)',
'method' => 'DELETE',
'action' => function (string $path, string $filename) {
return $this->file($path, $filename)->delete();
}
],
[
'pattern' => '(:all)/files/(:any)/name',
'method' => 'PATCH',
'action' => function (string $path, string $filename) {
return $this->file($path, $filename)->changeName($this->requestBody('name'));
}
],
[
'pattern' => 'files/search',
'method' => 'GET|POST',
'action' => function () {
$files = $this
->site()
->index(true)
->filter('isReadable', true)
->files();
if ($this->requestMethod() === 'GET') {
return $files->search($this->requestQuery('q'));
} else {
return $files->query($this->requestBody());
}
}
],
];

View file

@ -0,0 +1,46 @@
<?php
/**
* Roles Routes
*/
return [
[
'pattern' => 'languages',
'method' => 'GET',
'action' => function () {
return $this->kirby()->languages();
}
],
[
'pattern' => 'languages',
'method' => 'POST',
'action' => function () {
return $this->kirby()->languages()->create($this->requestBody());
}
],
[
'pattern' => 'languages/(:any)',
'method' => 'GET',
'action' => function (string $code) {
return $this->kirby()->languages()->find($code);
}
],
[
'pattern' => 'languages/(:any)',
'method' => 'PATCH',
'action' => function (string $code) {
if ($language = $this->kirby()->languages()->find($code)) {
return $language->update($this->requestBody());
}
}
],
[
'pattern' => 'languages/(:any)',
'method' => 'DELETE',
'action' => function (string $code) {
if ($language = $this->kirby()->languages()->find($code)) {
return $language->delete();
}
}
]
];

View file

@ -0,0 +1,99 @@
<?php
use Kirby\Exception\Exception;
/**
* Content Lock Routes
*/
return [
[
'pattern' => '(:all)/lock',
'method' => 'GET',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return [
'supported' => true,
'locked' => $lock->get()
];
}
return [
'supported' => false,
'locked' => null
];
}
],
[
'pattern' => '(:all)/lock',
'method' => 'PATCH',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->create();
}
throw new Exception([
'key' => 'lock.notImplemented',
'httpCode' => 501
]);
}
],
[
'pattern' => '(:all)/lock',
'method' => 'DELETE',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->remove();
}
throw new Exception([
'key' => 'lock.notImplemented',
'httpCode' => 501
]);
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'GET',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return [
'supported' => true,
'unlocked' => $lock->isUnlocked()
];
}
return [
'supported' => false,
'unlocked' => null
];
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'PATCH',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->unlock();
}
throw new Exception([
'key' => 'lock.notImplemented',
'httpCode' => 501
]);
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'DELETE',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->resolve();
}
throw new Exception([
'key' => 'lock.notImplemented',
'httpCode' => 501
]);
}
],
];

View file

@ -0,0 +1,127 @@
<?php
/**
* Page Routes
*/
return [
[
'pattern' => 'pages/(:any)',
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id);
}
],
[
'pattern' => 'pages/(:any)',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->page($id)->update($this->requestBody(), $this->language(), true);
}
],
[
'pattern' => 'pages/(:any)',
'method' => 'DELETE',
'action' => function (string $id) {
return $this->page($id)->delete($this->requestBody('force', false));
}
],
[
'pattern' => 'pages/(:any)/blueprint',
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id)->blueprint();
}
],
[
'pattern' => [
'pages/(:any)/blueprints',
/**
* @deprecated
* @todo remove in 3.6.0
*/
'pages/(:any)/children/blueprints',
],
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id)->blueprints($this->requestQuery('section'));
}
],
[
'pattern' => 'pages/(:any)/children',
'method' => 'GET',
'action' => function (string $id) {
return $this->pages($id, $this->requestQuery('status'));
}
],
[
'pattern' => 'pages/(:any)/children',
'method' => 'POST',
'action' => function (string $id) {
return $this->page($id)->createChild($this->requestBody());
}
],
[
'pattern' => 'pages/(:any)/children/search',
'method' => 'GET|POST',
'action' => function (string $id) {
return $this->searchPages($id);
}
],
[
'pattern' => 'pages/(:any)/duplicate',
'method' => 'POST',
'action' => function (string $id) {
return $this->page($id)->duplicate($this->requestBody('slug'), [
'children' => $this->requestBody('children'),
'files' => $this->requestBody('files'),
]);
}
],
[
'pattern' => 'pages/(:any)/slug',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->page($id)->changeSlug($this->requestBody('slug'));
}
],
[
'pattern' => 'pages/(:any)/status',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->page($id)->changeStatus($this->requestBody('status'), $this->requestBody('position'));
}
],
[
'pattern' => 'pages/(:any)/template',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->page($id)->changeTemplate($this->requestBody('template'));
}
],
[
'pattern' => 'pages/(:any)/title',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->page($id)->changeTitle($this->requestBody('title'));
}
],
[
'pattern' => 'pages/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $id, string $sectionName) {
if ($section = $this->page($id)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
[
'pattern' => 'pages/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $id, string $fieldName, string $path = null) {
if ($page = $this->page($id)) {
return $this->fieldApi($page, $fieldName, $path);
}
}
],
];

View file

@ -0,0 +1,28 @@
<?php
/**
* Roles Routes
*/
return [
[
'pattern' => 'roles',
'method' => 'GET',
'action' => function () {
switch (get('canBe')) {
case 'changed':
return $this->kirby()->roles()->canBeChanged();
case 'created':
return $this->kirby()->roles()->canBeCreated();
default:
return $this->kirby()->roles();
}
}
],
[
'pattern' => 'roles/(:any)',
'method' => 'GET',
'action' => function (string $name) {
return $this->kirby()->roles()->find($name);
}
]
];

View file

@ -0,0 +1,110 @@
<?php
/**
* Site Routes
*/
return [
[
'pattern' => 'site',
'action' => function () {
return $this->site();
}
],
[
'pattern' => 'site',
'method' => 'PATCH',
'action' => function () {
return $this->site()->update($this->requestBody(), $this->language(), true);
}
],
[
'pattern' => 'site/children',
'method' => 'GET',
'action' => function () {
return $this->pages(null, $this->requestQuery('status'));
}
],
[
'pattern' => 'site/children',
'method' => 'POST',
'action' => function () {
return $this->site()->createChild($this->requestBody());
}
],
[
'pattern' => 'site/children/search',
'method' => 'GET|POST',
'action' => function () {
return $this->searchPages();
}
],
[
'pattern' => 'site/blueprint',
'method' => 'GET',
'action' => function () {
return $this->site()->blueprint();
}
],
[
'pattern' => [
'site/blueprints',
/**
* @deprecated
* @todo remove in 3.6.0
*/
'site/children/blueprints',
],
'method' => 'GET',
'action' => function () {
return $this->site()->blueprints($this->requestQuery('section'));
}
],
[
'pattern' => 'site/find',
'method' => 'POST',
'action' => function () {
return $this->site()->find(false, ...$this->requestBody());
}
],
[
'pattern' => 'site/title',
'method' => 'PATCH',
'action' => function () {
return $this->site()->changeTitle($this->requestBody('title'));
}
],
[
'pattern' => 'site/search',
'method' => 'GET|POST',
'action' => function () {
$pages = $this
->site()
->index(true)
->filter('isReadable', true);
if ($this->requestMethod() === 'GET') {
return $pages->search($this->requestQuery('q'));
} else {
return $pages->query($this->requestBody());
}
}
],
[
'pattern' => 'site/sections/(:any)',
'method' => 'GET',
'action' => function (string $sectionName) {
if ($section = $this->site()->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
[
'pattern' => 'site/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $fieldName, string $path = null) {
return $this->fieldApi($this->site(), $fieldName, $path);
}
]
];

View file

@ -0,0 +1,79 @@
<?php
use Kirby\Exception\Exception;
use Kirby\Exception\InvalidArgumentException;
/**
* System Routes
*/
return [
[
'pattern' => 'system',
'method' => 'GET',
'auth' => false,
'action' => function () {
$system = $this->kirby()->system();
if ($this->kirby()->user()) {
return $system;
} else {
if ($system->isOk() === true) {
$info = $this->resolve($system)->view('login')->toArray();
} else {
$info = $this->resolve($system)->view('troubleshooting')->toArray();
}
return [
'status' => 'ok',
'data' => $info,
'type' => 'model'
];
}
}
],
[
'pattern' => 'system/register',
'method' => 'POST',
'action' => function () {
return $this->kirby()->system()->register($this->requestBody('license'), $this->requestBody('email'));
}
],
[
'pattern' => 'system/install',
'method' => 'POST',
'auth' => false,
'action' => function () {
$system = $this->kirby()->system();
$auth = $this->kirby()->auth();
// csrf token check
if ($auth->type() === 'session' && $auth->csrf() === false) {
throw new InvalidArgumentException('Invalid CSRF token');
}
if ($system->isOk() === false) {
throw new Exception('The server is not setup correctly');
}
if ($system->isInstallable() === false) {
throw new Exception('The Panel cannot be installed');
}
if ($system->isInstalled() === true) {
throw new Exception('The Panel is already installed');
}
// create the first user
$user = $this->users()->create($this->requestBody());
$token = $user->login($this->requestBody('password'));
return [
'status' => 'ok',
'token' => $token,
'user' => $this->resolve($user)->view('auth')->toArray()
];
}
]
];

View file

@ -0,0 +1,24 @@
<?php
/**
* Translations Routes
*/
return [
[
'pattern' => 'translations',
'method' => 'GET',
'auth' => false,
'action' => function () {
return $this->kirby()->translations();
}
],
[
'pattern' => 'translations/(:any)',
'method' => 'GET',
'auth' => false,
'action' => function (string $code) {
return $this->kirby()->translations()->find($code);
}
]
];

View file

@ -0,0 +1,160 @@
<?php
use Kirby\Toolkit\F;
/**
* User Routes
*/
return [
[
'pattern' => 'users',
'method' => 'GET',
'action' => function () {
return $this->users()->sort('username', 'asc', 'email', 'asc');
}
],
[
'pattern' => 'users',
'method' => 'POST',
'action' => function () {
return $this->users()->create($this->requestBody());
}
],
[
'pattern' => 'users/search',
'method' => 'GET|POST',
'action' => function () {
if ($this->requestMethod() === 'GET') {
return $this->users()->search($this->requestQuery('q'));
} else {
return $this->users()->query($this->requestBody());
}
}
],
[
'pattern' => 'users/(:any)',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id);
}
],
[
'pattern' => 'users/(:any)',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->update($this->requestBody(), $this->language(), true);
}
],
[
'pattern' => 'users/(:any)',
'method' => 'DELETE',
'action' => function (string $id) {
return $this->user($id)->delete();
}
],
[
'pattern' => 'users/(:any)/avatar',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id)->avatar();
}
],
[
'pattern' => 'users/(:any)/avatar',
'method' => 'POST',
'action' => function (string $id) {
if ($avatar = $this->user($id)->avatar()) {
$avatar->delete();
}
return $this->upload(function ($source, $filename) use ($id) {
return $this->user($id)->createFile([
'filename' => 'profile.' . F::extension($filename),
'template' => 'avatar',
'source' => $source
]);
}, $single = true);
}
],
[
'pattern' => 'users/(:any)/avatar',
'method' => 'DELETE',
'action' => function (string $id) {
return $this->user($id)->avatar()->delete();
}
],
[
'pattern' => 'users/(:any)/blueprint',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id)->blueprint();
}
],
[
'pattern' => 'users/(:any)/blueprints',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id)->blueprints($this->requestQuery('section'));
}
],
[
'pattern' => 'users/(:any)/email',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->changeEmail($this->requestBody('email'));
}
],
[
'pattern' => 'users/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $id, string $fieldName, string $path = null) {
if ($user = $this->user($id)) {
return $this->fieldApi($user, $fieldName, $path);
}
}
],
[
'pattern' => 'users/(:any)/language',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->changeLanguage($this->requestBody('language'));
}
],
[
'pattern' => 'users/(:any)/name',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->changeName($this->requestBody('name'));
}
],
[
'pattern' => 'users/(:any)/password',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->changePassword($this->requestBody('password'));
}
],
[
'pattern' => 'users/(:any)/role',
'method' => 'PATCH',
'action' => function (string $id) {
return $this->user($id)->changeRole($this->requestBody('role'));
}
],
[
'pattern' => 'users/(:any)/roles',
'action' => function (string $id) {
return $this->user($id)->roles();
}
],
[
'pattern' => 'users/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $id, string $sectionName) {
if ($section = $this->user($id)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
];

View file

@ -0,0 +1,2 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<pre><code class="language-<?= $block->language()->or('text') ?>"><?= $block->code()->html(false) ?></code></pre>

View file

@ -0,0 +1,59 @@
name: field.blocks.code.name
icon: code
wysiwyg: true
preview: code
fields:
code:
label: field.blocks.code.name
type: textarea
placeholder: field.blocks.code.placeholder
buttons: false
font: monospace
language:
label: field.blocks.code.language
type: select
default: text
options:
bash: Bash
basic: BASIC
c: C
clojure: Clojure
cpp: C++
csharp: C#
css: CSS
diff: Diff
elixir: Elixir
elm: Elm
erlang: Erlang
go: Go
graphql: GraphQL
haskell: Haskell
html: HTML
java: Java
js: JavaScript
json: JSON
latext: LaTeX
less: Less
lisp: Lisp
lua: Lua
makefile: Makefile
markdown: Markdown
markup: Markup
objectivec: Objective-C
pascal: Pascal
perl: Perl
php: PHP
text: Plain Text
python: Python
r: R
ruby: Ruby
rust: Rust
sass: Sass
scss: SCSS
shell: Shell
sql: SQL
swift: Swift
typescript: TypeScript
vbnet: VB.net
xml: XML
yaml: YAML

View file

@ -0,0 +1,10 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<figure>
<ul>
<?php foreach ($block->images()->toFiles() as $image): ?>
<li>
<?= $image ?>
</li>
<?php endforeach ?>
</ul>
</figure>

View file

@ -0,0 +1,15 @@
name: field.blocks.gallery.name
icon: dashboard
preview: gallery
fields:
images:
label: field.blocks.gallery.images.label
type: files
multiple: true
layout: cards
size: tiny
empty: field.blocks.gallery.images.empty
uploads:
template: blocks/image
image:
ratio: 1/1

View file

@ -0,0 +1,2 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<<?= $level = $block->level()->or('h2') ?>><?= $block->text() ?></<?= $level ?>>

View file

@ -0,0 +1,24 @@
name: field.blocks.heading.name
icon: title
wysiwyg: true
preview: heading
fields:
level:
label: field.blocks.heading.level
type: select
empty: false
default: "h2"
width: 1/6
options:
- h1
- h2
- h3
- h4
- h5
- h6
text:
label: field.blocks.heading.text
type: writer
inline: true
width: 5/6
placeholder: field.blocks.heading.placeholder

View file

@ -0,0 +1,35 @@
<?php
/** @var \Kirby\Cms\Block $block */
$alt = $block->alt();
$caption = $block->caption();
$crop = $block->crop()->isTrue();
$link = $block->link();
$ratio = $block->ratio()->or('auto');
$src = null;
if ($block->location() == 'web') {
$src = $block->src();
} elseif ($image = $block->image()->toFile()) {
$alt = $alt ?? $image->alt();
$src = $image->url();
}
?>
<?php if ($src): ?>
<figure<?= attr(['data-ratio' => $ratio, 'data-crop' => $crop], ' ') ?>>
<?php if ($link->isNotEmpty()): ?>
<a href="<?= $link->toUrl() ?>">
<img src="<?= $src ?>" alt="<?= $alt ?>">
</a>
<?php else: ?>
<img src="<?= $src ?>" alt="<?= $alt ?>">
<?php endif ?>
<?php if ($caption->isNotEmpty()): ?>
<figcaption>
<?= $caption ?>
</figcaption>
<?php endif ?>
</figure>
<?php endif ?>

View file

@ -0,0 +1,59 @@
name: field.blocks.image.name
icon: image
preview: image
fields:
location:
label: field.blocks.image.location
type: radio
columns: 2
default: "kirby"
options:
kirby: Kirby
web: Web
image:
label: field.blocks.image.name
type: files
multiple: false
image:
back: black
uploads:
template: blocks/image
when:
location: kirby
src:
label: field.blocks.image.url
type: url
when:
location: web
alt:
label: field.blocks.image.alt
type: text
icon: title
caption:
label: field.blocks.image.caption
type: writer
icon: text
inline: true
link:
label: field.blocks.image.link
type: text
icon: url
ratio:
label: field.blocks.image.ratio
type: select
placeholder: Auto
width: 1/2
options:
1/1: "1:1"
16/9: "16:9"
10/8: "10:8"
21/9: "21:9"
7/5: "7:5"
4/3: "4:3"
5/3: "5:3"
3/2: "3:2"
3/1: "3:1"
crop:
label: field.blocks.image.crop
type: toggle
width: 1/2

View file

@ -0,0 +1,2 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<?= $block->text();

View file

@ -0,0 +1,8 @@
name: field.blocks.list.name
icon: list-bullet
wysiwyg: true
preview: list
fields:
text:
label: field.blocks.list.name
type: list

View file

@ -0,0 +1,2 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<?= $block->text()->kt();

View file

@ -0,0 +1,11 @@
name: field.blocks.markdown.name
icon: markdown
preview: markdown
wysiwyg: true
fields:
text:
label: field.blocks.markdown.label
placeholder: field.blocks.markdown.placeholder
type: textarea
buttons: false
font: monospace

View file

@ -0,0 +1,9 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<blockquote>
<?= $block->text() ?>
<?php if ($block->citation()->isNotEmpty()): ?>
<footer>
<?= $block->citation() ?>
</footer>
<?php endif ?>
</blockquote>

View file

@ -0,0 +1,17 @@
name: field.blocks.quote.name
icon: quote
wysiwyg: true
preview: quote
fields:
text:
label: field.blocks.quote.text.label
placeholder: field.blocks.quote.text.placeholder
type: writer
inline: true
icon: quote
citation:
label: field.blocks.quote.citation.label
placeholder: field.blocks.quote.citation.placeholder
type: writer
inline: true
icon: user

View file

@ -0,0 +1,3 @@
name: Table
icon: menu
preview: table

View file

@ -0,0 +1,2 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<?= $block->text();

View file

@ -0,0 +1,9 @@
name: field.blocks.text.name
icon: text
wysiwyg: true
preview: text
fields:
text:
type: writer
nodes: false
placeholder: field.blocks.text.placeholder

View file

@ -0,0 +1,9 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<?php if ($block->url()->isNotEmpty()): ?>
<figure>
<?= video($block->url()) ?>
<?php if ($block->caption()->isNotEmpty()): ?>
<figcaption><?= $block->caption() ?></figcaption>
<?php endif ?>
</figure>
<?php endif ?>

View file

@ -0,0 +1,12 @@
name: field.blocks.video.name
icon: video
preview: video
fields:
url:
label: field.blocks.video.url.label
type: url
placeholder: field.blocks.video.url.placeholder
caption:
label: field.blocks.video.caption
type: writer
inline: true

View file

@ -0,0 +1,26 @@
<?php
$blocksRoot = __DIR__ . '/blocks';
return [
// blocks
'blocks/code' => $blocksRoot . '/code/code.yml',
'blocks/gallery' => $blocksRoot . '/gallery/gallery.yml',
'blocks/heading' => $blocksRoot . '/heading/heading.yml',
'blocks/image' => $blocksRoot . '/image/image.yml',
'blocks/list' => $blocksRoot . '/list/list.yml',
'blocks/markdown' => $blocksRoot . '/markdown/markdown.yml',
'blocks/quote' => $blocksRoot . '/quote/quote.yml',
'blocks/table' => $blocksRoot . '/table/table.yml',
'blocks/text' => $blocksRoot . '/text/text.yml',
'blocks/video' => $blocksRoot . '/video/video.yml',
// file blueprints
'files/default' => __DIR__ . '/blueprints/files/default.yml',
// page blueprints
'pages/default' => __DIR__ . '/blueprints/pages/default.yml',
// site blueprints
'site' => __DIR__ . '/blueprints/site.yml'
];

View file

@ -0,0 +1,56 @@
name: Code
icon: code
fields:
code:
label: Code
type: textarea
buttons: false
font: monospace
language:
label: Language
type: select
default: text
options:
bash: Bash
basic: BASIC
c: C
clojure: Clojure
cpp: C++
csharp: C#
css: CSS
diff: Diff
elixir: Elixir
elm: Elm
erlang: Erlang
go: Go
graphql: GraphQL
haskell: Haskell
html: HTML
java: Java
js: JavaScript
json: JSON
latext: LaTeX
less: Less
lisp: Lisp
lua: Lua
makefile: Makefile
markdown: Markdown
markup: Markup
objectivec: Objective-C
pascal: Pascal
perl: Perl
php: PHP
text: Plain Text
python: Python
r: R
ruby: Ruby
rust: Rust
sass: Sass
scss: SCSS
shell: Shell
sql: SQL
swift: Swift
typescript: TypeScript
vbnet: VB.net
xml: XML
yaml: YAML

View file

@ -0,0 +1,21 @@
icon: title
fields:
text:
type: text
level:
type: select
width: 1/2
default: 1
empty: false
default: "2"
options:
- value: "1"
text: Heading 1
- value: "2"
text: Heading 2
- value: "3"
text: Heading 3
id:
type: text
label: ID
width: 1/2

View file

@ -0,0 +1,16 @@
name: Image
icon: image
fields:
image:
type: files
multiple: false
alt:
type: text
icon: title
caption:
type: writer
inline: true
icon: text
link:
type: text
icon: url

View file

@ -0,0 +1,12 @@
name: Quote
icon: quote
fields:
text:
label: Quote Text
type: writer
inline: true
citation:
label: Citation
type: writer
inline: true
placeholder: by …

View file

@ -0,0 +1,25 @@
name: Table
icon: menu
fields:
rows:
label: Menu
type: structure
columns:
dish: true
description: true
price:
before:
width: 1/4
align: right
fields:
dish:
label: Dish
type: text
description:
label: Description
type: text
price:
label: Price
type: number
before:
step: 0.01

View file

@ -0,0 +1,5 @@
name: Text
icon: text
fields:
text:
type: writer

View file

@ -0,0 +1,8 @@
name: Video
icon: video
label: "{{ url }}"
fields:
url:
type: url
caption:
type: writer

View file

@ -0,0 +1,2 @@
name: File
title: file

View file

@ -0,0 +1,3 @@
name: Page
title: Page

View file

@ -0,0 +1,7 @@
name: Site
title: Site
sections:
pages:
headline: Pages
type: pages

378
kirby/config/components.php Normal file
View file

@ -0,0 +1,378 @@
<?php
use Kirby\Cms\App;
use Kirby\Cms\Collection;
use Kirby\Cms\File;
use Kirby\Cms\Filename;
use Kirby\Cms\FileVersion;
use Kirby\Cms\Template;
use Kirby\Data\Data;
use Kirby\Http\Server;
use Kirby\Http\Uri;
use Kirby\Http\Url;
use Kirby\Image\Darkroom;
use Kirby\Text\Markdown;
use Kirby\Text\SmartyPants;
use Kirby\Toolkit\A;
use Kirby\Toolkit\F;
use Kirby\Toolkit\Str;
use Kirby\Toolkit\Tpl as Snippet;
return [
/**
* Used by the `css()` helper
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $url Relative or absolute URL
* @param string|array $options An array of attributes for the link tag or a media attribute string
*/
'css' => function (App $kirby, string $url, $options = null): string {
return $url;
},
/**
* Object and variable dumper
* to help with debugging.
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param mixed $variable
* @param bool $echo
* @return string
*/
'dump' => function (App $kirby, $variable, bool $echo = true) {
if (Server::cli() === true) {
$output = print_r($variable, true) . PHP_EOL;
} else {
$output = '<pre>' . print_r($variable, true) . '</pre>';
}
if ($echo === true) {
echo $output;
}
return $output;
},
/**
* Modify URLs for file objects
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param \Kirby\Cms\File $file The original file object
* @return string
*/
'file::url' => function (App $kirby, File $file): string {
return $file->mediaUrl();
},
/**
* Adapt file characteristics
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param \Kirby\Cms\File|\Kirby\Cms\FileModifications $file The file object
* @param array $options All thumb options (width, height, crop, blur, grayscale)
* @return \Kirby\Cms\File|\Kirby\Cms\FileVersion
*/
'file::version' => function (App $kirby, $file, array $options = []) {
if ($file->isResizable() === false) {
return $file;
}
// create url and root
$mediaRoot = dirname($file->mediaRoot());
$template = $mediaRoot . '/{{ name }}{{ attributes }}.{{ extension }}';
$thumbRoot = (new Filename($file->root(), $template, $options))->toString();
$thumbName = basename($thumbRoot);
$job = $mediaRoot . '/.jobs/' . $thumbName . '.json';
if (file_exists($thumbRoot) === false) {
try {
Data::write($job, array_merge($options, [
'filename' => $file->filename()
]));
} catch (Throwable $e) {
return $file;
}
}
return new FileVersion([
'modifications' => $options,
'original' => $file,
'root' => $thumbRoot,
'url' => dirname($file->mediaUrl()) . '/' . $thumbName,
]);
},
/**
* Used by the `js()` helper
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $url Relative or absolute URL
* @param string|array $options An array of attributes for the link tag or a media attribute string
*/
'js' => function (App $kirby, string $url, $options = null): string {
return $url;
},
/**
* Add your own Markdown parser
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $text Text to parse
* @param array $options Markdown options
* @param bool $inline Whether to wrap the text in `<p>` tags
* @return string
*/
'markdown' => function (App $kirby, string $text = null, array $options = [], bool $inline = false): string {
static $markdown;
static $config;
// if the config options have changed or the component is called for the first time,
// (re-)initialize the parser object
if ($config !== $options) {
$markdown = new Markdown($options);
$config = $options;
}
return $markdown->parse($text, $inline);
},
/**
* Add your own search engine
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param \Kirby\Cms\Collection $collection Collection of searchable models
* @param string $query
* @param mixed $params
* @return \Kirby\Cms\Collection|bool
*/
'search' => function (App $kirby, Collection $collection, string $query = null, $params = []) {
if (empty(trim($query)) === true) {
return $collection->limit(0);
}
if (is_string($params) === true) {
$params = ['fields' => Str::split($params, '|')];
}
$defaults = [
'fields' => [],
'minlength' => 2,
'score' => [],
'words' => false,
];
$options = array_merge($defaults, $params);
$collection = clone $collection;
$searchWords = preg_replace('/(\s)/u', ',', $query);
$searchWords = Str::split($searchWords, ',', $options['minlength']);
$lowerQuery = Str::lower($query);
$exactQuery = $options['words'] ? '(\b' . preg_quote($query) . '\b)' : preg_quote($query);
if (empty($options['stopwords']) === false) {
$searchWords = array_diff($searchWords, $options['stopwords']);
}
$searchWords = array_map(function ($value) use ($options) {
return $options['words'] ? '\b' . preg_quote($value) . '\b' : preg_quote($value);
}, $searchWords);
$preg = '!(' . implode('|', $searchWords) . ')!i';
$results = $collection->filter(function ($item) use ($query, $preg, $options, $lowerQuery, $exactQuery) {
$data = $item->content()->toArray();
$keys = array_keys($data);
$keys[] = 'id';
if (is_a($item, 'Kirby\Cms\User') === true) {
$keys[] = 'name';
$keys[] = 'email';
$keys[] = 'role';
} elseif (is_a($item, 'Kirby\Cms\Page') === true) {
// apply the default score for pages
$options['score'] = array_merge([
'id' => 64,
'title' => 64,
], $options['score']);
}
if (empty($options['fields']) === false) {
$fields = array_map('strtolower', $options['fields']);
$keys = array_intersect($keys, $fields);
}
$item->searchHits = 0;
$item->searchScore = 0;
foreach ($keys as $key) {
$score = $options['score'][$key] ?? 1;
$value = $data[$key] ?? (string)$item->$key();
$lowerValue = Str::lower($value);
// check for exact matches
if ($lowerQuery == $lowerValue) {
$item->searchScore += 16 * $score;
$item->searchHits += 1;
// check for exact beginning matches
} elseif ($options['words'] === false && Str::startsWith($lowerValue, $lowerQuery) === true) {
$item->searchScore += 8 * $score;
$item->searchHits += 1;
// check for exact query matches
} elseif ($matches = preg_match_all('!' . $exactQuery . '!i', $value, $r)) {
$item->searchScore += 2 * $score;
$item->searchHits += $matches;
}
// check for any match
if ($matches = preg_match_all($preg, $value, $r)) {
$item->searchHits += $matches;
$item->searchScore += $matches * $score;
}
}
return $item->searchHits > 0 ? true : false;
});
return $results->sort('searchScore', 'desc');
},
/**
* Add your own SmartyPants parser
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $text Text to parse
* @param array $options SmartyPants options
* @return string
*/
'smartypants' => function (App $kirby, string $text = null, array $options = []): string {
static $smartypants;
static $config;
// if the config options have changed or the component is called for the first time,
// (re-)initialize the parser object
if ($config !== $options) {
$smartypants = new Smartypants($options);
$config = $options;
}
return $smartypants->parse($text);
},
/**
* Add your own snippet loader
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string|array $name Snippet name
* @param array $data Data array for the snippet
* @return string|null
*/
'snippet' => function (App $kirby, $name, array $data = []): ?string {
$snippets = A::wrap($name);
foreach ($snippets as $name) {
$name = (string)$name;
$file = $kirby->root('snippets') . '/' . $name . '.php';
if (file_exists($file) === false) {
$file = $kirby->extensions('snippets')[$name] ?? null;
}
if ($file) {
break;
}
}
return Snippet::load($file, $data);
},
/**
* Add your own template engine
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $name Template name
* @param string $type Extension type
* @param string $defaultType Default extension type
* @return \Kirby\Cms\Template
*/
'template' => function (App $kirby, string $name, string $type = 'html', string $defaultType = 'html') {
return new Template($name, $type, $defaultType);
},
/**
* Add your own thumb generator
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $src The root of the original file
* @param string $template The template for the root to the desired destination
* @param array $options All thumb options that should be applied: `width`, `height`, `crop`, `blur`, `grayscale`
* @return string
*/
'thumb' => function (App $kirby, string $src, string $template, array $options): string {
$darkroom = Darkroom::factory(option('thumbs.driver', 'gd'), option('thumbs', []));
$options = $darkroom->preprocess($src, $options);
$root = (new Filename($src, $template, $options))->toString();
F::copy($src, $root, true);
$darkroom->process($root, $options);
return $root;
},
/**
* Modify all URLs
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $path URL path
* @param array|string|null $options Array of options for the Uri class
* @param Closure $originalHandler Deprecated: Callback function to the original URL handler with `$path` and `$options` as parameters
* Use `$kirby->nativeComponent('url')` inside your URL component instead.
* @return string
*
* @todo Remove $originalHandler parameter in 3.6.0
*/
'url' => function (App $kirby, string $path = null, $options = null, Closure $originalHandler = null): string {
$language = null;
// get language from simple string option
if (is_string($options) === true) {
$language = $options;
$options = null;
}
// get language from array
if (is_array($options) === true && isset($options['language']) === true) {
$language = $options['language'];
unset($options['language']);
}
// get a language url for the linked page, if the page can be found
if ($kirby->multilang() === true) {
$parts = Str::split($path, '#');
if ($page = page($parts[0] ?? null)) {
$path = $page->url($language);
if (isset($parts[1]) === true) {
$path .= '#' . $parts[1];
}
}
}
// keep relative urls
if (substr($path, 0, 2) === './' || substr($path, 0, 3) === '../') {
return $path;
}
$url = Url::makeAbsolute($path, $kirby->url());
if ($options === null) {
return $url;
}
return (new Uri($url, $options))->toString();
},
];

32
kirby/config/fields.php Normal file
View file

@ -0,0 +1,32 @@
<?php
return [
'blocks' => 'Kirby\Form\Field\BlocksField',
'checkboxes' => __DIR__ . '/fields/checkboxes.php',
'date' => __DIR__ . '/fields/date.php',
'email' => __DIR__ . '/fields/email.php',
'files' => __DIR__ . '/fields/files.php',
'gap' => __DIR__ . '/fields/gap.php',
'headline' => __DIR__ . '/fields/headline.php',
'hidden' => __DIR__ . '/fields/hidden.php',
'info' => __DIR__ . '/fields/info.php',
'layout' => 'Kirby\Form\Field\LayoutField',
'line' => __DIR__ . '/fields/line.php',
'list' => __DIR__ . '/fields/list.php',
'multiselect' => __DIR__ . '/fields/multiselect.php',
'number' => __DIR__ . '/fields/number.php',
'pages' => __DIR__ . '/fields/pages.php',
'radio' => __DIR__ . '/fields/radio.php',
'range' => __DIR__ . '/fields/range.php',
'select' => __DIR__ . '/fields/select.php',
'structure' => __DIR__ . '/fields/structure.php',
'tags' => __DIR__ . '/fields/tags.php',
'tel' => __DIR__ . '/fields/tel.php',
'text' => __DIR__ . '/fields/text.php',
'textarea' => __DIR__ . '/fields/textarea.php',
'time' => __DIR__ . '/fields/time.php',
'toggle' => __DIR__ . '/fields/toggle.php',
'url' => __DIR__ . '/fields/url.php',
'users' => __DIR__ . '/fields/users.php',
'writer' => __DIR__ . '/fields/writer.php'
];

View file

@ -0,0 +1,61 @@
<?php
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
return [
'mixins' => ['min', 'options'],
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'before' => null,
'icon' => null,
'placeholder' => null,
/**
* Arranges the checkboxes in the given number of columns
*/
'columns' => function (int $columns = 1) {
return $columns;
},
/**
* Default value for the field, which will be used when a page/file/user is created
*/
'default' => function ($default = null) {
return Str::split($default, ',');
},
/**
* Maximum number of checked boxes
*/
'max' => function (int $max = null) {
return $max;
},
/**
* Minimum number of checked boxes
*/
'min' => function (int $min = null) {
return $min;
},
'value' => function ($value = null) {
return Str::split($value, ',');
},
],
'computed' => [
'default' => function () {
return $this->sanitizeOptions($this->default);
},
'value' => function () {
return $this->sanitizeOptions($this->value);
},
],
'save' => function ($value): string {
return A::join($value, ', ');
},
'validations' => [
'options',
'max',
'min'
]
];

View file

@ -0,0 +1,179 @@
<?php
use Kirby\Exception\Exception;
use Kirby\Form\Field;
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;
return [
'mixins' => ['datetime'],
'props' => [
/**
* Unset inherited props
*/
'placeholder' => null,
/**
* Activate/deactivate the dropdown calendar
*/
'calendar' => function (bool $calendar = true) {
return $calendar;
},
/**
* Default date when a new page/file/user gets created
*/
'default' => function (string $default = null) {
return $default;
},
/**
* Custom format (dayjs tokens: `DD`, `MM`, `YYYY`) that is
* used to display the field in the Panel
*/
'display' => function ($display = 'YYYY-MM-DD') {
return I18n::translate($display, $display);
},
/**
* Changes the calendar icon to something custom
*/
'icon' => function (string $icon = 'calendar') {
return $icon;
},
/**
* Latest date, which can be selected/saved (Y-m-d)
*/
'max' => function (string $max = null) {
return $this->toDatetime($max);
},
/**
* Earliest date, which can be selected/saved (Y-m-d)
*/
'min' => function (string $min = null) {
return $this->toDatetime($min);
},
/**
* Round to the nearest: sub-options for `unit` (day) and `size` (1)
*/
'step' => function ($step = null) {
$default = [
'size' => 1,
'unit' => 'day'
];
if ($step === null) {
return $default;
}
if (is_array($step) === true) {
$step = array_merge($default, $step);
$step['unit'] = strtolower($step['unit']);
return $step;
}
if (is_int($step) === true) {
return array_merge($default, ['size' => $step]);
}
if (is_string($step) === true) {
return array_merge($default, ['unit' => strtolower($step)]);
}
},
/**
* Pass `true` or an array of time field options to show the time selector.
*/
'time' => function ($time = false) {
return $time;
},
/**
* Must be a parseable date string
*/
'value' => function ($value = null) {
return $value;
},
],
'computed' => [
'default' => function () {
return $this->toDatetime($this->default);
},
'display' => function () {
if ($this->display) {
return Str::upper($this->display);
}
},
'format' => function () {
return $this->props['format'] ?? ($this->time === false ? 'Y-m-d' : 'Y-m-d H:i:s');
},
'time' => function () {
if ($this->time === false) {
return false;
}
$props = is_array($this->time) ? $this->time : [];
$props['model'] = $this->model();
$field = new Field('time', $props);
return $field->toArray();
},
'step' => function () {
if ($this->time === false) {
return $this->step;
}
return $this->time['step'];
},
'value' => function () {
return $this->toDatetime($this->value);
},
],
'validations' => [
'date',
'minMax' => function ($value) {
$min = $this->min ? strtotime($this->min) : null;
$max = $this->max ? strtotime($this->max) : null;
$value = strtotime($this->value());
$format = $this->time === false ? 'd.m.Y' : 'd.m.Y H:i';
$errors = [];
if ($value && $min && $value < $min) {
$errors['min'] = $min;
}
if ($value && $max && $value > $max) {
$errors['max'] = $max;
}
if (empty($errors) === false) {
if ($min && $max) {
throw new Exception([
'key' => 'validation.date.between',
'data' => [
'min' => date($format, $min),
'max' => date($format, $max)
]
]);
} elseif ($min) {
throw new Exception([
'key' => 'validation.date.after',
'data' => [
'date' => date($format, $min),
]
]);
} else {
throw new Exception([
'key' => 'validation.date.before',
'data' => [
'date' => date($format, $max),
]
]);
}
}
return true;
},
]
];

View file

@ -0,0 +1,40 @@
<?php
use Kirby\Toolkit\I18n;
return [
'extends' => 'text',
'props' => [
/**
* Unset inherited props
*/
'converter' => null,
'counter' => null,
/**
* Sets the HTML5 autocomplete mode for the input
*/
'autocomplete' => function (string $autocomplete = 'email') {
return $autocomplete;
},
/**
* Changes the email icon to something custom
*/
'icon' => function (string $icon = 'email') {
return $icon;
},
/**
* Custom placeholder text, when the field is empty.
*/
'placeholder' => function ($value = null) {
return I18n::translate($value, $value) ?? I18n::translate('email.placeholder');
}
],
'validations' => [
'minlength',
'maxlength',
'email'
]
];

View file

@ -0,0 +1,138 @@
<?php
use Kirby\Data\Data;
use Kirby\Toolkit\A;
return [
'mixins' => [
'picker',
'filepicker',
'min',
'upload'
],
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'before' => null,
'autofocus' => null,
'icon' => null,
'placeholder' => null,
/**
* Sets the file(s), which are selected by default when a new page is created
*/
'default' => function ($default = null) {
return $default;
},
/**
* Changes the layout of the selected files. Available layouts: `list`, `cards`
*/
'layout' => function (string $layout = 'list') {
return $layout;
},
/**
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
*/
'size' => function (string $size = 'auto') {
return $size;
},
'value' => function ($value = null) {
return $value;
}
],
'computed' => [
'parentModel' => function () {
if (is_string($this->parent) === true && $model = $this->model()->query($this->parent, 'Kirby\Cms\Model')) {
return $model;
}
return $this->model();
},
'parent' => function () {
return $this->parentModel->apiUrl(true);
},
'query' => function () {
return $this->query ?? $this->parentModel::CLASS_ALIAS . '.files';
},
'default' => function () {
return $this->toFiles($this->default);
},
'value' => function () {
return $this->toFiles($this->value);
},
],
'methods' => [
'fileResponse' => function ($file) {
return $file->panelPickerData([
'image' => $this->image,
'info' => $this->info ?? false,
'model' => $this->model(),
'text' => $this->text,
]);
},
'toFiles' => function ($value = null) {
$files = [];
foreach (Data::decode($value, 'yaml') as $id) {
if (is_array($id) === true) {
$id = $id['id'] ?? null;
}
if ($id !== null && ($file = $this->kirby()->file($id, $this->model()))) {
$files[] = $this->fileResponse($file);
}
}
return $files;
}
],
'api' => function () {
return [
[
'pattern' => '/',
'action' => function () {
$field = $this->field();
return $field->filepicker([
'image' => $field->image(),
'info' => $field->info(),
'limit' => $field->limit(),
'page' => $this->requestQuery('page'),
'query' => $field->query(),
'search' => $this->requestQuery('search'),
'text' => $field->text()
]);
}
],
[
'pattern' => 'upload',
'method' => 'POST',
'action' => function () {
$field = $this->field();
$uploads = $field->uploads();
return $field->upload($this, $uploads, function ($file, $parent) use ($field) {
return $file->panelPickerData([
'image' => $field->image(),
'info' => $field->info(),
'model' => $field->model(),
'text' => $field->text(),
]);
});
}
]
];
},
'save' => function ($value = null) {
return A::pluck($value, 'uuid');
},
'validations' => [
'max',
'min'
]
];

View file

@ -0,0 +1,5 @@
<?php
return [
'save' => false
];

View file

@ -0,0 +1,26 @@
<?php
return [
'save' => false,
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'autofocus' => null,
'before' => null,
'default' => null,
'disabled' => null,
'icon' => null,
'placeholder' => null,
'required' => null,
'translate' => null,
/**
* If `false`, the prepended number will be hidden
*/
'numbered' => function (bool $numbered = true) {
return $numbered;
}
]
];

View file

@ -0,0 +1,3 @@
<?php
return [];

View file

@ -0,0 +1,44 @@
<?php
use Kirby\Toolkit\I18n;
return [
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'autofocus' => null,
'before' => null,
'default' => null,
'disabled' => null,
'icon' => null,
'placeholder' => null,
'required' => null,
'translate' => null,
/**
* Text to be displayed
*/
'text' => function ($value = null) {
return I18n::translate($value, $value);
},
/**
* Change the design of the info box
*/
'theme' => function (string $theme = null) {
return $theme;
}
],
'computed' => [
'text' => function () {
if ($text = $this->text) {
$text = $this->model()->toString($text);
$text = $this->kirby()->kirbytext($text);
return $text;
}
}
],
'save' => false,
];

View file

@ -0,0 +1,5 @@
<?php
return [
'save' => false
];

View file

@ -0,0 +1,17 @@
<?php
return [
'props' => [
/**
* Sets the allowed HTML formats. Available formats: `bold`, `italic`, `underline`, `strike`, `code`, `link`. Activate them all by passing `true`. Deactivate them all by passing `false`
*/
'marks' => function ($marks = true) {
return $marks;
}
],
'computed' => [
'value' => function () {
return trim($this->value);
}
]
];

View file

@ -0,0 +1,28 @@
<?php
return [
'props' => [
/**
* Defines a custom format that is used when the field is saved
*/
'format' => function (string $format = null) {
return $format;
}
],
'methods' => [
'toDatetime' => function ($value, string $format = 'Y-m-d H:i:s') {
if ($timestamp = timestamp($value, $this->step)) {
return date($format, $timestamp);
}
return null;
}
],
'save' => function ($value) {
if ($value !== null && $timestamp = strtotime($value)) {
return date($this->format, $timestamp);
}
return '';
},
];

View file

@ -0,0 +1,14 @@
<?php
use Kirby\Cms\FilePicker;
return [
'methods' => [
'filepicker' => function (array $params = []) {
// fetch the parent model
$params['model'] = $this->model();
return (new FilePicker($params))->toArray();
}
]
];

View file

@ -0,0 +1,22 @@
<?php
return [
'computed' => [
'min' => function () {
// set min to at least 1, if required
if ($this->required === true) {
return $this->min ?? 1;
}
return $this->min;
},
'required' => function () {
// set required to true if min is set
if ($this->min) {
return true;
}
return $this->required;
}
]
];

View file

@ -0,0 +1,48 @@
<?php
use Kirby\Form\Options;
return [
'props' => [
/**
* API settings for options requests. This will only take affect when `options` is set to `api`.
*/
'api' => function ($api = null) {
return $api;
},
/**
* An array with options
*/
'options' => function ($options = []) {
return $options;
},
/**
* Query settings for options queries. This will only take affect when `options` is set to `query`.
*/
'query' => function ($query = null) {
return $query;
},
],
'computed' => [
'options' => function (): array {
return $this->getOptions();
}
],
'methods' => [
'getOptions' => function () {
return Options::factory(
$this->options(),
$this->props,
$this->model()
);
},
'sanitizeOption' => function ($option) {
$allowed = array_column($this->options(), 'value');
return in_array($option, $allowed, true) === true ? $option : null;
},
'sanitizeOptions' => function ($options) {
$allowed = array_column($this->options(), 'value');
return array_intersect($options, $allowed);
},
]
];

View file

@ -0,0 +1,14 @@
<?php
use Kirby\Cms\PagePicker;
return [
'methods' => [
'pagepicker' => function (array $params = []) {
// inject the current model
$params['model'] = $this->model();
return (new PagePicker($params))->toArray();
}
]
];

View file

@ -0,0 +1,78 @@
<?php
use Kirby\Toolkit\I18n;
return [
'props' => [
/**
* The placeholder text if none have been selected yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* Image settings for each item
*/
'image' => function ($image = null) {
return $image;
},
/**
* Info text for each item
*/
'info' => function (string $info = null) {
return $info;
},
/**
* Whether each item should be clickable
*/
'link' => function (bool $link = true) {
return $link;
},
/**
* The minimum number of required selected
*/
'min' => function (int $min = null) {
return $min;
},
/**
* The maximum number of allowed selected
*/
'max' => function (int $max = null) {
return $max;
},
/**
* If `false`, only a single one can be selected
*/
'multiple' => function (bool $multiple = true) {
return $multiple;
},
/**
* Query for the items to be included in the picker
*/
'query' => function (string $query = null) {
return $query;
},
/**
* Enable/disable the search field in the picker
*/
'search' => function (bool $search = true) {
return $search;
},
/**
* Main text for each item
*/
'text' => function (string $text = null) {
return $text;
},
],
];

View file

@ -0,0 +1,72 @@
<?php
use Kirby\Cms\Api;
use Kirby\Cms\File;
use Kirby\Exception\Exception;
return [
'props' => [
/**
* Sets the upload options for linked files (since 3.2.0)
*/
'uploads' => function ($uploads = []) {
if ($uploads === false) {
return false;
}
if (is_string($uploads) === true) {
$uploads = ['template' => $uploads];
}
if (is_array($uploads) === false) {
$uploads = [];
}
$template = $uploads['template'] ?? null;
if ($template) {
$file = new File([
'filename' => 'tmp',
'template' => $template
]);
$uploads['accept'] = $file->blueprint()->acceptMime();
} else {
$uploads['accept'] = '*';
}
return $uploads;
},
],
'methods' => [
'upload' => function (Api $api, $params, Closure $map) {
if ($params === false) {
throw new Exception('Uploads are disabled for this field');
}
if ($parentQuery = ($params['parent'] ?? null)) {
$parent = $this->model()->query($parentQuery);
} else {
$parent = $this->model();
}
if (is_a($parent, 'Kirby\Cms\File') === true) {
$parent = $parent->parent();
}
return $api->upload(function ($source, $filename) use ($parent, $params, $map) {
$file = $parent->createFile([
'source' => $source,
'template' => $params['template'] ?? null,
'filename' => $filename,
]);
if (is_a($file, 'Kirby\Cms\File') === false) {
throw new Exception('The file could not be uploaded');
}
return $map($file, $parent);
});
}
]
];

View file

@ -0,0 +1,13 @@
<?php
use Kirby\Cms\UserPicker;
return [
'methods' => [
'userpicker' => function (array $params = []) {
$params['model'] = $this->model();
return (new UserPicker($params))->toArray();
}
]
];

View file

@ -0,0 +1,32 @@
<?php
return [
'extends' => 'tags',
'props' => [
/**
* Unset inherited props
*/
'accept' => null,
/**
* Custom icon to replace the arrow down.
*/
'icon' => function (string $icon = null) {
return $icon;
},
/**
* Enable/disable the search in the dropdown
* Also limit displayed items (display: 20)
* and set minimum number of characters to search (min: 3)
*/
'search' => function ($search = true) {
return $search;
},
/**
* If `true`, selected entries will be sorted
* according to their position in the dropdown
*/
'sort' => function (bool $sort = false) {
return $sort;
},
]
];

View file

@ -0,0 +1,48 @@
<?php
use Kirby\Toolkit\Str;
return [
'props' => [
/**
* Default number that will be saved when a new page/user/file is created
*/
'default' => function ($default = null) {
return $this->toNumber($default);
},
/**
* The lowest allowed number
*/
'min' => function (float $min = null) {
return $min;
},
/**
* The highest allowed number
*/
'max' => function (float $max = null) {
return $max;
},
/**
* Allowed incremental steps between numbers (i.e `0.5`)
*/
'step' => function ($step = null) {
return $this->toNumber($step);
},
'value' => function ($value = null) {
return $this->toNumber($value);
}
],
'methods' => [
'toNumber' => function ($value) {
if ($this->isEmpty($value) === true) {
return null;
}
return is_float($value) === true ? $value : (float)Str::float($value);
}
],
'validations' => [
'min',
'max'
]
];

View file

@ -0,0 +1,117 @@
<?php
use Kirby\Data\Data;
use Kirby\Toolkit\A;
return [
'mixins' => ['min', 'pagepicker', 'picker'],
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'autofocus' => null,
'before' => null,
'icon' => null,
'placeholder' => null,
/**
* Default selected page(s) when a new page/file/user is created
*/
'default' => function ($default = null) {
return $this->toPages($default);
},
/**
* Changes the layout of the selected files. Available layouts: `list`, `cards`
*/
'layout' => function (string $layout = 'list') {
return $layout;
},
/**
* Optional query to select a specific set of pages
*/
'query' => function (string $query = null) {
return $query;
},
/**
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
*/
'size' => function (string $size = 'auto') {
return $size;
},
/**
* Optionally include subpages of pages
*/
'subpages' => function (bool $subpages = true) {
return $subpages;
},
'value' => function ($value = null) {
return $this->toPages($value);
},
],
'computed' => [
/**
* Unset inherited computed
*/
'default' => null
],
'methods' => [
'pageResponse' => function ($page) {
return $page->panelPickerData([
'image' => $this->image,
'info' => $this->info,
'text' => $this->text,
]);
},
'toPages' => function ($value = null) {
$pages = [];
$kirby = kirby();
foreach (Data::decode($value, 'yaml') as $id) {
if (is_array($id) === true) {
$id = $id['id'] ?? null;
}
if ($id !== null && ($page = $kirby->page($id))) {
$pages[] = $this->pageResponse($page);
}
}
return $pages;
}
],
'api' => function () {
return [
[
'pattern' => '/',
'action' => function () {
$field = $this->field();
return $field->pagepicker([
'image' => $field->image(),
'info' => $field->info(),
'limit' => $field->limit(),
'page' => $this->requestQuery('page'),
'parent' => $this->requestQuery('parent'),
'query' => $field->query(),
'search' => $this->requestQuery('search'),
'subpages' => $field->subpages(),
'text' => $field->text()
]);
}
]
];
},
'save' => function ($value = null) {
return A::pluck($value, 'id');
},
'validations' => [
'max',
'min'
]
];

View file

@ -0,0 +1,29 @@
<?php
return [
'mixins' => ['options'],
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'before' => null,
'icon' => null,
'placeholder' => null,
/**
* Arranges the radio buttons in the given number of columns
*/
'columns' => function (int $columns = 1) {
return $columns;
},
],
'computed' => [
'default' => function () {
return $this->sanitizeOption($this->default);
},
'value' => function () {
return $this->sanitizeOption($this->value) ?? '';
}
]
];

View file

@ -0,0 +1,24 @@
<?php
return [
'extends' => 'number',
'props' => [
/**
* Unset inherited props
*/
'placeholder' => null,
/**
* The maximum value on the slider
*/
'max' => function (float $max = 100) {
return $max;
},
/**
* Enables/disables the tooltip and set the before and after values
*/
'tooltip' => function ($tooltip = true) {
return $tooltip;
},
]
];

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