Update Composer packages
This commit is contained in:
parent
df93324906
commit
45bdef9a3b
378 changed files with 28466 additions and 28852 deletions
214
composer.lock
generated
214
composer.lock
generated
|
@ -8,21 +8,21 @@
|
|||
"packages": [
|
||||
{
|
||||
"name": "amteich/kirby-twig",
|
||||
"version": "4.1.6",
|
||||
"version": "4.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/amteich/kirby-twig.git",
|
||||
"reference": "d7f5535a24211702a76bde5c7f59aaf23904efab"
|
||||
"reference": "7cdc1e5d78a19e8e395c1d3516fe90bf512c20fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/amteich/kirby-twig/zipball/d7f5535a24211702a76bde5c7f59aaf23904efab",
|
||||
"reference": "d7f5535a24211702a76bde5c7f59aaf23904efab",
|
||||
"url": "https://api.github.com/repos/amteich/kirby-twig/zipball/7cdc1e5d78a19e8e395c1d3516fe90bf512c20fb",
|
||||
"reference": "7cdc1e5d78a19e8e395c1d3516fe90bf512c20fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"getkirby/composer-installer": "^1.1",
|
||||
"twig/twig": "^3.0"
|
||||
"twig/twig": "^3.4"
|
||||
},
|
||||
"type": "kirby-plugin",
|
||||
"autoload": {
|
||||
|
@ -47,9 +47,9 @@
|
|||
"description": "Twig templating support for Kirby CMS",
|
||||
"support": {
|
||||
"issues": "https://github.com/amteich/kirby-twig/issues",
|
||||
"source": "https://github.com/amteich/kirby-twig/tree/4.1.6"
|
||||
"source": "https://github.com/amteich/kirby-twig/tree/4.2.0"
|
||||
},
|
||||
"time": "2022-01-03T09:07:58+00:00"
|
||||
"time": "2022-12-09T21:39:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "claviska/simpleimage",
|
||||
|
@ -101,17 +101,98 @@
|
|||
"time": "2022-07-05T13:18:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.14.5",
|
||||
"name": "composer/semver",
|
||||
"version": "3.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc"
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/a63e5e8f26ebbebf8ed3c5c691637325512eb0dc",
|
||||
"reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
|
||||
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Semver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nils Adermann",
|
||||
"email": "naderman@naderman.de",
|
||||
"homepage": "http://www.naderman.de"
|
||||
},
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
},
|
||||
{
|
||||
"name": "Rob Bast",
|
||||
"email": "rob.bast@gmail.com",
|
||||
"homepage": "http://robbast.nl"
|
||||
}
|
||||
],
|
||||
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
||||
"keywords": [
|
||||
"semantic",
|
||||
"semver",
|
||||
"validation",
|
||||
"versioning"
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.org/composer",
|
||||
"issues": "https://github.com/composer/semver/issues",
|
||||
"source": "https://github.com/composer/semver/tree/3.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://packagist.com",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/composer",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-01T19:23:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.14.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "f7948baaa0330277c729714910336383286305da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/f7948baaa0330277c729714910336383286305da",
|
||||
"reference": "f7948baaa0330277c729714910336383286305da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -161,7 +242,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.14.5"
|
||||
"source": "https://github.com/filp/whoops/tree/2.14.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -169,24 +250,25 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-07T12:00:00+00:00"
|
||||
"time": "2022-11-02T16:23:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "getkirby/cms",
|
||||
"version": "3.7.5",
|
||||
"version": "3.8.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/getkirby/kirby.git",
|
||||
"reference": "021561f7444896fc9917eccb52768a6e715e9a74"
|
||||
"reference": "41719bd54310dfc2e321a75a8549da98ccf5cd1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/getkirby/kirby/zipball/021561f7444896fc9917eccb52768a6e715e9a74",
|
||||
"reference": "021561f7444896fc9917eccb52768a6e715e9a74",
|
||||
"url": "https://api.github.com/repos/getkirby/kirby/zipball/41719bd54310dfc2e321a75a8549da98ccf5cd1d",
|
||||
"reference": "41719bd54310dfc2e321a75a8549da98ccf5cd1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"claviska/simpleimage": "3.7.0",
|
||||
"composer/semver": "3.3.2",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
|
@ -198,12 +280,12 @@
|
|||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-simplexml": "*",
|
||||
"filp/whoops": "2.14.5",
|
||||
"filp/whoops": "2.14.6",
|
||||
"getkirby/composer-installer": "^1.2.1",
|
||||
"laminas/laminas-escaper": "2.10.0",
|
||||
"laminas/laminas-escaper": "2.12.0",
|
||||
"michelf/php-smartypants": "1.8.1",
|
||||
"php": ">=7.4.0 <8.2.0",
|
||||
"phpmailer/phpmailer": "6.6.4",
|
||||
"php": ">=8.0.0 <8.2.0",
|
||||
"phpmailer/phpmailer": "6.6.5",
|
||||
"symfony/polyfill-intl-idn": "1.26.0",
|
||||
"symfony/polyfill-mbstring": "1.26.0"
|
||||
},
|
||||
|
@ -268,7 +350,7 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-30T18:27:48+00:00"
|
||||
"time": "2022-12-06T14:31:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "getkirby/composer-installer",
|
||||
|
@ -356,32 +438,32 @@
|
|||
},
|
||||
{
|
||||
"name": "laminas/laminas-escaper",
|
||||
"version": "2.10.0",
|
||||
"version": "2.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-escaper.git",
|
||||
"reference": "58af67282db37d24e584a837a94ee55b9c7552be"
|
||||
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/58af67282db37d24e584a837a94ee55b9c7552be",
|
||||
"reference": "58af67282db37d24e584a837a94ee55b9c7552be",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
|
||||
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.4 || ~8.0.0 || ~8.1.0"
|
||||
"php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"zendframework/zend-escaper": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.26.6",
|
||||
"laminas/laminas-coding-standard": "~2.3.0",
|
||||
"laminas/laminas-coding-standard": "~2.4.0",
|
||||
"maglnet/composer-require-checker": "^3.8.0",
|
||||
"phpunit/phpunit": "^9.5.18",
|
||||
"psalm/plugin-phpunit": "^0.16.1",
|
||||
"psalm/plugin-phpunit": "^0.17.0",
|
||||
"vimeo/psalm": "^4.22.0"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -414,7 +496,7 @@
|
|||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-08T20:15:36+00:00"
|
||||
"time": "2022-10-10T10:11:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/color-extractor",
|
||||
|
@ -530,16 +612,16 @@
|
|||
},
|
||||
{
|
||||
"name": "mullema/k3-image-clip",
|
||||
"version": "3.1.0",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mullema/k3-image-clip.git",
|
||||
"reference": "c2e01f2ceb9eb5bc56895177359d398a3a2dbcf4"
|
||||
"reference": "66e5c2147fd6736f48878aaed6eef9ffe08cdd21"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mullema/k3-image-clip/zipball/c2e01f2ceb9eb5bc56895177359d398a3a2dbcf4",
|
||||
"reference": "c2e01f2ceb9eb5bc56895177359d398a3a2dbcf4",
|
||||
"url": "https://api.github.com/repos/mullema/k3-image-clip/zipball/66e5c2147fd6736f48878aaed6eef9ffe08cdd21",
|
||||
"reference": "66e5c2147fd6736f48878aaed6eef9ffe08cdd21",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -566,22 +648,22 @@
|
|||
"description": "Visual image clip for Kirby 3",
|
||||
"support": {
|
||||
"issues": "https://github.com/mullema/k3-image-clip/issues",
|
||||
"source": "https://github.com/mullema/k3-image-clip/tree/3.1.0"
|
||||
"source": "https://github.com/mullema/k3-image-clip/tree/3.2.0"
|
||||
},
|
||||
"time": "2022-06-26T08:59:46+00:00"
|
||||
"time": "2022-11-05T10:49:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v6.6.4",
|
||||
"version": "v6.6.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b"
|
||||
"reference": "8b6386d7417526d1ea4da9edb70b8352f7543627"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a94fdebaea6bd17f51be0c2373ab80d3d681269b",
|
||||
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/8b6386d7417526d1ea4da9edb70b8352f7543627",
|
||||
"reference": "8b6386d7417526d1ea4da9edb70b8352f7543627",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -605,8 +687,8 @@
|
|||
"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)"
|
||||
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
|
||||
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -638,7 +720,7 @@
|
|||
"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.6.4"
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -646,7 +728,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-22T09:22:00+00:00"
|
||||
"time": "2022-10-07T12:23:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
|
@ -738,16 +820,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -762,7 +844,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -800,7 +882,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -816,7 +898,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
|
@ -907,16 +989,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -928,7 +1010,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -971,7 +1053,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -987,7 +1069,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
|
@ -1074,16 +1156,16 @@
|
|||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.4.2",
|
||||
"version": "v3.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077"
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077",
|
||||
"reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1134,7 +1216,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.2"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1146,7 +1228,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-12T06:47:24+00:00"
|
||||
"time": "2022-09-28T08:42:51+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* stop at older or too recent versions
|
||||
*/
|
||||
if (
|
||||
version_compare(PHP_VERSION, '7.4.0', '>=') === false ||
|
||||
version_compare(PHP_VERSION, '8.0.0', '>=') === false ||
|
||||
version_compare(PHP_VERSION, '8.2.0', '<') === false
|
||||
) {
|
||||
die(include __DIR__ . '/views/php.php');
|
||||
|
@ -16,11 +16,15 @@ 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
|
||||
*
|
||||
* @psalm-suppress MissingFile
|
||||
*/
|
||||
include $autoloader;
|
||||
} elseif (is_file($autoloader = __DIR__ . '/vendor/autoload.php')) {
|
||||
/**
|
||||
* Fall back to the local autoloader if that exists
|
||||
*
|
||||
* @psalm-suppress MissingFile
|
||||
*/
|
||||
include $autoloader;
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
##
|
||||
## Bundle of CA Root Certificates
|
||||
##
|
||||
## Certificate data from Mozilla as of: Tue Jul 19 03:12:06 2022 GMT
|
||||
## Certificate data from Mozilla as of: Tue Oct 11 03:12:05 2022 GMT
|
||||
##
|
||||
## This is a bundle of X.509 certificates of public Certificate Authorities
|
||||
## (CA). These were automatically extracted from Mozilla's root certificates
|
||||
|
@ -14,7 +14,7 @@
|
|||
## Just configure this file as the SSLCACertificateFile.
|
||||
##
|
||||
## Conversion done with mk-ca-bundle.pl version 1.29.
|
||||
## SHA256: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066
|
||||
## SHA256: 3ff8bd209b5f2e739b9f2b96eacb694a774114685b02978257824f37ff528f71
|
||||
##
|
||||
|
||||
|
||||
|
@ -3458,3 +3458,49 @@ zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
|
|||
PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
|
||||
Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Security Communication RootCA3
|
||||
==============================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
|
||||
IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
|
||||
b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
|
||||
CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
|
||||
AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
|
||||
MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
|
||||
hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
|
||||
NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
|
||||
/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
|
||||
npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
|
||||
XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
|
||||
p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
|
||||
3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
|
||||
GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
|
||||
CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
|
||||
/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
|
||||
YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
|
||||
Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
|
||||
H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
|
||||
YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
|
||||
XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
|
||||
+LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
|
||||
KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
|
||||
dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
|
||||
6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Security Communication ECC RootCA1
|
||||
==================================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
|
||||
VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
|
||||
dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
|
||||
MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
|
||||
BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
|
||||
IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
|
||||
5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
|
||||
BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
|
||||
BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
|
||||
snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
|
||||
N9k=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"description": "The Kirby 3 core",
|
||||
"license": "proprietary",
|
||||
"type": "kirby-cms",
|
||||
"version": "3.7.5",
|
||||
"version": "3.8.3",
|
||||
"keywords": [
|
||||
"kirby",
|
||||
"cms",
|
||||
|
@ -24,7 +24,7 @@
|
|||
"source": "https://github.com/getkirby/kirby"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0 <8.2.0",
|
||||
"php": ">=8.0.0 <8.2.0",
|
||||
"ext-SimpleXML": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
|
@ -37,11 +37,12 @@
|
|||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"claviska/simpleimage": "3.7.0",
|
||||
"filp/whoops": "2.14.5",
|
||||
"composer/semver": "3.3.2",
|
||||
"filp/whoops": "2.14.6",
|
||||
"getkirby/composer-installer": "^1.2.1",
|
||||
"laminas/laminas-escaper": "2.10.0",
|
||||
"laminas/laminas-escaper": "2.12.0",
|
||||
"michelf/php-smartypants": "1.8.1",
|
||||
"phpmailer/phpmailer": "6.6.4",
|
||||
"phpmailer/phpmailer": "6.6.5",
|
||||
"symfony/polyfill-intl-idn": "1.26.0",
|
||||
"symfony/polyfill-mbstring": "1.26.0"
|
||||
},
|
||||
|
@ -76,7 +77,7 @@
|
|||
},
|
||||
"optimize-autoloader": true,
|
||||
"platform": {
|
||||
"php": "7.4.0"
|
||||
"php": "8.0.0"
|
||||
},
|
||||
"platform-check": false
|
||||
},
|
||||
|
|
167
kirby/composer.lock
generated
167
kirby/composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "fb087946fb5ac5910e25a4d263905d99",
|
||||
"content-hash": "a2b48616382734757b5cf4a9bd73ccdb",
|
||||
"packages": [
|
||||
{
|
||||
"name": "claviska/simpleimage",
|
||||
|
@ -56,17 +56,98 @@
|
|||
"time": "2022-07-05T13:18:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.14.5",
|
||||
"name": "composer/semver",
|
||||
"version": "3.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc"
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/a63e5e8f26ebbebf8ed3c5c691637325512eb0dc",
|
||||
"reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
|
||||
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Semver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nils Adermann",
|
||||
"email": "naderman@naderman.de",
|
||||
"homepage": "http://www.naderman.de"
|
||||
},
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
},
|
||||
{
|
||||
"name": "Rob Bast",
|
||||
"email": "rob.bast@gmail.com",
|
||||
"homepage": "http://robbast.nl"
|
||||
}
|
||||
],
|
||||
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
||||
"keywords": [
|
||||
"semantic",
|
||||
"semver",
|
||||
"validation",
|
||||
"versioning"
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.org/composer",
|
||||
"issues": "https://github.com/composer/semver/issues",
|
||||
"source": "https://github.com/composer/semver/tree/3.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://packagist.com",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/composer",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-01T19:23:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.14.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "f7948baaa0330277c729714910336383286305da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/f7948baaa0330277c729714910336383286305da",
|
||||
"reference": "f7948baaa0330277c729714910336383286305da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -116,7 +197,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.14.5"
|
||||
"source": "https://github.com/filp/whoops/tree/2.14.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -124,7 +205,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-07T12:00:00+00:00"
|
||||
"time": "2022-11-02T16:23:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "getkirby/composer-installer",
|
||||
|
@ -175,32 +256,32 @@
|
|||
},
|
||||
{
|
||||
"name": "laminas/laminas-escaper",
|
||||
"version": "2.10.0",
|
||||
"version": "2.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-escaper.git",
|
||||
"reference": "58af67282db37d24e584a837a94ee55b9c7552be"
|
||||
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/58af67282db37d24e584a837a94ee55b9c7552be",
|
||||
"reference": "58af67282db37d24e584a837a94ee55b9c7552be",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
|
||||
"reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.4 || ~8.0.0 || ~8.1.0"
|
||||
"php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"zendframework/zend-escaper": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.26.6",
|
||||
"laminas/laminas-coding-standard": "~2.3.0",
|
||||
"laminas/laminas-coding-standard": "~2.4.0",
|
||||
"maglnet/composer-require-checker": "^3.8.0",
|
||||
"phpunit/phpunit": "^9.5.18",
|
||||
"psalm/plugin-phpunit": "^0.16.1",
|
||||
"psalm/plugin-phpunit": "^0.17.0",
|
||||
"vimeo/psalm": "^4.22.0"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -233,7 +314,7 @@
|
|||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-08T20:15:36+00:00"
|
||||
"time": "2022-10-10T10:11:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/color-extractor",
|
||||
|
@ -349,16 +430,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v6.6.4",
|
||||
"version": "v6.6.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b"
|
||||
"reference": "8b6386d7417526d1ea4da9edb70b8352f7543627"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a94fdebaea6bd17f51be0c2373ab80d3d681269b",
|
||||
"reference": "a94fdebaea6bd17f51be0c2373ab80d3d681269b",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/8b6386d7417526d1ea4da9edb70b8352f7543627",
|
||||
"reference": "8b6386d7417526d1ea4da9edb70b8352f7543627",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -382,8 +463,8 @@
|
|||
"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)"
|
||||
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
|
||||
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -415,7 +496,7 @@
|
|||
"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.6.4"
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.6.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -423,34 +504,34 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-22T09:22:00+00:00"
|
||||
"time": "2022-10-07T12:23:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
"Psr\\Log\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -471,9 +552,9 @@
|
|||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
||||
"source": "https://github.com/php-fig/log/tree/3.0.0"
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
"time": "2021-07-14T16:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
|
@ -564,16 +645,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -585,7 +666,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -628,7 +709,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -644,7 +725,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
|
@ -737,7 +818,7 @@
|
|||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.4.0 <8.2.0",
|
||||
"php": ">=8.0.0 <8.2.0",
|
||||
"ext-simplexml": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
|
@ -752,7 +833,7 @@
|
|||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.4.0"
|
||||
"php": "8.0.0"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ return [
|
|||
'cookie' => 'Kirby\Http\Cookie',
|
||||
'header' => 'Kirby\Http\Header',
|
||||
'remote' => 'Kirby\Http\Remote',
|
||||
'server' => 'Kirby\Http\Server',
|
||||
|
||||
// image classes
|
||||
'dimensions' => 'Kirby\Image\Dimensions',
|
||||
|
|
|
@ -57,6 +57,7 @@ return [
|
|||
},
|
||||
'type' => fn (File $file) => $file->type(),
|
||||
'url' => fn (File $file) => $file->url(),
|
||||
'uuid' => fn (File $file) => $file->uuid()?->toString()
|
||||
],
|
||||
'type' => 'Kirby\Cms\File',
|
||||
'views' => [
|
||||
|
@ -79,7 +80,8 @@ return [
|
|||
'size',
|
||||
'template',
|
||||
'type',
|
||||
'url'
|
||||
'url',
|
||||
'uuid'
|
||||
],
|
||||
'compact' => [
|
||||
'filename',
|
||||
|
@ -87,6 +89,7 @@ return [
|
|||
'link',
|
||||
'type',
|
||||
'url',
|
||||
'uuid'
|
||||
],
|
||||
'panel' => [
|
||||
'blueprint',
|
||||
|
@ -109,7 +112,8 @@ return [
|
|||
'prevWithTemplate' => 'compact',
|
||||
'template',
|
||||
'type',
|
||||
'url'
|
||||
'url',
|
||||
'uuid'
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Helpers;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
|
@ -21,54 +20,25 @@ return [
|
|||
'hasFiles' => fn (Page $page) => $page->hasFiles(),
|
||||
'id' => fn (Page $page) => $page->id(),
|
||||
'isSortable' => fn (Page $page) => $page->isSortable(),
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Remove in 3.8.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
'next' => function (Page $page) {
|
||||
Helpers::deprecated('The API field page.next has been deprecated and will be removed in 3.8.0.');
|
||||
|
||||
return $page
|
||||
->nextAll()
|
||||
->filter('intendedTemplate', $page->intendedTemplate())
|
||||
->filter('status', $page->status())
|
||||
->filter('isReadable', true)
|
||||
->first();
|
||||
},
|
||||
'num' => fn (Page $page) => $page->num(),
|
||||
'options' => fn (Page $page) => $page->panel()->options(['preview']),
|
||||
'panelImage' => fn (Page $page) => $page->panel()->image(),
|
||||
'parent' => fn (Page $page) => $page->parent(),
|
||||
'parents' => fn (Page $page) => $page->parents()->flip(),
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Remove in 3.8.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
'prev' => function (Page $page) {
|
||||
Helpers::deprecated('The API field page.prev has been deprecated and will be removed in 3.8.0.');
|
||||
|
||||
return $page
|
||||
->prevAll()
|
||||
->filter('intendedTemplate', $page->intendedTemplate())
|
||||
->filter('status', $page->status())
|
||||
->filter('isReadable', true)
|
||||
->last();
|
||||
},
|
||||
'previewUrl' => fn (Page $page) => $page->previewUrl(),
|
||||
'siblings' => function (Page $page) {
|
||||
'num' => fn (Page $page) => $page->num(),
|
||||
'options' => fn (Page $page) => $page->panel()->options(['preview']),
|
||||
'panelImage' => fn (Page $page) => $page->panel()->image(),
|
||||
'parent' => fn (Page $page) => $page->parent(),
|
||||
'parents' => fn (Page $page) => $page->parents()->flip(),
|
||||
'previewUrl' => fn (Page $page) => $page->previewUrl(),
|
||||
'siblings' => function (Page $page) {
|
||||
if ($page->isDraft() === true) {
|
||||
return $page->parentModel()->children()->not($page);
|
||||
} else {
|
||||
return $page->siblings();
|
||||
}
|
||||
|
||||
return $page->siblings();
|
||||
},
|
||||
'slug' => fn (Page $page) => $page->slug(),
|
||||
'status' => fn (Page $page) => $page->status(),
|
||||
'template' => fn (Page $page) => $page->intendedTemplate()->name(),
|
||||
'title' => fn (Page $page) => $page->title()->value(),
|
||||
'url' => fn (Page $page) => $page->url(),
|
||||
'uuid' => fn (Page $page) => $page->uuid()?->toString()
|
||||
],
|
||||
'type' => 'Kirby\Cms\Page',
|
||||
'views' => [
|
||||
|
@ -76,7 +46,8 @@ return [
|
|||
'id',
|
||||
'title',
|
||||
'url',
|
||||
'num'
|
||||
'num',
|
||||
'uuid'
|
||||
],
|
||||
'default' => [
|
||||
'content',
|
||||
|
@ -88,7 +59,8 @@ return [
|
|||
'slug',
|
||||
'template',
|
||||
'title',
|
||||
'url'
|
||||
'url',
|
||||
'uuid'
|
||||
],
|
||||
'panel' => [
|
||||
'id',
|
||||
|
@ -102,7 +74,8 @@ return [
|
|||
'previewUrl',
|
||||
'slug',
|
||||
'title',
|
||||
'url'
|
||||
'url',
|
||||
'uuid'
|
||||
],
|
||||
'selector' => [
|
||||
'id',
|
||||
|
|
|
@ -32,28 +32,20 @@ return [
|
|||
'slugs' => fn () => Str::$language,
|
||||
'title' => fn () => $this->site()->title()->value(),
|
||||
'translation' => function () {
|
||||
if ($user = $this->user()) {
|
||||
$translationCode = $user->language();
|
||||
} else {
|
||||
$translationCode = $this->kirby()->panelLanguage();
|
||||
}
|
||||
$code = $this->user()?->language() ??
|
||||
$this->kirby()->panelLanguage();
|
||||
|
||||
if ($translation = $this->kirby()->translation($translationCode)) {
|
||||
return $translation;
|
||||
} else {
|
||||
return $this->kirby()->translation('en');
|
||||
}
|
||||
return $this->kirby()->translation($code) ??
|
||||
$this->kirby()->translation('en');
|
||||
},
|
||||
'kirbytext' => fn () => $this->kirby()->option('panel.kirbytext') ?? true,
|
||||
'user' => fn () => $this->user(),
|
||||
'version' => function () {
|
||||
$user = $this->user();
|
||||
|
||||
if ($user && $user->role()->permissions()->for('access', 'system') === true) {
|
||||
if ($this->user()?->role()->permissions()->for('access', 'system') === true) {
|
||||
return $this->kirby()->version();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
],
|
||||
'type' => 'Kirby\Cms\System',
|
||||
|
|
|
@ -24,7 +24,8 @@ return [
|
|||
'prev' => fn (User $user) => $user->prev(),
|
||||
'role' => fn (User $user) => $user->role(),
|
||||
'roles' => fn (User $user) => $user->roles(),
|
||||
'username' => fn (User $user) => $user->username()
|
||||
'username' => fn (User $user) => $user->username(),
|
||||
'uuid' => fn (User $user) => $user->uuid()?->toString()
|
||||
],
|
||||
'type' => 'Kirby\Cms\User',
|
||||
'views' => [
|
||||
|
@ -39,7 +40,8 @@ return [
|
|||
'options',
|
||||
'prev' => 'compact',
|
||||
'role',
|
||||
'username'
|
||||
'username',
|
||||
'uuid'
|
||||
],
|
||||
'compact' => [
|
||||
'avatar' => 'compact',
|
||||
|
@ -48,7 +50,8 @@ return [
|
|||
'language',
|
||||
'name',
|
||||
'role' => 'compact',
|
||||
'username'
|
||||
'username',
|
||||
'uuid'
|
||||
],
|
||||
'auth' => [
|
||||
'avatar' => 'compact',
|
||||
|
@ -72,6 +75,7 @@ return [
|
|||
'prev' => ['id', 'name'],
|
||||
'role',
|
||||
'username',
|
||||
'uuid'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
|
|
@ -70,13 +70,11 @@ return [
|
|||
$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');
|
||||
}
|
||||
$mode = match (true) {
|
||||
isset($methods['code']) => 'login',
|
||||
isset($methods['password-reset']) => 'password-reset',
|
||||
default => throw new InvalidArgumentException('Login without password is not enabled')
|
||||
};
|
||||
|
||||
$status = $auth->createChallenge($email, $long, $mode);
|
||||
}
|
||||
|
@ -87,13 +85,13 @@ return [
|
|||
'status' => 'ok',
|
||||
'user' => $this->resolve($user)->view('auth')->toArray()
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'code' => 200,
|
||||
'status' => 'ok',
|
||||
'challenge' => $status->challenge()
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'code' => 200,
|
||||
'status' => 'ok',
|
||||
'challenge' => $status->challenge()
|
||||
];
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -105,4 +103,14 @@ return [
|
|||
return true;
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'auth/ping',
|
||||
'method' => 'POST',
|
||||
'auth' => false,
|
||||
'action' => function () {
|
||||
// refresh the session timeout
|
||||
$this->kirby()->session();
|
||||
return true;
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
|
@ -12,9 +12,7 @@ return [
|
|||
'pattern' => $pattern . '/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();
|
||||
}
|
||||
return $this->file($path, $filename)->blueprint()->section($sectionName)?->toResponse();
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -60,9 +58,9 @@ return [
|
|||
|
||||
if ($this->requestMethod() === 'GET') {
|
||||
return $files->search($this->requestQuery('q'));
|
||||
} else {
|
||||
return $files->query($this->requestBody());
|
||||
}
|
||||
|
||||
return $files->query($this->requestBody());
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -86,16 +84,20 @@ return [
|
|||
'pattern' => $pattern . '/files/(:any)',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->file($path, $filename)->update($this->requestBody(), $this->language(), true);
|
||||
return $this->file($path, $filename)->update(
|
||||
$this->requestBody(),
|
||||
$this->language(),
|
||||
true
|
||||
);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => $pattern . '/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);
|
||||
});
|
||||
return $this->upload(
|
||||
fn ($source) => $this->file($path, $filename)->replace($source)
|
||||
);
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -124,9 +126,9 @@ return [
|
|||
|
||||
if ($this->requestMethod() === 'GET') {
|
||||
return $files->search($this->requestQuery('q'));
|
||||
} else {
|
||||
return $files->query($this->requestBody());
|
||||
}
|
||||
|
||||
return $files->query($this->requestBody());
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
|
@ -29,18 +29,14 @@ return [
|
|||
'pattern' => 'languages/(:any)',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $code) {
|
||||
if ($language = $this->kirby()->languages()->find($code)) {
|
||||
return $language->update($this->requestBody());
|
||||
}
|
||||
return $this->kirby()->languages()->find($code)?->update($this->requestBody());
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'languages/(:any)',
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $code) {
|
||||
if ($language = $this->kirby()->languages()->find($code)) {
|
||||
return $language->delete();
|
||||
}
|
||||
return $this->kirby()->languages()->find($code)?->delete();
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
@ -5,40 +5,41 @@
|
|||
* Content Lock Routes
|
||||
*/
|
||||
return [
|
||||
[
|
||||
'pattern' => '(:all)/lock',
|
||||
'method' => 'GET',
|
||||
'action' => function (string $path) {
|
||||
return [
|
||||
'lock' => $this->parent($path)->lock()?->toArray() ?? false
|
||||
];
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/lock',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path) {
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->create();
|
||||
}
|
||||
return $this->parent($path)->lock()?->create();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/lock',
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $path) {
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->remove();
|
||||
}
|
||||
return $this->parent($path)->lock()?->remove();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/unlock',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path) {
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->unlock();
|
||||
}
|
||||
return $this->parent($path)->lock()?->unlock();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/unlock',
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $path) {
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->resolve();
|
||||
}
|
||||
return $this->parent($path)->lock()?->resolve();
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
|
@ -104,9 +104,7 @@ return [
|
|||
'pattern' => 'pages/(:any)/sections/(:any)',
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id, string $sectionName) {
|
||||
if ($section = $this->page($id)->blueprint()->section($sectionName)) {
|
||||
return $section->toResponse();
|
||||
}
|
||||
return $this->page($id)->blueprint()->section($sectionName)?->toResponse();
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -10,14 +10,11 @@ return [
|
|||
'action' => function () {
|
||||
$kirby = $this->kirby();
|
||||
|
||||
switch ($kirby->request()->get('canBe')) {
|
||||
case 'changed':
|
||||
return $kirby->roles()->canBeChanged();
|
||||
case 'created':
|
||||
return $kirby->roles()->canBeCreated();
|
||||
default:
|
||||
return $kirby->roles();
|
||||
}
|
||||
return match ($kirby->request()->get('canBe')) {
|
||||
'changed' => $kirby->roles()->canBeChanged(),
|
||||
'created' => $kirby->roles()->canBeCreated(),
|
||||
default => $kirby->roles()
|
||||
};
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -79,18 +79,16 @@ return [
|
|||
|
||||
if ($this->requestMethod() === 'GET') {
|
||||
return $pages->search($this->requestQuery('q'));
|
||||
} else {
|
||||
return $pages->query($this->requestBody());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
return $this->site()->blueprint()->section($sectionName)?->toResponse();
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -17,19 +17,18 @@ return [
|
|||
|
||||
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'
|
||||
];
|
||||
}
|
||||
|
||||
$info = match ($system->isOk()) {
|
||||
true => $this->resolve($system)->view('login')->toArray(),
|
||||
false => $this->resolve($system)->view('troubleshooting')->toArray()
|
||||
};
|
||||
|
||||
return [
|
||||
'status' => 'ok',
|
||||
'data' => $info,
|
||||
'type' => 'model'
|
||||
];
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -26,9 +26,9 @@ return [
|
|||
'action' => function () {
|
||||
if ($this->requestMethod() === 'GET') {
|
||||
return $this->users()->search($this->requestQuery('q'));
|
||||
} else {
|
||||
return $this->users()->query($this->requestBody());
|
||||
}
|
||||
|
||||
return $this->users()->query($this->requestBody());
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -79,17 +79,16 @@ return [
|
|||
],
|
||||
'method' => 'POST',
|
||||
'action' => function (string $id) {
|
||||
if ($avatar = $this->user($id)->avatar()) {
|
||||
$avatar->delete();
|
||||
}
|
||||
$this->user($id)->avatar()?->delete();
|
||||
|
||||
return $this->upload(function ($source, $filename) use ($id) {
|
||||
return $this->user($id)->createFile([
|
||||
return $this->upload(
|
||||
fn ($source, $filename) => $this->user($id)->createFile([
|
||||
'filename' => 'profile.' . F::extension($filename),
|
||||
'template' => 'avatar',
|
||||
'source' => $source
|
||||
]);
|
||||
}, $single = true);
|
||||
]),
|
||||
single: true
|
||||
);
|
||||
}
|
||||
],
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
|
|
@ -1,48 +1,92 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
'system' => [
|
||||
'pattern' => 'system',
|
||||
'action' => function () {
|
||||
$kirby = App::instance();
|
||||
$system = $kirby->system();
|
||||
$license = $system->license();
|
||||
$kirby = App::instance();
|
||||
$system = $kirby->system();
|
||||
$updateStatus = $system->updateStatus();
|
||||
$license = $system->license();
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($license === true) {
|
||||
// valid license, but user is not admin
|
||||
$license = 'Kirby 3';
|
||||
} elseif ($license === false) {
|
||||
// no valid license
|
||||
$license = null;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
$environment = [
|
||||
[
|
||||
'label' => $license ? I18n::translate('license') : I18n::translate('license.register.label'),
|
||||
'value' => $license ? 'Kirby 3' : I18n::translate('license.unregistered.label'),
|
||||
'theme' => $license ? null : 'negative',
|
||||
'dialog' => $license ? 'license' : 'registration'
|
||||
],
|
||||
[
|
||||
'label' => $updateStatus?->label() ?? I18n::translate('version'),
|
||||
'value' => $kirby->version(),
|
||||
'link' => (
|
||||
$updateStatus ?
|
||||
$updateStatus->url() :
|
||||
'https://github.com/getkirby/kirby/releases/tag/' . $kirby->version()
|
||||
),
|
||||
'theme' => $updateStatus?->theme()
|
||||
],
|
||||
[
|
||||
'label' => 'PHP',
|
||||
'value' => phpversion()
|
||||
],
|
||||
[
|
||||
'label' => I18n::translate('server'),
|
||||
'value' => $system->serverSoftware() ?? '?'
|
||||
]
|
||||
];
|
||||
|
||||
$exceptions = $updateStatus?->exceptionMessages() ?? [];
|
||||
|
||||
$plugins = $system->plugins()->values(function ($plugin) use (&$exceptions) {
|
||||
$authors = $plugin->authorsNames();
|
||||
$updateStatus = $plugin->updateStatus();
|
||||
$version = $updateStatus?->toArray() ?? $plugin->version() ?? '–';
|
||||
|
||||
if ($updateStatus !== null) {
|
||||
$exceptions = array_merge($exceptions, $updateStatus->exceptionMessages());
|
||||
}
|
||||
|
||||
$plugins = $system->plugins()->values(function ($plugin) {
|
||||
return [
|
||||
'author' => $plugin->authorsNames(),
|
||||
'license' => $plugin->license(),
|
||||
'author' => empty($authors) ? '–' : $authors,
|
||||
'license' => $plugin->license() ?? '–',
|
||||
'name' => [
|
||||
'text' => $plugin->name(),
|
||||
'text' => $plugin->name() ?? '–',
|
||||
'href' => $plugin->link(),
|
||||
],
|
||||
'version' => $plugin->version(),
|
||||
'version' => $version,
|
||||
];
|
||||
});
|
||||
|
||||
$security = $updateStatus?->messages() ?? [];
|
||||
|
||||
if ($kirby->option('debug', false) === true) {
|
||||
$security[] = [
|
||||
'id' => 'debug',
|
||||
'text' => I18n::translate('system.issues.debug'),
|
||||
'link' => 'https://getkirby.com/security/debug'
|
||||
];
|
||||
}
|
||||
|
||||
if ($kirby->environment()->https() !== true) {
|
||||
$security[] = [
|
||||
'id' => 'https',
|
||||
'text' => I18n::translate('system.issues.https'),
|
||||
'link' => 'https://getkirby.com/security/https'
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-system-view',
|
||||
'props' => [
|
||||
'debug' => $kirby->option('debug', false),
|
||||
'license' => $license,
|
||||
'plugins' => $plugins,
|
||||
'php' => phpversion(),
|
||||
'server' => $system->serverSoftware(),
|
||||
'https' => $kirby->environment()->https(),
|
||||
'version' => $kirby->version(),
|
||||
'urls' => [
|
||||
'environment' => $environment,
|
||||
'exceptions' => $kirby->option('debug') === true ? $exceptions : [],
|
||||
'plugins' => $plugins,
|
||||
'security' => $security,
|
||||
'urls' => [
|
||||
'content' => $system->exposedFileUrl('content'),
|
||||
'git' => $system->exposedFileUrl('git'),
|
||||
'kirby' => $system->exposedFileUrl('kirby'),
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<?php /** @var \Kirby\Cms\Block $block */ ?>
|
||||
<figure>
|
||||
<?php
|
||||
/** @var \Kirby\Cms\Block $block */
|
||||
$caption = $block->caption();
|
||||
$crop = $block->crop()->isTrue();
|
||||
$ratio = $block->ratio()->or('auto');
|
||||
?>
|
||||
<figure<?= Html::attr(['data-ratio' => $ratio, 'data-crop' => $crop], null, ' ') ?>>
|
||||
<ul>
|
||||
<?php foreach ($block->images()->toFiles() as $image): ?>
|
||||
<li>
|
||||
|
@ -7,4 +12,9 @@
|
|||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php if ($caption->isNotEmpty()): ?>
|
||||
<figcaption>
|
||||
<?= $caption ?>
|
||||
</figcaption>
|
||||
<?php endif ?>
|
||||
</figure>
|
||||
|
|
|
@ -14,3 +14,27 @@ fields:
|
|||
template: blocks/image
|
||||
image:
|
||||
ratio: 1/1
|
||||
caption:
|
||||
label: field.blocks.image.caption
|
||||
type: writer
|
||||
icon: text
|
||||
inline: true
|
||||
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
|
||||
|
|
|
@ -4,8 +4,9 @@ use Kirby\Cms\App;
|
|||
use Kirby\Cms\Collection;
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Cms\FileVersion;
|
||||
use Kirby\Cms\Helpers;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Cms\Template;
|
||||
use Kirby\Cms\User;
|
||||
use Kirby\Data\Data;
|
||||
use Kirby\Email\PHPMailer as Emailer;
|
||||
use Kirby\Filesystem\F;
|
||||
|
@ -30,33 +31,6 @@ return [
|
|||
*/
|
||||
'css' => fn (App $kirby, string $url, $options = null): string => $url,
|
||||
|
||||
|
||||
/**
|
||||
* Object and variable dumper
|
||||
* to help with debugging.
|
||||
*
|
||||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param mixed $variable
|
||||
* @param bool $echo
|
||||
* @return string
|
||||
*
|
||||
* @deprecated 3.7.0 Disable `dump()` via `KIRBY_HELPER_DUMP` instead and create your own function
|
||||
* @todo move to `Helpers::dump()`, remove component in 3.8.0
|
||||
*/
|
||||
'dump' => function (App $kirby, $variable, bool $echo = true) {
|
||||
if ($kirby->environment()->cli() === true) {
|
||||
$output = print_r($variable, true) . PHP_EOL;
|
||||
} else {
|
||||
$output = '<pre>' . print_r($variable, true) . '</pre>';
|
||||
}
|
||||
|
||||
if ($echo === true) {
|
||||
echo $output;
|
||||
}
|
||||
|
||||
return $output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add your own email provider
|
||||
*
|
||||
|
@ -108,7 +82,7 @@ return [
|
|||
Data::write($job, array_merge($options, [
|
||||
'filename' => $file->filename()
|
||||
]));
|
||||
} catch (Throwable $e) {
|
||||
} catch (Throwable) {
|
||||
// if thumb doesn't exist yet and job file cannot
|
||||
// be created, return
|
||||
return $file;
|
||||
|
@ -138,24 +112,16 @@ return [
|
|||
* @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 (deprecated: set via $options['inline'] instead)
|
||||
* @return string
|
||||
* @todo remove $inline parameter in in 3.8.0
|
||||
*/
|
||||
'markdown' => function (App $kirby, string $text = null, array $options = [], bool $inline = false): string {
|
||||
'markdown' => function (
|
||||
App $kirby,
|
||||
string $text = null,
|
||||
array $options = []
|
||||
): string {
|
||||
static $markdown;
|
||||
static $config;
|
||||
|
||||
// warning for deprecated fourth parameter
|
||||
if (func_num_args() === 4 && isset($options['inline']) === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
Helpers::deprecated('markdown component: the $inline parameter is deprecated and will be removed in Kirby 3.8.0. Use $options[\'inline\'] instead.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// support for the deprecated fourth argument
|
||||
$options['inline'] ??= $inline;
|
||||
|
||||
// if the config options have changed or the component is called for the first time,
|
||||
// (re-)initialize the parser object
|
||||
if ($config !== $options) {
|
||||
|
@ -206,17 +172,22 @@ return [
|
|||
return $options['words'] ? '\b' . preg_quote($value) . '\b' : preg_quote($value);
|
||||
}, $searchWords);
|
||||
|
||||
// returns an empty collection if there is no search word
|
||||
if (empty($searchWords) === true) {
|
||||
return $collection->limit(0);
|
||||
}
|
||||
|
||||
$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) {
|
||||
if ($item instanceof User) {
|
||||
$keys[] = 'name';
|
||||
$keys[] = 'email';
|
||||
$keys[] = 'role';
|
||||
} elseif (is_a($item, 'Kirby\Cms\Page') === true) {
|
||||
} elseif ($item instanceof Page) {
|
||||
// apply the default score for pages
|
||||
$options['score'] = array_merge([
|
||||
'id' => 64,
|
||||
|
@ -295,9 +266,8 @@ return [
|
|||
* @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 {
|
||||
'snippet' => function (App $kirby, $name, array $data = []): string {
|
||||
$snippets = A::wrap($name);
|
||||
|
||||
foreach ($snippets as $name) {
|
||||
|
|
|
@ -46,13 +46,13 @@ return [
|
|||
/**
|
||||
* Latest date, which can be selected/saved (Y-m-d)
|
||||
*/
|
||||
'max' => function (string $max = null): ?string {
|
||||
'max' => function (string $max = null): string|null {
|
||||
return Date::optional($max);
|
||||
},
|
||||
/**
|
||||
* Earliest date, which can be selected/saved (Y-m-d)
|
||||
*/
|
||||
'min' => function (string $min = null): ?string {
|
||||
'min' => function (string $min = null): string|null {
|
||||
return Date::optional($min);
|
||||
},
|
||||
|
||||
|
|
|
@ -34,7 +34,10 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'parentModel' => function () {
|
||||
if (is_string($this->parent) === true && $model = $this->model()->query($this->parent, 'Kirby\Cms\Model')) {
|
||||
if (
|
||||
is_string($this->parent) === true &&
|
||||
$model = $this->model()->query($this->parent, 'Kirby\Cms\Model')
|
||||
) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
@ -68,10 +71,13 @@ return [
|
|||
|
||||
foreach (Data::decode($value, 'yaml') as $id) {
|
||||
if (is_array($id) === true) {
|
||||
$id = $id['id'] ?? null;
|
||||
$id = $id['uuid'] ?? $id['id'] ?? null;
|
||||
}
|
||||
|
||||
if ($id !== null && ($file = $this->kirby()->file($id, $this->model()))) {
|
||||
if (
|
||||
$id !== null &&
|
||||
($file = $this->kirby()->file($id, $this->model()))
|
||||
) {
|
||||
$files[] = $this->fileResponse($file);
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +128,7 @@ return [
|
|||
];
|
||||
},
|
||||
'save' => function ($value = null) {
|
||||
return A::pluck($value, 'uuid');
|
||||
return A::pluck($value, $this->store);
|
||||
},
|
||||
'validations' => [
|
||||
'max',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Form\Options;
|
||||
use Kirby\Field\FieldOptions;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
|
@ -30,19 +30,18 @@ return [
|
|||
],
|
||||
'methods' => [
|
||||
'getOptions' => function () {
|
||||
return Options::factory(
|
||||
$this->options(),
|
||||
$this->props,
|
||||
$this->model()
|
||||
);
|
||||
$props = FieldOptions::polyfill($this->props);
|
||||
$options = FieldOptions::factory($props['options']);
|
||||
return $options->render($this->model());
|
||||
},
|
||||
'sanitizeOption' => function ($option) {
|
||||
$allowed = array_column($this->options(), 'value');
|
||||
return in_array($option, $allowed, true) === true ? $option : null;
|
||||
'sanitizeOption' => function ($value) {
|
||||
$options = array_column($this->options(), 'value');
|
||||
return in_array($value, $options, true) === true ? $value : null;
|
||||
},
|
||||
'sanitizeOptions' => function ($options) {
|
||||
$allowed = array_column($this->options(), 'value');
|
||||
return array_intersect($options, $allowed);
|
||||
'sanitizeOptions' => function ($values) {
|
||||
$options = array_column($this->options(), 'value');
|
||||
$options = array_intersect($values, $options);
|
||||
return array_values($options);
|
||||
},
|
||||
]
|
||||
];
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
|
@ -67,12 +68,21 @@ return [
|
|||
return $search;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether to store UUID or ID in the
|
||||
* content file of the model
|
||||
*
|
||||
* @param string $store 'uuid'|'id'
|
||||
*/
|
||||
'store' => function (string $store = 'uuid') {
|
||||
return Str::lower($store);
|
||||
},
|
||||
|
||||
/**
|
||||
* Main text for each item
|
||||
*/
|
||||
'text' => function (string $text = null) {
|
||||
return $text;
|
||||
},
|
||||
|
||||
],
|
||||
];
|
||||
|
|
|
@ -51,7 +51,7 @@ return [
|
|||
$parent = $this->model();
|
||||
}
|
||||
|
||||
if (is_a($parent, 'Kirby\Cms\File') === true) {
|
||||
if ($parent instanceof File) {
|
||||
$parent = $parent->parent();
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ return [
|
|||
'filename' => $filename,
|
||||
]);
|
||||
|
||||
if (is_a($file, 'Kirby\Cms\File') === false) {
|
||||
if ($file instanceof File === false) {
|
||||
throw new Exception('The file could not be uploaded');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
return [
|
||||
'extends' => 'tags',
|
||||
'props' => [
|
||||
|
@ -28,5 +30,18 @@ return [
|
|||
'sort' => function (bool $sort = false) {
|
||||
return $sort;
|
||||
},
|
||||
]
|
||||
],
|
||||
'methods' => [
|
||||
'toValues' => function ($value) {
|
||||
if (is_null($value) === true) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (is_array($value) === false) {
|
||||
$value = Str::split($value, $this->separator());
|
||||
}
|
||||
|
||||
return $this->sanitizeOptions($value);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
104
kirby/config/fields/object.php
Normal file
104
kirby/config/fields/object.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Data\Data;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Form\Form;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
/**
|
||||
* Unset inherited props
|
||||
*/
|
||||
'after' => null,
|
||||
'before' => null,
|
||||
'autofocus' => null,
|
||||
'icon' => null,
|
||||
'placeholder' => null,
|
||||
|
||||
/**
|
||||
* Set the default values for the object
|
||||
*/
|
||||
'default' => function ($default = null) {
|
||||
return $default;
|
||||
},
|
||||
|
||||
/**
|
||||
* The placeholder text if no information has been added yet
|
||||
*/
|
||||
'empty' => function ($empty = null) {
|
||||
return I18n::translate($empty, $empty);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fields setup for the object form. Works just like fields in regular forms.
|
||||
*/
|
||||
'fields' => function (array $fields = []) {
|
||||
return $fields;
|
||||
}
|
||||
],
|
||||
'computed' => [
|
||||
'default' => function () {
|
||||
if (empty($this->default) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->form($this->default)->values();
|
||||
},
|
||||
'fields' => function () {
|
||||
if (empty($this->fields) === true) {
|
||||
throw new Exception('Please provide some fields for the object');
|
||||
}
|
||||
|
||||
return $this->form()->fields()->toArray();
|
||||
},
|
||||
'value' => function () {
|
||||
$data = Data::decode($this->value, 'yaml');
|
||||
|
||||
if (empty($data) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->form($data)->values();
|
||||
}
|
||||
],
|
||||
'methods' => [
|
||||
'form' => function (array $values = []) {
|
||||
return new Form([
|
||||
'fields' => $this->attrs['fields'],
|
||||
'values' => $values,
|
||||
'model' => $this->model
|
||||
]);
|
||||
},
|
||||
],
|
||||
'save' => function ($value) {
|
||||
if (empty($value) === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->form($value)->content();
|
||||
},
|
||||
'validations' => [
|
||||
'object' => function ($value) {
|
||||
if (empty($value) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$errors = $this->form($value)->errors();
|
||||
|
||||
if (empty($errors) === false) {
|
||||
// use the first error for details
|
||||
$name = array_key_first($errors);
|
||||
$error = $errors[$name];
|
||||
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'object.validation',
|
||||
'data' => [
|
||||
'label' => $error['label'] ?? $name,
|
||||
'message' => implode("\n", $error['message'])
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
]
|
||||
];
|
|
@ -67,7 +67,7 @@ return [
|
|||
|
||||
foreach (Data::decode($value, 'yaml') as $id) {
|
||||
if (is_array($id) === true) {
|
||||
$id = $id['id'] ?? null;
|
||||
$id = $id['uuid'] ?? $id['id'] ?? null;
|
||||
}
|
||||
|
||||
if ($id !== null && ($page = $kirby->page($id))) {
|
||||
|
@ -102,7 +102,7 @@ return [
|
|||
];
|
||||
},
|
||||
'save' => function ($value = null) {
|
||||
return A::pluck($value, 'id');
|
||||
return A::pluck($value, $this->store);
|
||||
},
|
||||
'validations' => [
|
||||
'max',
|
||||
|
|
|
@ -108,7 +108,7 @@ return [
|
|||
$columns = [];
|
||||
$mobile = 0;
|
||||
|
||||
if (empty($this->columns)) {
|
||||
if (empty($this->columns) === true) {
|
||||
foreach ($this->fields as $field) {
|
||||
// Skip hidden and unsaveable fields
|
||||
// They should never be included as column
|
||||
|
@ -129,7 +129,10 @@ return [
|
|||
|
||||
$field = $this->fields[$columnName] ?? null;
|
||||
|
||||
if (empty($field) === true || $field['saveable'] === false) {
|
||||
if (
|
||||
empty($field) === true ||
|
||||
$field['saveable'] === false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -137,10 +140,10 @@ return [
|
|||
$mobile++;
|
||||
}
|
||||
|
||||
$columns[$columnName] = array_merge($columnProps, [
|
||||
$columns[$columnName] = array_merge([
|
||||
'type' => $field['type'],
|
||||
'label' => $field['label'] ?? $field['name']
|
||||
]);
|
||||
], $columnProps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ return [
|
|||
* Set to `list` to display each tag with 100% width,
|
||||
* otherwise the tags are displayed inline
|
||||
*/
|
||||
'layout' => function (?string $layout = null) {
|
||||
'layout' => function (string|null $layout = null) {
|
||||
return $layout;
|
||||
},
|
||||
/**
|
||||
|
@ -55,43 +55,32 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'default' => function (): array {
|
||||
return $this->toTags($this->default);
|
||||
return $this->toValues($this->default);
|
||||
},
|
||||
'value' => function (): array {
|
||||
return $this->toTags($this->value);
|
||||
return $this->toValues($this->value);
|
||||
}
|
||||
],
|
||||
'methods' => [
|
||||
'toTags' => function ($value) {
|
||||
'toValues' => function ($value) {
|
||||
if (is_null($value) === true) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$options = $this->options();
|
||||
if (is_array($value) === false) {
|
||||
$value = Str::split($value, $this->separator());
|
||||
}
|
||||
|
||||
// transform into value-text objects
|
||||
return array_map(function ($option) use ($options) {
|
||||
// already a valid object
|
||||
if (is_array($option) === true && isset($option['value'], $option['text']) === true) {
|
||||
return $option;
|
||||
}
|
||||
if ($this->accept === 'options') {
|
||||
$value = $this->sanitizeOptions($value);
|
||||
}
|
||||
|
||||
$index = array_search($option, array_column($options, 'value'));
|
||||
|
||||
if ($index !== false) {
|
||||
return $options[$index];
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $option,
|
||||
'text' => $option,
|
||||
];
|
||||
}, Str::split($value, $this->separator()));
|
||||
return $value;
|
||||
}
|
||||
],
|
||||
'save' => function (array $value = null): string {
|
||||
return A::join(
|
||||
A::pluck($value, 'value'),
|
||||
$value,
|
||||
$this->separator() . ' '
|
||||
);
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ return [
|
|||
/**
|
||||
* Sets the default time when a new page/file/user is created
|
||||
*/
|
||||
'default' => function ($default = null): ?string {
|
||||
'default' => function ($default = null): string|null {
|
||||
return $default;
|
||||
},
|
||||
|
||||
|
@ -36,13 +36,13 @@ return [
|
|||
/**
|
||||
* Latest time, which can be selected/saved (H:i or H:i:s)
|
||||
*/
|
||||
'max' => function (string $max = null): ?string {
|
||||
'max' => function (string $max = null): string|null {
|
||||
return Date::optional($max);
|
||||
},
|
||||
/**
|
||||
* Earliest time, which can be selected/saved (H:i or H:i:s)
|
||||
*/
|
||||
'min' => function (string $min = null): ?string {
|
||||
'min' => function (string $min = null): string|null {
|
||||
return Date::optional($min);
|
||||
},
|
||||
|
||||
|
@ -62,7 +62,7 @@ return [
|
|||
'unit' => 'minute',
|
||||
]);
|
||||
},
|
||||
'value' => function ($value = null): ?string {
|
||||
'value' => function ($value = null): string|null {
|
||||
return $value;
|
||||
}
|
||||
],
|
||||
|
@ -80,7 +80,7 @@ return [
|
|||
'format' => function () {
|
||||
return $this->props['format'] ?? 'H:i:s';
|
||||
},
|
||||
'value' => function (): ?string {
|
||||
'value' => function (): string|null {
|
||||
return $this->toDatetime($this->value, 'H:i:s') ?? '';
|
||||
}
|
||||
],
|
||||
|
|
|
@ -49,9 +49,9 @@ return [
|
|||
'value' => function () {
|
||||
if ($this->props['value'] === null) {
|
||||
return $this->default();
|
||||
} else {
|
||||
return $this->toBool($this->props['value']);
|
||||
}
|
||||
|
||||
return $this->toBool($this->props['value']);
|
||||
}
|
||||
],
|
||||
'methods' => [
|
||||
|
|
|
@ -96,7 +96,7 @@ return [
|
|||
];
|
||||
},
|
||||
'save' => function ($value = null) {
|
||||
return A::pluck($value, 'id');
|
||||
return A::pluck($value, $this->store);
|
||||
},
|
||||
'validations' => [
|
||||
'max',
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Helpers;
|
||||
use Kirby\Cms\Html;
|
||||
use Kirby\Cms\Response;
|
||||
use Kirby\Cms\Url;
|
||||
use Kirby\Filesystem\Asset;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Http\Router;
|
||||
use Kirby\Toolkit\Date;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
@ -35,7 +35,7 @@ if (Helpers::hasOverride('attr') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $after An optional string that will be appended if the result is not empty
|
||||
* @return string|null
|
||||
*/
|
||||
function attr(?array $attr = null, ?string $before = null, ?string $after = null): ?string
|
||||
function attr(array|null $attr = null, string|null $before = null, string|null $after = null): string|null
|
||||
{
|
||||
return Html::attr($attr, null, $before, $after);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ if (Helpers::hasOverride('csrf') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $check Pass a token here to compare it to the one in the session
|
||||
* @return string|bool Either the token or a boolean check result
|
||||
*/
|
||||
function csrf(?string $check = null)
|
||||
function csrf(string|null $check = null)
|
||||
{
|
||||
// check explicitly if there have been no arguments at all;
|
||||
// checking for null introduces a security issue because null could come
|
||||
|
@ -82,7 +82,7 @@ if (Helpers::hasOverride('css') === false) { // @codeCoverageIgnore
|
|||
* @param string|array $options Pass an array of attributes for the link tag or a media attribute string
|
||||
* @return string|null
|
||||
*/
|
||||
function css($url, $options = null): ?string
|
||||
function css($url, $options = null): string|null
|
||||
{
|
||||
return Html::css($url, $options);
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ if (Helpers::hasOverride('gist') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $file
|
||||
* @return string
|
||||
*/
|
||||
function gist(string $url, ?string $file = null): string
|
||||
function gist(string $url, string|null $file = null): string
|
||||
{
|
||||
return App::instance()->kirbytag([
|
||||
'gist' => $url,
|
||||
|
@ -199,7 +199,7 @@ if (Helpers::hasOverride('h') === false) { // @codeCoverageIgnore
|
|||
* @param bool $keepTags
|
||||
* @return string
|
||||
*/
|
||||
function h(?string $string, bool $keepTags = false): string
|
||||
function h(string|null $string, bool $keepTags = false): string
|
||||
{
|
||||
return Html::encode($string, $keepTags);
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ if (Helpers::hasOverride('html') === false) { // @codeCoverageIgnore
|
|||
* @param bool $keepTags
|
||||
* @return string
|
||||
*/
|
||||
function html(?string $string, bool $keepTags = false): string
|
||||
function html(string|null $string, bool $keepTags = false): string
|
||||
{
|
||||
return Html::encode($string, $keepTags);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ if (Helpers::hasOverride('image') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $path
|
||||
* @return \Kirby\Cms\File|null
|
||||
*/
|
||||
function image(?string $path = null)
|
||||
function image(string|null $path = null)
|
||||
{
|
||||
return App::instance()->image($path);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ if (Helpers::hasOverride('js') === false) { // @codeCoverageIgnore
|
|||
* @param string|array $options
|
||||
* @return string|null
|
||||
*/
|
||||
function js($url, $options = null): ?string
|
||||
function js($url, $options = null): string|null
|
||||
{
|
||||
return Html::js($url, $options);
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ if (Helpers::hasOverride('kirbytag') === false) { // @codeCoverageIgnore
|
|||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytag($type, ?string $value = null, array $attr = [], array $data = []): string
|
||||
function kirbytag($type, string|null $value = null, array $attr = [], array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytag($type, $value, $attr, $data);
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ if (Helpers::hasOverride('kirbytags') === false) { // @codeCoverageIgnore
|
|||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytags(?string $text = null, array $data = []): string
|
||||
function kirbytags(string|null $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytags($text, $data);
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ if (Helpers::hasOverride('kirbytext') === false) { // @codeCoverageIgnore
|
|||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytext(?string $text = null, array $data = []): string
|
||||
function kirbytext(string|null $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytext($text, $data);
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ if (Helpers::hasOverride('kirbytextinline') === false) { // @codeCoverageIgnore
|
|||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
function kirbytextinline(?string $text = null, array $options = []): string
|
||||
function kirbytextinline(string|null $text = null, array $options = []): string
|
||||
{
|
||||
$options['markdown']['inline'] = true;
|
||||
return App::instance()->kirbytext($text, $options);
|
||||
|
@ -348,7 +348,7 @@ if (Helpers::hasOverride('kt') === false) { // @codeCoverageIgnore
|
|||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kt(?string $text = null, array $data = []): string
|
||||
function kt(string|null $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytext($text, $data);
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ if (Helpers::hasOverride('kti') === false) { // @codeCoverageIgnore
|
|||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
function kti(?string $text = null, array $options = []): string
|
||||
function kti(string|null $text = null, array $options = []): string
|
||||
{
|
||||
$options['markdown']['inline'] = true;
|
||||
return App::instance()->kirbytext($text, $options);
|
||||
|
@ -378,7 +378,7 @@ if (Helpers::hasOverride('load') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $base
|
||||
* @return void
|
||||
*/
|
||||
function load(array $classmap, ?string $base = null): void
|
||||
function load(array $classmap, string|null $base = null): void
|
||||
{
|
||||
F::loadClasses($classmap, $base);
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ if (Helpers::hasOverride('markdown') === false) { // @codeCoverageIgnore
|
|||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
function markdown(?string $text = null, array $options = []): string
|
||||
function markdown(string|null $text = null, array $options = []): string
|
||||
{
|
||||
return App::instance()->markdown($text, $options);
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ if (Helpers::hasOverride('page') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $id
|
||||
* @return \Kirby\Cms\Page|null
|
||||
*/
|
||||
function page(?string $id = null)
|
||||
function page(string|null $id = null)
|
||||
{
|
||||
if (empty($id) === true) {
|
||||
return App::instance()->site()->page();
|
||||
|
@ -459,8 +459,9 @@ if (Helpers::hasOverride('param') === false) { // @codeCoverageIgnore
|
|||
* @param string $key
|
||||
* @param string|null $fallback
|
||||
* @return string|null
|
||||
* @psalm-return ($fallback is string ? string : string|null)
|
||||
*/
|
||||
function param(string $key, ?string $fallback = null): ?string
|
||||
function param(string $key, string|null $fallback = null): string|null
|
||||
{
|
||||
return App::instance()->request()->url()->params()->$key ?? $fallback;
|
||||
}
|
||||
|
@ -505,7 +506,7 @@ if (Helpers::hasOverride('router') === false) { // @codeCoverageIgnore
|
|||
* @param \Closure|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
function router(?string $path = null, string $method = 'GET', array $routes = [], ?Closure $callback = null)
|
||||
function router(string|null $path = null, string $method = 'GET', array $routes = [], Closure|null $callback = null)
|
||||
{
|
||||
return Router::execute($path, $method, $routes, $callback);
|
||||
}
|
||||
|
@ -545,7 +546,7 @@ if (Helpers::hasOverride('smartypants') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $text
|
||||
* @return string
|
||||
*/
|
||||
function smartypants(?string $text = null): string
|
||||
function smartypants(string|null $text = null): string
|
||||
{
|
||||
return App::instance()->smartypants($text);
|
||||
}
|
||||
|
@ -560,7 +561,7 @@ if (Helpers::hasOverride('snippet') === false) { // @codeCoverageIgnore
|
|||
* @param bool $return
|
||||
* @return string|null
|
||||
*/
|
||||
function snippet($name, $data = [], bool $return = false): ?string
|
||||
function snippet($name, $data = [], bool $return = false): string|null
|
||||
{
|
||||
return App::instance()->snippet($name, $data, $return);
|
||||
}
|
||||
|
@ -624,7 +625,7 @@ if (Helpers::hasOverride('timestamp') === false) { // @codeCoverageIgnore
|
|||
* @param int|array|null $step array of `unit` and `size` to round to nearest
|
||||
* @return int|null
|
||||
*/
|
||||
function timestamp(?string $date = null, $step = null): ?int
|
||||
function timestamp(string|null $date = null, $step = null): int|null
|
||||
{
|
||||
return Date::roundedTimestamp($date, $step);
|
||||
}
|
||||
|
@ -641,7 +642,7 @@ if (Helpers::hasOverride('tt') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function tt(string $key, $fallback = null, ?array $replace = null, ?string $locale = null): string
|
||||
function tt(string $key, $fallback = null, array|null $replace = null, string|null $locale = null): string
|
||||
{
|
||||
return I18n::template($key, $fallback, $replace, $locale);
|
||||
}
|
||||
|
@ -657,7 +658,7 @@ if (Helpers::hasOverride('twitter') === false) { // @codeCoverageIgnore
|
|||
* @param string|null $class
|
||||
* @return string
|
||||
*/
|
||||
function twitter(string $username, ?string $text = null, ?string $title = null, ?string $class = null): string
|
||||
function twitter(string $username, string|null $text = null, string|null $title = null, string|null $class = null): string
|
||||
{
|
||||
return App::instance()->kirbytag([
|
||||
'twitter' => $username,
|
||||
|
@ -676,7 +677,7 @@ if (Helpers::hasOverride('u') === false) { // @codeCoverageIgnore
|
|||
* @param array|string|null $options
|
||||
* @return string
|
||||
*/
|
||||
function u(?string $path = null, $options = null): string
|
||||
function u(string|null $path = null, $options = null): string
|
||||
{
|
||||
return Url::to($path, $options);
|
||||
}
|
||||
|
@ -690,7 +691,7 @@ if (Helpers::hasOverride('url') === false) { // @codeCoverageIgnore
|
|||
* @param array|string|null $options
|
||||
* @return string
|
||||
*/
|
||||
function url(?string $path = null, $options = null): string
|
||||
function url(string|null $path = null, $options = null): string
|
||||
{
|
||||
return Url::to($path, $options);
|
||||
}
|
||||
|
@ -719,7 +720,7 @@ if (Helpers::hasOverride('video') === false) { // @codeCoverageIgnore
|
|||
* @param array $attr
|
||||
* @return string|null
|
||||
*/
|
||||
function video(string $url, array $options = [], array $attr = []): ?string
|
||||
function video(string $url, array $options = [], array $attr = []): string|null
|
||||
{
|
||||
return Html::video($url, $options, $attr);
|
||||
}
|
||||
|
@ -734,7 +735,7 @@ if (Helpers::hasOverride('vimeo') === false) { // @codeCoverageIgnore
|
|||
* @param array $attr
|
||||
* @return string|null
|
||||
*/
|
||||
function vimeo(string $url, array $options = [], array $attr = []): ?string
|
||||
function vimeo(string $url, array $options = [], array $attr = []): string|null
|
||||
{
|
||||
return Html::vimeo($url, $options, $attr);
|
||||
}
|
||||
|
@ -764,7 +765,7 @@ if (Helpers::hasOverride('youtube') === false) { // @codeCoverageIgnore
|
|||
* @param array $attr
|
||||
* @return string|null
|
||||
*/
|
||||
function youtube(string $url, array $options = [], array $attr = []): ?string
|
||||
function youtube(string $url, array $options = [], array $attr = []): string|null
|
||||
{
|
||||
return Html::youtube($url, $options, $attr);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Blocks;
|
||||
use Kirby\Cms\Content;
|
||||
use Kirby\Cms\Field;
|
||||
use Kirby\Cms\Files;
|
||||
use Kirby\Cms\Html;
|
||||
|
@ -63,16 +64,16 @@ return function (App $app) {
|
|||
*/
|
||||
'toBlocks' => function (Field $field) {
|
||||
try {
|
||||
$blocks = Blocks::factory(Blocks::parse($field->value()), [
|
||||
'parent' => $field->parent(),
|
||||
$blocks = Blocks::parse($field->value());
|
||||
$blocks = Blocks::factory($blocks, [
|
||||
'parent' => $field->parent()
|
||||
]);
|
||||
|
||||
return $blocks->filter('isHidden', false);
|
||||
} catch (Throwable $e) {
|
||||
if ($field->parent() === null) {
|
||||
$message = 'Invalid blocks data for "' . $field->key() . '" field';
|
||||
} else {
|
||||
$message = 'Invalid blocks data for "' . $field->key() . '" field on parent "' . $field->parent()->title() . '"';
|
||||
} catch (Throwable) {
|
||||
$message = 'Invalid blocks data for "' . $field->key() . '" field';
|
||||
|
||||
if ($parent = $field->parent()) {
|
||||
$message .= ' on parent "' . $parent->title() . '"';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException($message);
|
||||
|
@ -99,13 +100,10 @@ return function (App $app) {
|
|||
* @return array
|
||||
*/
|
||||
'toData' => function (Field $field, string $method = ',') {
|
||||
switch ($method) {
|
||||
case 'yaml':
|
||||
case 'json':
|
||||
return Data::decode($field->value, $method);
|
||||
default:
|
||||
return $field->split($method);
|
||||
}
|
||||
return match ($method) {
|
||||
'yaml', 'json' => Data::decode($field->value, $method),
|
||||
default => $field->split($method)
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -222,6 +220,17 @@ return function (App $app) {
|
|||
return Html::a($href, $field->value, $attr ?? []);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse yaml data and convert it to a
|
||||
* content object
|
||||
*
|
||||
* @param \Kirby\Cms\Field $field
|
||||
* @return \Kirby\Cms\Content
|
||||
*/
|
||||
'toObject' => function (Field $field) {
|
||||
return new Content($field->yaml(), $field->parent(), true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a page object from a page id in the field
|
||||
*
|
||||
|
@ -252,11 +261,11 @@ return function (App $app) {
|
|||
'toStructure' => function (Field $field) {
|
||||
try {
|
||||
return new Structure(Data::decode($field->value, 'yaml'), $field->parent());
|
||||
} catch (Exception $e) {
|
||||
if ($field->parent() === null) {
|
||||
$message = 'Invalid structure data for "' . $field->key() . '" field';
|
||||
} else {
|
||||
$message = 'Invalid structure data for "' . $field->key() . '" field on parent "' . $field->parent()->title() . '"';
|
||||
} catch (Exception) {
|
||||
$message = 'Invalid structure data for "' . $field->key() . '" field';
|
||||
|
||||
if ($parent = $field->parent()) {
|
||||
$message .= ' on parent "' . $parent->title() . '"';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException($message);
|
||||
|
@ -341,7 +350,7 @@ return function (App $app) {
|
|||
* @param string $context Location of output (`html`, `attr`, `js`, `css`, `url` or `xml`)
|
||||
*/
|
||||
'escape' => function (Field $field, string $context = 'html') {
|
||||
$field->value = Str::esc($field->value, $context);
|
||||
$field->value = Str::esc($field->value ?? '', $context);
|
||||
return $field;
|
||||
},
|
||||
|
||||
|
@ -500,10 +509,11 @@ return function (App $app) {
|
|||
*
|
||||
* @param \Kirby\Cms\Field $field
|
||||
* @param array $data
|
||||
* @param string $fallback Fallback for tokens in the template that cannot be replaced
|
||||
* @param string|null $fallback Fallback for tokens in the template that cannot be replaced
|
||||
* (`null` to keep the original token)
|
||||
* @return \Kirby\Cms\Field
|
||||
*/
|
||||
'replace' => function (Field $field, array $data = [], string $fallback = '') use ($app) {
|
||||
'replace' => function (Field $field, array $data = [], string|null $fallback = '') use ($app) {
|
||||
if ($parent = $field->parent()) {
|
||||
// never pass `null` as the $template to avoid the fallback to the model ID
|
||||
$field->value = $parent->toString($field->value ?? '', $data, $fallback);
|
||||
|
|
|
@ -5,7 +5,7 @@ use Kirby\Toolkit\I18n;
|
|||
return function (array $props) {
|
||||
$props['sections'] = [
|
||||
'files' => [
|
||||
'headline' => $props['headline'] ?? I18n::translate('files'),
|
||||
'label' => $props['label'] ?? $props['headline'] ?? I18n::translate('files'),
|
||||
'type' => 'files',
|
||||
'layout' => $props['layout'] ?? 'cards',
|
||||
'template' => $props['template'] ?? null,
|
||||
|
@ -17,6 +17,7 @@ return function (array $props) {
|
|||
// remove global options
|
||||
unset(
|
||||
$props['headline'],
|
||||
$props['label'],
|
||||
$props['layout'],
|
||||
$props['template'],
|
||||
$props['image']
|
||||
|
|
|
@ -10,7 +10,7 @@ return function ($props) {
|
|||
|
||||
if (is_string($props) === true) {
|
||||
$props = [
|
||||
'headline' => $props
|
||||
'label' => $props
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -27,18 +27,18 @@ return function ($props) {
|
|||
|
||||
if ($pages !== false) {
|
||||
$sidebar['pages'] = $section([
|
||||
'headline' => I18n::translate('pages'),
|
||||
'type' => 'pages',
|
||||
'status' => 'all',
|
||||
'layout' => 'list',
|
||||
'label' => I18n::translate('pages'),
|
||||
'type' => 'pages',
|
||||
'status' => 'all',
|
||||
'layout' => 'list',
|
||||
], $pages);
|
||||
}
|
||||
|
||||
if ($files !== false) {
|
||||
$sidebar['files'] = $section([
|
||||
'headline' => I18n::translate('files'),
|
||||
'type' => 'files',
|
||||
'layout' => 'list'
|
||||
'label' => I18n::translate('files'),
|
||||
'type' => 'files',
|
||||
'layout' => 'list'
|
||||
], $files);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ return function (array $props) {
|
|||
// load the general templates setting for all sections
|
||||
$templates = $props['templates'] ?? null;
|
||||
|
||||
$section = function ($headline, $status, $props) use ($templates) {
|
||||
$section = function ($label, $status, $props) use ($templates) {
|
||||
$defaults = [
|
||||
'headline' => $headline,
|
||||
'type' => 'pages',
|
||||
'layout' => 'list',
|
||||
'status' => $status
|
||||
'label' => $label,
|
||||
'type' => 'pages',
|
||||
'layout' => 'list',
|
||||
'status' => $status
|
||||
];
|
||||
|
||||
if ($props === true) {
|
||||
|
@ -20,7 +20,7 @@ return function (array $props) {
|
|||
|
||||
if (is_string($props) === true) {
|
||||
$props = [
|
||||
'headline' => $props
|
||||
'label' => $props
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use Kirby\Cms\PluginAssets;
|
|||
use Kirby\Panel\Panel;
|
||||
use Kirby\Panel\Plugins;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Kirby\Uuid\Uuid;
|
||||
|
||||
return function ($kirby) {
|
||||
$api = $kirby->option('api.slug', 'api');
|
||||
|
@ -101,6 +102,26 @@ return function ($kirby) {
|
|||
return Panel::router($path);
|
||||
}
|
||||
],
|
||||
// permalinks for page/file UUIDs
|
||||
[
|
||||
'pattern' => '@/(page|file)/(:all)',
|
||||
'method' => 'ALL',
|
||||
'env' => 'site',
|
||||
'action' => function (string $type, string $id) use ($kirby) {
|
||||
// try to resolve to model, but only from UUID cache;
|
||||
// this ensures that only existing UUIDs can be queried
|
||||
// and attackers can't force Kirby to go through the whole
|
||||
// site index with a non-existing UUID
|
||||
if ($model = Uuid::for($type . '://' . $id)?->model(true)) {
|
||||
return $kirby
|
||||
->response()
|
||||
->redirect($model->url());
|
||||
}
|
||||
|
||||
// render the error page
|
||||
return false;
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
// Multi-language setup
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Cms\Site;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
return [
|
||||
|
@ -31,7 +33,10 @@ return [
|
|||
'fields' => function () {
|
||||
$fields = $this->form->fields()->toArray();
|
||||
|
||||
if (is_a($this->model, 'Kirby\Cms\Page') === true || is_a($this->model, 'Kirby\Cms\Site') === true) {
|
||||
if (
|
||||
$this->model instanceof Page ||
|
||||
$this->model instanceof Site
|
||||
) {
|
||||
// the title should never be updated directly via
|
||||
// fields section to avoid conflicts with the rename dialog
|
||||
unset($fields['title']);
|
||||
|
|
|
@ -25,9 +25,9 @@ return [
|
|||
],
|
||||
'toArray' => function () {
|
||||
return [
|
||||
'headline' => $this->headline,
|
||||
'text' => $this->text,
|
||||
'theme' => $this->theme
|
||||
'label' => $this->headline,
|
||||
'text' => $this->text,
|
||||
'theme' => $this->theme
|
||||
];
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Helpers;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
/**
|
||||
* The headline for the section. This can be a simple string or a template with additional info from the parent page.
|
||||
* @todo remove in 3.9.0
|
||||
* @deprecated 3.8.0 Use `label` instead
|
||||
*/
|
||||
'headline' => function ($headline = null) {
|
||||
// TODO: add deprecation notive in 3.8.0
|
||||
// if ($headline !== null) {
|
||||
// Helpers::deprecated('`headline` prop for sections has been deprecated and will be removed in Kirby 3.9.0. Use `label` instead.');
|
||||
// }
|
||||
|
||||
return I18n::translate($headline, $headline);
|
||||
},
|
||||
/**
|
||||
|
@ -28,14 +22,14 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'headline' => function () {
|
||||
if ($this->headline) {
|
||||
return $this->model()->toString($this->headline);
|
||||
}
|
||||
|
||||
if ($this->label) {
|
||||
return $this->model()->toString($this->label);
|
||||
}
|
||||
|
||||
if ($this->headline) {
|
||||
return $this->model()->toString($this->headline);
|
||||
}
|
||||
|
||||
return ucfirst($this->name);
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Cms\Site;
|
||||
use Kirby\Cms\User;
|
||||
use Kirby\Exception\Exception;
|
||||
|
||||
return [
|
||||
|
@ -24,10 +28,10 @@ return [
|
|||
}
|
||||
|
||||
if (
|
||||
is_a($parent, 'Kirby\Cms\Page') === false &&
|
||||
is_a($parent, 'Kirby\Cms\Site') === false &&
|
||||
is_a($parent, 'Kirby\Cms\File') === false &&
|
||||
is_a($parent, 'Kirby\Cms\User') === false
|
||||
$parent instanceof Page === false &&
|
||||
$parent instanceof Site === false &&
|
||||
$parent instanceof File === false &&
|
||||
$parent instanceof User === false
|
||||
) {
|
||||
throw new Exception('The parent for the section "' . $this->name() . '" has to be a page, site or user object');
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ return [
|
|||
}
|
||||
],
|
||||
'methods' => [
|
||||
'searchterm' => function (): ?string {
|
||||
'searchterm' => function (): string|null {
|
||||
return App::instance()->request()->get('searchterm');
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Blueprint;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Cms\Site;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
@ -53,8 +55,8 @@ return [
|
|||
$parent = $this->parentModel();
|
||||
|
||||
if (
|
||||
is_a($parent, 'Kirby\Cms\Site') === false &&
|
||||
is_a($parent, 'Kirby\Cms\Page') === false
|
||||
$parent instanceof Site === false &&
|
||||
$parent instanceof Page === false
|
||||
) {
|
||||
throw new InvalidArgumentException('The parent is invalid. You must choose the site or a page as parent.');
|
||||
}
|
||||
|
@ -62,22 +64,13 @@ return [
|
|||
return $parent;
|
||||
},
|
||||
'pages' => function () {
|
||||
switch ($this->status) {
|
||||
case 'draft':
|
||||
$pages = $this->parent->drafts();
|
||||
break;
|
||||
case 'listed':
|
||||
$pages = $this->parent->children()->listed();
|
||||
break;
|
||||
case 'published':
|
||||
$pages = $this->parent->children();
|
||||
break;
|
||||
case 'unlisted':
|
||||
$pages = $this->parent->children()->unlisted();
|
||||
break;
|
||||
default:
|
||||
$pages = $this->parent->childrenAndDrafts();
|
||||
}
|
||||
$pages = match ($this->status) {
|
||||
'draft' => $this->parent->drafts(),
|
||||
'listed' => $this->parent->children()->listed(),
|
||||
'published' => $this->parent->children(),
|
||||
'unlisted' => $this->parent->children()->unlisted(),
|
||||
default => $this->parent->childrenAndDrafts()
|
||||
};
|
||||
|
||||
// filters pages that are protected and not in the templates list
|
||||
// internal `filter()` method used instead of foreach loop that previously included `unset()`
|
||||
|
@ -228,7 +221,7 @@ return [
|
|||
'name' => basename($props['name']),
|
||||
'title' => $props['title'],
|
||||
];
|
||||
} catch (Throwable $e) {
|
||||
} catch (Throwable) {
|
||||
$blueprints[] = [
|
||||
'name' => basename($template),
|
||||
'title' => ucfirst($template),
|
||||
|
|
|
@ -47,10 +47,12 @@ return [
|
|||
continue;
|
||||
}
|
||||
|
||||
$info = $report['info'] ?? null;
|
||||
|
||||
$reports[] = [
|
||||
'label' => I18n::translate($report['label'], $report['label']),
|
||||
'value' => $value($report['value'] ?? null),
|
||||
'info' => $value($report['info'] ?? null),
|
||||
'info' => $value(I18n::translate($info, $info)),
|
||||
'link' => $value($report['link'] ?? null),
|
||||
'theme' => $value($report['theme'] ?? null)
|
||||
];
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
/**
|
||||
* Constants
|
||||
* @deprecated 3.8.0 Use `/` instead
|
||||
*/
|
||||
define('DS', '/');
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use Kirby\Cms\Html;
|
||||
use Kirby\Cms\Url;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Kirby\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* Default KirbyTags definition
|
||||
|
@ -117,11 +118,8 @@ return [
|
|||
return $img;
|
||||
}
|
||||
|
||||
if ($link = $tag->file($tag->link)) {
|
||||
$link = $link->url();
|
||||
} else {
|
||||
$link = $tag->link === 'self' ? $tag->src : $tag->link;
|
||||
}
|
||||
$link = $tag->file($tag->link)?->url();
|
||||
$link ??= $tag->link === 'self' ? $tag->src : $tag->link;
|
||||
|
||||
return Html::a($link, [$img], [
|
||||
'rel' => $tag->rel,
|
||||
|
@ -173,6 +171,15 @@ return [
|
|||
$tag->value = Url::to($tag->value, $tag->lang);
|
||||
}
|
||||
|
||||
// if value is a UUID, resolve to page/file model
|
||||
// and use the URL as value
|
||||
if (
|
||||
Uuid::is($tag->value, 'page') === true ||
|
||||
Uuid::is($tag->value, 'file') === true
|
||||
) {
|
||||
$tag->value = Uuid::for($tag->value)->model()->url();
|
||||
}
|
||||
|
||||
return Html::a($tag->value, $tag->text, [
|
||||
'rel' => $tag->rel,
|
||||
'class' => $tag->class,
|
||||
|
|
|
@ -465,7 +465,7 @@ class ParsedownExtra extends Parsedown
|
|||
),
|
||||
);
|
||||
|
||||
uasort($this->DefinitionData['Footnote'], 'self::sortFootnotes');
|
||||
uasort($this->DefinitionData['Footnote'], [$this,'sortFootnotes']);
|
||||
|
||||
foreach ($this->DefinitionData['Footnote'] as $definitionId => $DefinitionData) {
|
||||
if (! isset($DefinitionData['number'])) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2
kirby/panel/dist/css/style.css
vendored
2
kirby/panel/dist/css/style.css
vendored
File diff suppressed because one or more lines are too long
3
kirby/panel/dist/img/icons.svg
vendored
3
kirby/panel/dist/img/icons.svg
vendored
|
@ -409,6 +409,9 @@
|
|||
<symbol id="icon-markdown" viewBox="0 0 16 16">
|
||||
<path d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z" />
|
||||
</symbol>
|
||||
<symbol id="icon-mastodon" viewBox="0 0 16 16">
|
||||
<path d="M14.943 3.935c-.215-1.591-1.612-2.845-3.268-3.088-.28-.041-1.338-.19-3.79-.19h-.019c-2.453 0-2.979.148-3.258.19-1.61.236-3.08 1.363-3.437 2.973-.172.793-.19 1.672-.158 2.478.045 1.157.054 2.311.16 3.463.073.765.2 1.524.382 2.27.339 1.38 1.711 2.53 3.056 2.998 1.44.488 2.988.57 4.472.234.163-.038.325-.081.484-.131.36-.114.783-.241 1.093-.465a.036.036 0 0 0 .015-.027v-1.116a.033.033 0 0 0-.041-.031c-.951.225-1.925.338-2.902.336-1.682 0-2.134-.792-2.264-1.122a3.463 3.463 0 0 1-.196-.884.032.032 0 0 1 .04-.033c.935.224 1.893.337 2.855.336.231 0 .461 0 .693-.006.967-.027 1.986-.076 2.938-.26l.067-.015c1.501-.286 2.93-1.184 3.075-3.458.005-.09.018-.938.018-1.03.001-.316.103-2.24-.015-3.422Zm-2.31 5.674h-1.578V5.772c0-.808-.339-1.22-1.028-1.22-.758 0-1.138.488-1.138 1.45v2.1H7.32v-2.1c0-.962-.38-1.45-1.138-1.45-.686 0-1.029.412-1.03 1.22v3.837H3.577V5.656c0-.808.208-1.45.623-1.926.429-.474.991-.718 1.689-.718.808 0 1.418.308 1.825.924l.393.655.393-.655c.407-.616 1.017-.924 1.823-.924.698 0 1.26.244 1.69.718.415.475.623 1.117.623 1.926l-.002 3.953Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-menu" viewBox="0 0 16 16">
|
||||
<path d="M0 0h16v3H0V0zM0 6h16v3H0V6zM0 12h16v3H0v-3z" />
|
||||
</symbol>
|
||||
|
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 61 KiB |
2
kirby/panel/dist/js/index.js
vendored
2
kirby/panel/dist/js/index.js
vendored
File diff suppressed because one or more lines are too long
7
kirby/panel/dist/js/vendor.js
vendored
7
kirby/panel/dist/js/vendor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -4,10 +4,14 @@ namespace Kirby\Api;
|
|||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kirby\Cms\User;
|
||||
use Kirby\Exception\Exception as ExceptionException;
|
||||
use Kirby\Exception\NotFoundException;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Http\Route;
|
||||
use Kirby\Http\Router;
|
||||
use Kirby\Toolkit\Collection as BaseCollection;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Pagination;
|
||||
use Kirby\Toolkit\Properties;
|
||||
|
@ -32,82 +36,59 @@ class Api
|
|||
|
||||
/**
|
||||
* Authentication callback
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $authentication;
|
||||
protected Closure|null $authentication = null;
|
||||
|
||||
/**
|
||||
* Debugging flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $debug = false;
|
||||
protected bool $debug = false;
|
||||
|
||||
/**
|
||||
* Collection definition
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $collections = [];
|
||||
protected array $collections = [];
|
||||
|
||||
/**
|
||||
* Injected data/dependencies
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
protected array $data = [];
|
||||
|
||||
/**
|
||||
* Model definitions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $models = [];
|
||||
protected array $models = [];
|
||||
|
||||
/**
|
||||
* The current route
|
||||
*
|
||||
* @var \Kirby\Http\Route
|
||||
*/
|
||||
protected $route;
|
||||
protected Route|null $route = null;
|
||||
|
||||
/**
|
||||
* The Router instance
|
||||
*
|
||||
* @var \Kirby\Http\Router
|
||||
*/
|
||||
protected $router;
|
||||
protected Router|null $router = null;
|
||||
|
||||
/**
|
||||
* Route definition
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $routes = [];
|
||||
protected array $routes = [];
|
||||
|
||||
/**
|
||||
* Request data
|
||||
* [query, body, files]
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requestData = [];
|
||||
protected array $requestData = [];
|
||||
|
||||
/**
|
||||
* The applied request method
|
||||
* (GET, POST, PATCH, etc.)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $requestMethod;
|
||||
protected string|null $requestMethod = null;
|
||||
|
||||
/**
|
||||
* Magic accessor for any given data
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
*/
|
||||
public function __call(string $method, array $args = [])
|
||||
|
@ -117,8 +98,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Creates a new API instance
|
||||
*
|
||||
* @param array $props
|
||||
*/
|
||||
public function __construct(array $props)
|
||||
{
|
||||
|
@ -128,16 +107,10 @@ class Api
|
|||
/**
|
||||
* Runs the authentication method
|
||||
* if set
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
if ($auth = $this->authentication()) {
|
||||
return $auth->call($this);
|
||||
}
|
||||
|
||||
return true;
|
||||
return $this->authentication()?->call($this) ?? true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,7 +118,7 @@ class Api
|
|||
*
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function authentication()
|
||||
public function authentication(): Closure|null
|
||||
{
|
||||
return $this->authentication;
|
||||
}
|
||||
|
@ -154,14 +127,10 @@ class Api
|
|||
* Execute an API call for the given path,
|
||||
* request method and optional request data
|
||||
*
|
||||
* @param string|null $path
|
||||
* @param string $method
|
||||
* @param array $requestData
|
||||
* @return mixed
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function call(string $path = null, string $method = 'GET', array $requestData = [])
|
||||
public function call(string|null $path = null, string $method = 'GET', array $requestData = [])
|
||||
{
|
||||
$path = rtrim($path ?? '', '/');
|
||||
|
||||
|
@ -170,19 +139,18 @@ class Api
|
|||
|
||||
$this->router = new Router($this->routes());
|
||||
$this->route = $this->router->find($path, $method);
|
||||
$auth = $this->route->attributes()['auth'] ?? true;
|
||||
$auth = $this->route?->attributes()['auth'] ?? true;
|
||||
|
||||
if ($auth !== false) {
|
||||
$user = $this->authenticate();
|
||||
|
||||
// set PHP locales based on *user* language
|
||||
// so that e.g. strftime() gets formatted correctly
|
||||
if (is_a($user, 'Kirby\Cms\User') === true) {
|
||||
if ($user instanceof User) {
|
||||
$language = $user->language();
|
||||
|
||||
// get the locale from the translation
|
||||
$translation = $user->kirby()->translation($language);
|
||||
$locale = ($translation !== null) ? $translation->locale() : $language;
|
||||
$locale = $user->kirby()->translation($language)->locale();
|
||||
|
||||
// provide some variants as fallbacks to be
|
||||
// compatible with as many systems as possible
|
||||
|
@ -208,14 +176,17 @@ class Api
|
|||
$validate = Pagination::$validate;
|
||||
Pagination::$validate = false;
|
||||
|
||||
$output = $this->route->action()->call($this, ...$this->route->arguments());
|
||||
$output = $this->route?->action()->call(
|
||||
$this,
|
||||
...$this->route->arguments()
|
||||
);
|
||||
|
||||
// restore old pagination validation mode
|
||||
Pagination::$validate = $validate;
|
||||
|
||||
if (
|
||||
is_object($output) === true &&
|
||||
is_a($output, 'Kirby\\Http\\Response') !== true
|
||||
$output instanceof Response === false
|
||||
) {
|
||||
return $this->resolve($output)->toResponse();
|
||||
}
|
||||
|
@ -226,13 +197,10 @@ class Api
|
|||
/**
|
||||
* Setter and getter for an API collection
|
||||
*
|
||||
* @param string $name
|
||||
* @param array|null $collection
|
||||
* @return \Kirby\Api\Collection
|
||||
* @throws \Kirby\Exception\NotFoundException If no collection for `$name` exists
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function collection(string $name, $collection = null)
|
||||
public function collection(string $name, array|BaseCollection|null $collection = null): Collection
|
||||
{
|
||||
if (isset($this->collections[$name]) === false) {
|
||||
throw new NotFoundException(sprintf('The collection "%s" does not exist', $name));
|
||||
|
@ -243,8 +211,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Returns the collections definition
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function collections(): array
|
||||
{
|
||||
|
@ -255,13 +221,9 @@ class Api
|
|||
* Returns the injected data array
|
||||
* or certain parts of it by key
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed ...$args
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Kirby\Exception\NotFoundException If no data for `$key` exists
|
||||
*/
|
||||
public function data($key = null, ...$args)
|
||||
public function data(string|null $key = null, ...$args)
|
||||
{
|
||||
if ($key === null) {
|
||||
return $this->data;
|
||||
|
@ -272,7 +234,7 @@ class Api
|
|||
}
|
||||
|
||||
// lazy-load data wrapped in Closures
|
||||
if (is_a($this->data[$key], 'Closure') === true) {
|
||||
if ($this->data[$key] instanceof Closure) {
|
||||
return $this->data[$key]->call($this, ...$args);
|
||||
}
|
||||
|
||||
|
@ -281,8 +243,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Returns the debugging flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function debug(): bool
|
||||
{
|
||||
|
@ -291,9 +251,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Checks if injected data exists for the given key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function hasData(string $key): bool
|
||||
{
|
||||
|
@ -305,39 +262,31 @@ class Api
|
|||
* based on the `type` field
|
||||
*
|
||||
* @param array models or collections
|
||||
* @param mixed $object
|
||||
*
|
||||
* @return string key of match
|
||||
* @return string|null key of match
|
||||
*/
|
||||
protected function match(array $array, $object = null)
|
||||
protected function match(array $array, $object = null): string|null
|
||||
{
|
||||
foreach ($array as $definition => $model) {
|
||||
if (is_a($object, $model['type']) === true) {
|
||||
if ($object instanceof $model['type']) {
|
||||
return $definition;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an API model instance by name
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param mixed $object
|
||||
* @return \Kirby\Api\Model
|
||||
*
|
||||
* @throws \Kirby\Exception\NotFoundException If no model for `$name` exists
|
||||
*/
|
||||
public function model(string $name = null, $object = null)
|
||||
public function model(string|null $name = null, $object = null): Model
|
||||
{
|
||||
// Try to auto-match object with API models
|
||||
if ($name === null) {
|
||||
if ($model = $this->match($this->models, $object)) {
|
||||
$name = $model;
|
||||
}
|
||||
}
|
||||
$name ??= $this->match($this->models, $object);
|
||||
|
||||
if (isset($this->models[$name]) === false) {
|
||||
throw new NotFoundException(sprintf('The model "%s" does not exist', $name));
|
||||
throw new NotFoundException(sprintf('The model "%s" does not exist', $name ?? 'NULL'));
|
||||
}
|
||||
|
||||
return new Model($this, $object, $this->models[$name]);
|
||||
|
@ -345,8 +294,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Returns all model definitions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function models(): array
|
||||
{
|
||||
|
@ -363,8 +310,11 @@ class Api
|
|||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestData(string $type = null, string $key = null, $default = null)
|
||||
{
|
||||
public function requestData(
|
||||
string|null $type = null,
|
||||
string|null $key = null,
|
||||
$default = null
|
||||
) {
|
||||
if ($type === null) {
|
||||
return $this->requestData;
|
||||
}
|
||||
|
@ -381,58 +331,40 @@ class Api
|
|||
|
||||
/**
|
||||
* Returns the request body if available
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestBody(string $key = null, $default = null)
|
||||
public function requestBody(string|null $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('body', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the files from the request if available
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestFiles(string $key = null, $default = null)
|
||||
public function requestFiles(string|null $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('files', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all headers from the request if available
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestHeaders(string $key = null, $default = null)
|
||||
public function requestHeaders(string|null $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('headers', $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function requestMethod(): string
|
||||
public function requestMethod(): string|null
|
||||
{
|
||||
return $this->requestMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request query if available
|
||||
*
|
||||
* @param string|null $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestQuery(string $key = null, $default = null)
|
||||
public function requestQuery(string|null $key = null, $default = null)
|
||||
{
|
||||
return $this->requestData('query', $key, $default);
|
||||
}
|
||||
|
@ -441,14 +373,14 @@ class Api
|
|||
* Turns a Kirby object into an
|
||||
* API model or collection representation
|
||||
*
|
||||
* @param mixed $object
|
||||
* @return \Kirby\Api\Model|\Kirby\Api\Collection
|
||||
*
|
||||
* @throws \Kirby\Exception\NotFoundException If `$object` cannot be resolved
|
||||
*/
|
||||
public function resolve($object)
|
||||
public function resolve($object): Model|Collection
|
||||
{
|
||||
if (is_a($object, 'Kirby\Api\Model') === true || is_a($object, 'Kirby\Api\Collection') === true) {
|
||||
if (
|
||||
$object instanceof Model ||
|
||||
$object instanceof Collection
|
||||
) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
|
@ -465,8 +397,6 @@ class Api
|
|||
|
||||
/**
|
||||
* Returns all defined routes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function routes(): array
|
||||
{
|
||||
|
@ -475,11 +405,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the authentication callback
|
||||
*
|
||||
* @param \Closure|null $authentication
|
||||
* @return $this
|
||||
*/
|
||||
protected function setAuthentication(Closure $authentication = null)
|
||||
protected function setAuthentication(Closure|null $authentication = null): static
|
||||
{
|
||||
$this->authentication = $authentication;
|
||||
return $this;
|
||||
|
@ -487,11 +415,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the collections definition
|
||||
*
|
||||
* @param array|null $collections
|
||||
* @return $this
|
||||
*/
|
||||
protected function setCollections(array $collections = null)
|
||||
protected function setCollections(array|null $collections = null): static
|
||||
{
|
||||
if ($collections !== null) {
|
||||
$this->collections = array_change_key_case($collections);
|
||||
|
@ -501,11 +427,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the injected data
|
||||
*
|
||||
* @param array|null $data
|
||||
* @return $this
|
||||
*/
|
||||
protected function setData(array $data = null)
|
||||
protected function setData(array|null $data = null): static
|
||||
{
|
||||
$this->data = $data ?? [];
|
||||
return $this;
|
||||
|
@ -513,11 +437,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the debug flag
|
||||
*
|
||||
* @param bool $debug
|
||||
* @return $this
|
||||
*/
|
||||
protected function setDebug(bool $debug = false)
|
||||
protected function setDebug(bool $debug = false): static
|
||||
{
|
||||
$this->debug = $debug;
|
||||
return $this;
|
||||
|
@ -525,11 +447,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the model definitions
|
||||
*
|
||||
* @param array|null $models
|
||||
* @return $this
|
||||
*/
|
||||
protected function setModels(array $models = null)
|
||||
protected function setModels(array|null $models = null): static
|
||||
{
|
||||
if ($models !== null) {
|
||||
$this->models = array_change_key_case($models);
|
||||
|
@ -540,11 +460,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the request data
|
||||
*
|
||||
* @param array|null $requestData
|
||||
* @return $this
|
||||
*/
|
||||
protected function setRequestData(array $requestData = null)
|
||||
protected function setRequestData(array|null $requestData = null): static
|
||||
{
|
||||
$defaults = [
|
||||
'query' => [],
|
||||
|
@ -558,11 +476,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the request method
|
||||
*
|
||||
* @param string|null $requestMethod
|
||||
* @return $this
|
||||
*/
|
||||
protected function setRequestMethod(string $requestMethod = null)
|
||||
protected function setRequestMethod(string|null $requestMethod = null): static
|
||||
{
|
||||
$this->requestMethod = $requestMethod ?? 'GET';
|
||||
return $this;
|
||||
|
@ -570,11 +486,9 @@ class Api
|
|||
|
||||
/**
|
||||
* Setter for the route definitions
|
||||
*
|
||||
* @param array|null $routes
|
||||
* @return $this
|
||||
*/
|
||||
protected function setRoutes(array $routes = null)
|
||||
protected function setRoutes(array|null $routes = null): static
|
||||
{
|
||||
$this->routes = $routes ?? [];
|
||||
return $this;
|
||||
|
@ -582,13 +496,8 @@ class Api
|
|||
|
||||
/**
|
||||
* Renders the API call
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @param array $requestData
|
||||
* @return mixed
|
||||
*/
|
||||
public function render(string $path, $method = 'GET', array $requestData = [])
|
||||
public function render(string $path, string $method = 'GET', array $requestData = [])
|
||||
{
|
||||
try {
|
||||
$result = $this->call($path, $method, $requestData);
|
||||
|
@ -596,13 +505,12 @@ class Api
|
|||
$result = $this->responseForException($e);
|
||||
}
|
||||
|
||||
if ($result === null) {
|
||||
$result = $this->responseFor404();
|
||||
} elseif ($result === false) {
|
||||
$result = $this->responseFor400();
|
||||
} elseif ($result === true) {
|
||||
$result = $this->responseFor200();
|
||||
}
|
||||
$result = match ($result) {
|
||||
null => $this->responseFor404(),
|
||||
false => $this->responseFor400(),
|
||||
true => $this->responseFor200(),
|
||||
default => $result
|
||||
};
|
||||
|
||||
if (is_array($result) === false) {
|
||||
return $result;
|
||||
|
@ -628,8 +536,6 @@ class Api
|
|||
/**
|
||||
* Returns a 200 - ok
|
||||
* response array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function responseFor200(): array
|
||||
{
|
||||
|
@ -643,8 +549,6 @@ class Api
|
|||
/**
|
||||
* Returns a 400 - bad request
|
||||
* response array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function responseFor400(): array
|
||||
{
|
||||
|
@ -658,8 +562,6 @@ class Api
|
|||
/**
|
||||
* Returns a 404 - not found
|
||||
* response array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function responseFor404(): array
|
||||
{
|
||||
|
@ -674,9 +576,6 @@ class Api
|
|||
* Creates the response array for
|
||||
* an exception. Kirby exceptions will
|
||||
* have more information
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return array
|
||||
*/
|
||||
public function responseForException(Throwable $e): array
|
||||
{
|
||||
|
@ -696,11 +595,11 @@ class Api
|
|||
'file' => F::relativepath($e->getFile(), $docRoot),
|
||||
'line' => $e->getLine(),
|
||||
'details' => [],
|
||||
'route' => $this->route ? $this->route->pattern() : null
|
||||
'route' => $this->route?->pattern()
|
||||
];
|
||||
|
||||
// extend the information for Kirby Exceptions
|
||||
if (is_a($e, 'Kirby\Exception\Exception') === true) {
|
||||
if ($e instanceof ExceptionException) {
|
||||
$result['key'] = $e->getKey();
|
||||
$result['details'] = $e->getDetails();
|
||||
$result['code'] = $e->getHttpCode();
|
||||
|
@ -726,14 +625,9 @@ class Api
|
|||
* move_uploaded_file() not working with unit test
|
||||
* Added debug parameter for testing purposes as we did in the Email class
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param bool $single
|
||||
* @param bool $debug
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception If request has no files or there was an error with the upload
|
||||
*/
|
||||
public function upload(Closure $callback, $single = false, $debug = false): array
|
||||
public function upload(Closure $callback, bool $single = false, bool $debug = false): array
|
||||
{
|
||||
$trials = 0;
|
||||
$uploads = [];
|
||||
|
@ -757,13 +651,16 @@ class Api
|
|||
|
||||
if ($postMaxSize < $uploadMaxFileSize) {
|
||||
throw new Exception(I18n::translate('upload.error.iniPostSize'));
|
||||
} else {
|
||||
throw new Exception(I18n::translate('upload.error.noFiles'));
|
||||
}
|
||||
|
||||
throw new Exception(I18n::translate('upload.error.noFiles'));
|
||||
}
|
||||
|
||||
foreach ($files as $upload) {
|
||||
if (isset($upload['tmp_name']) === false && is_array($upload)) {
|
||||
if (
|
||||
isset($upload['tmp_name']) === false &&
|
||||
is_array($upload) === true
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -780,7 +677,10 @@ class Api
|
|||
|
||||
// try to detect the correct mime and add the extension
|
||||
// accordingly. This will avoid .tmp filenames
|
||||
if (empty($extension) === true || in_array($extension, ['tmp', 'temp'])) {
|
||||
if (
|
||||
empty($extension) === true ||
|
||||
in_array($extension, ['tmp', 'temp']) === true
|
||||
) {
|
||||
$mime = F::mime($upload['tmp_name']);
|
||||
$extension = F::mimeToExtension($mime);
|
||||
$filename = F::name($upload['name']) . '.' . $extension;
|
||||
|
@ -792,7 +692,10 @@ class Api
|
|||
|
||||
// move the file to a location including the extension,
|
||||
// for better mime detection
|
||||
if ($debug === false && move_uploaded_file($upload['tmp_name'], $source) === false) {
|
||||
if (
|
||||
$debug === false &&
|
||||
move_uploaded_file($upload['tmp_name'], $source) === false
|
||||
) {
|
||||
throw new Exception(I18n::translate('upload.error.cantMove'));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Kirby\Api;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
|
@ -19,48 +20,27 @@ use Kirby\Toolkit\Str;
|
|||
*/
|
||||
class Collection
|
||||
{
|
||||
/**
|
||||
* @var \Kirby\Api\Api
|
||||
*/
|
||||
protected $api;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected Api $api;
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected $select;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Collection constructor
|
||||
*
|
||||
* @param \Kirby\Api\Api $api
|
||||
* @param mixed|null $data
|
||||
* @param array $schema
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(Api $api, $data, array $schema)
|
||||
{
|
||||
$this->api = $api;
|
||||
$this->data = $data;
|
||||
$this->model = $schema['model'] ?? null;
|
||||
$this->view = $schema['view'] ?? null;
|
||||
$this->api = $api;
|
||||
$this->data = $data;
|
||||
$this->model = $schema['model'] ?? null;
|
||||
$this->select = null;
|
||||
$this->view = $schema['view'] ?? null;
|
||||
|
||||
if ($data === null) {
|
||||
if (is_a($schema['default'] ?? null, 'Closure') === false) {
|
||||
if (($schema['default'] ?? null) instanceof Closure === false) {
|
||||
throw new Exception('Missing collection data');
|
||||
}
|
||||
|
||||
|
@ -69,18 +49,17 @@ class Collection
|
|||
|
||||
if (
|
||||
isset($schema['type']) === true &&
|
||||
is_a($this->data, $schema['type']) === false
|
||||
$this->data instanceof $schema['type'] === false
|
||||
) {
|
||||
throw new Exception('Invalid collection type');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|null $keys
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function select($keys = null)
|
||||
public function select($keys = null): static
|
||||
{
|
||||
if ($keys === false) {
|
||||
return $this;
|
||||
|
@ -99,7 +78,6 @@ class Collection
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
@ -125,7 +103,6 @@ class Collection
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
@ -167,10 +144,9 @@ class Collection
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $view
|
||||
* @return $this
|
||||
*/
|
||||
public function view(string $view)
|
||||
public function view(string $view): static
|
||||
{
|
||||
$this->view = $view;
|
||||
return $this;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Kirby\Api;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
|
@ -21,37 +22,15 @@ use Kirby\Toolkit\Str;
|
|||
*/
|
||||
class Model
|
||||
{
|
||||
/**
|
||||
* @var \Kirby\Api\Api
|
||||
*/
|
||||
protected $api;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected Api $api;
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
protected $fields;
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
protected $select;
|
||||
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
protected $views;
|
||||
|
||||
/**
|
||||
* Model constructor
|
||||
*
|
||||
* @param \Kirby\Api\Api $api
|
||||
* @param mixed $data
|
||||
* @param array $schema
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(Api $api, $data, array $schema)
|
||||
|
@ -62,12 +41,15 @@ class Model
|
|||
$this->select = $schema['select'] ?? null;
|
||||
$this->views = $schema['views'] ?? [];
|
||||
|
||||
if ($this->select === null && array_key_exists('default', $this->views)) {
|
||||
if (
|
||||
$this->select === null &&
|
||||
array_key_exists('default', $this->views)
|
||||
) {
|
||||
$this->view('default');
|
||||
}
|
||||
|
||||
if ($data === null) {
|
||||
if (is_a($schema['default'] ?? null, 'Closure') === false) {
|
||||
if (($schema['default'] ?? null) instanceof Closure === false) {
|
||||
throw new Exception('Missing model data');
|
||||
}
|
||||
|
||||
|
@ -76,18 +58,17 @@ class Model
|
|||
|
||||
if (
|
||||
isset($schema['type']) === true &&
|
||||
is_a($this->data, $schema['type']) === false
|
||||
$this->data instanceof $schema['type'] === false
|
||||
) {
|
||||
throw new Exception(sprintf('Invalid model type "%s" expected: "%s"', get_class($this->data), $schema['type']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $keys
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function select($keys = null)
|
||||
public function select($keys = null): static
|
||||
{
|
||||
if ($keys === false) {
|
||||
return $this;
|
||||
|
@ -106,7 +87,6 @@ class Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function selection(): array
|
||||
|
@ -153,7 +133,6 @@ class Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
@ -163,7 +142,10 @@ class Model
|
|||
$result = [];
|
||||
|
||||
foreach ($this->fields as $key => $resolver) {
|
||||
if (array_key_exists($key, $select) === false || is_a($resolver, 'Closure') === false) {
|
||||
if (
|
||||
array_key_exists($key, $select) === false ||
|
||||
$resolver instanceof Closure === false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -174,8 +156,8 @@ class Model
|
|||
}
|
||||
|
||||
if (
|
||||
is_a($value, 'Kirby\Api\Collection') === true ||
|
||||
is_a($value, 'Kirby\Api\Model') === true
|
||||
$value instanceof Collection ||
|
||||
$value instanceof self
|
||||
) {
|
||||
$selection = $select[$key];
|
||||
|
||||
|
@ -199,7 +181,6 @@ class Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Kirby\Exception\NotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
@ -224,11 +205,10 @@ class Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function view(string $name)
|
||||
public function view(string $name): static
|
||||
{
|
||||
if ($name === 'any') {
|
||||
return $this->select(null);
|
||||
|
|
90
kirby/src/Blueprint/Collection.php
Normal file
90
kirby/src/Blueprint/Collection.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\Collection as BaseCollection;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Toolkit\A;
|
||||
use TypeError;
|
||||
|
||||
/**
|
||||
* Typed collection
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Collection extends BaseCollection
|
||||
{
|
||||
/**
|
||||
* The expected object type
|
||||
*/
|
||||
public const TYPE = Node::class;
|
||||
|
||||
public function __construct(array $objects = [])
|
||||
{
|
||||
foreach ($objects as $object) {
|
||||
$this->__set($object->id, $object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Kirby Collection class only shows the key to
|
||||
* avoid huge tress with dump, but for the blueprint
|
||||
* collections this is really not useful
|
||||
*/
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
return A::map($this->data, fn ($item) => (array)$item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the type of every item that is being
|
||||
* added to the collection. They cneed to have
|
||||
* the class defined by static::TYPE.
|
||||
*/
|
||||
public function __set(string $key, $value): void
|
||||
{
|
||||
if (
|
||||
is_a($value, static::TYPE) === false
|
||||
) {
|
||||
throw new TypeError('Each value in the collection must be an instance of ' . static::TYPE);
|
||||
}
|
||||
|
||||
parent::__set($key, $value);
|
||||
}
|
||||
|
||||
public static function factory(array $items)
|
||||
{
|
||||
$collection = new static();
|
||||
$className = static::TYPE;
|
||||
|
||||
foreach ($items as $id => $item) {
|
||||
if (is_array($item) === true) {
|
||||
$item['id'] ??= $id;
|
||||
$item = $className::factory($item);
|
||||
$collection->__set($item->id, $item);
|
||||
} else {
|
||||
$collection->__set($id, $className::factory($item));
|
||||
}
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
public function render(ModelWithContent $model)
|
||||
{
|
||||
$props = [];
|
||||
|
||||
foreach ($this->data as $key => $item) {
|
||||
$props[$key] = $item->render($model);
|
||||
}
|
||||
|
||||
return $props;
|
||||
}
|
||||
}
|
75
kirby/src/Blueprint/Config.php
Normal file
75
kirby/src/Blueprint/Config.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Closure;
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Data\Yaml;
|
||||
use Kirby\Exception\NotFoundException;
|
||||
use Kirby\Filesystem\F;
|
||||
|
||||
/**
|
||||
* Config
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
public string $file;
|
||||
public string $id;
|
||||
public string|array|Closure|null $plugin;
|
||||
public string $root;
|
||||
|
||||
public function __construct(
|
||||
public string $path
|
||||
) {
|
||||
$kirby = App::instance();
|
||||
|
||||
$this->id = basename($this->path);
|
||||
$this->root = $kirby->root('blueprints');
|
||||
$this->file = $this->root . '/' . $this->path . '.yml';
|
||||
$this->plugin = $kirby->extension('blueprints', $this->path);
|
||||
}
|
||||
|
||||
public function read(): array
|
||||
{
|
||||
if (F::exists($this->file, $this->root) === true) {
|
||||
return $this->unpack($this->file);
|
||||
}
|
||||
|
||||
return $this->unpack($this->plugin);
|
||||
}
|
||||
|
||||
public function write(array $props): bool
|
||||
{
|
||||
return Yaml::write($this->file, $props);
|
||||
}
|
||||
|
||||
public function unpack(string|array|Closure|null $extension): array
|
||||
{
|
||||
return match (true) {
|
||||
// extension does not exist
|
||||
is_null($extension)
|
||||
=> throw new NotFoundException('"' . $this->path . '" could not be found'),
|
||||
|
||||
// extension is stored as a file path
|
||||
is_string($extension)
|
||||
=> Yaml::read($extension),
|
||||
|
||||
// extension is a callback to be resolved
|
||||
is_callable($extension)
|
||||
=> $extension(App::instance()),
|
||||
|
||||
// extension is already defined as array
|
||||
default
|
||||
=> $extension
|
||||
};
|
||||
}
|
||||
}
|
65
kirby/src/Blueprint/Extension.php
Normal file
65
kirby/src/Blueprint/Extension.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
/**
|
||||
* Extension
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Extension
|
||||
{
|
||||
public function __construct(
|
||||
public string $path
|
||||
) {
|
||||
}
|
||||
|
||||
public static function apply(array $props): array
|
||||
{
|
||||
if (isset($props['extends']) === false) {
|
||||
return $props;
|
||||
}
|
||||
|
||||
// already extended
|
||||
if (is_a($props['extends'], Extension::class) === true) {
|
||||
return $props;
|
||||
}
|
||||
|
||||
$extension = new static($props['extends']);
|
||||
return $extension->extend($props);
|
||||
}
|
||||
|
||||
public function extend(array $props): array
|
||||
{
|
||||
$props = array_replace_recursive(
|
||||
$this->read(),
|
||||
$props
|
||||
);
|
||||
|
||||
$props['extends'] = $this;
|
||||
|
||||
return $props;
|
||||
}
|
||||
|
||||
public static function factory(string|array $path): static
|
||||
{
|
||||
if (is_string($path) === true) {
|
||||
return new static(path: $path);
|
||||
}
|
||||
|
||||
return new static(...$path);
|
||||
}
|
||||
|
||||
public function read(): array
|
||||
{
|
||||
$config = new Config($this->path);
|
||||
return $config->read();
|
||||
}
|
||||
}
|
119
kirby/src/Blueprint/Factory.php
Normal file
119
kirby/src/Blueprint/Factory.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use ReflectionException;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionProperty;
|
||||
use ReflectionUnionType;
|
||||
|
||||
/**
|
||||
* Factory
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* Resolves the properties by
|
||||
* applying a map of factories (propName => class)
|
||||
*/
|
||||
public static function apply(array $properties, array $factories): array
|
||||
{
|
||||
foreach ($factories as $property => $class) {
|
||||
// skip non-existing properties, empty properties
|
||||
// or properties that are matching objects
|
||||
if (
|
||||
isset($properties[$property]) === false ||
|
||||
$properties[$property] === null ||
|
||||
is_a($properties[$property], $class) === true
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$properties[$property] = $class::factory($properties[$property]);
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
public static function forNamedType(ReflectionNamedType|null $type, $value)
|
||||
{
|
||||
// get the class name for the single type
|
||||
$className = $type->getName();
|
||||
|
||||
// check if there's a factory for the value
|
||||
if (method_exists($className, 'factory') === true) {
|
||||
return $className::factory($value);
|
||||
}
|
||||
|
||||
// try to assign the value directly and trust
|
||||
// in PHP's type system.
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function forProperties(string $class, array $properties): array
|
||||
{
|
||||
foreach ($properties as $property => $value) {
|
||||
try {
|
||||
$properties[$property] = static::forProperty($class, $property, $value);
|
||||
} catch (ReflectionException $e) {
|
||||
// the property does not exist
|
||||
unset($properties[$property]);
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
public static function forProperty(string $class, string $property, $value)
|
||||
{
|
||||
if (is_null($value) === true) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// instantly assign objects
|
||||
// PHP's type system will find issues automatically
|
||||
if (is_object($value) === true) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// get the type for the property
|
||||
$reflection = new ReflectionProperty($class, $property);
|
||||
$propType = $reflection->getType();
|
||||
|
||||
// no type given
|
||||
if ($propType === null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// union types
|
||||
if (is_a($propType, ReflectionUnionType::class) === true) {
|
||||
return static::forUnionType($propType, $value);
|
||||
}
|
||||
|
||||
return static::forNamedType($propType, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* For properties with union types,
|
||||
* the first named type is used to create
|
||||
* the factory or pass a built-in value
|
||||
*/
|
||||
public static function forUnionType(ReflectionUnionType $type, $value)
|
||||
{
|
||||
return static::forNamedType($type->getTypes()[0], $value);
|
||||
}
|
||||
|
||||
public static function make(string $class, array $properties): object
|
||||
{
|
||||
return new $class(...static::forProperties($class, $properties));
|
||||
}
|
||||
}
|
118
kirby/src/Blueprint/Node.php
Normal file
118
kirby/src/Blueprint/Node.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
|
||||
/**
|
||||
* A node of the blueprint
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
public const TYPE = 'node';
|
||||
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public Extension|null $extends = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic getter for properties
|
||||
*/
|
||||
public function __call(string $name, array $args)
|
||||
{
|
||||
$this->defaults();
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply default values
|
||||
*/
|
||||
public function defaults(): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance by a set of array properties.
|
||||
*/
|
||||
public static function factory(array $props): static
|
||||
{
|
||||
$props = Extension::apply($props);
|
||||
$props = static::polyfill($props);
|
||||
return Factory::make(static::class, $props);
|
||||
}
|
||||
|
||||
|
||||
public static function load(string|array $props): static
|
||||
{
|
||||
// load by path
|
||||
if (is_string($props) === true) {
|
||||
$props = static::loadProps($props);
|
||||
}
|
||||
|
||||
return static::factory($props);
|
||||
}
|
||||
|
||||
public static function loadProps(string $path): array
|
||||
{
|
||||
$config = new Config($path);
|
||||
$props = $config->read();
|
||||
|
||||
// add the id if it's not set yet
|
||||
$props['id'] ??= basename($path);
|
||||
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional method that runs before static::factory sends
|
||||
* its properties to the instance. This is perfect to clean
|
||||
* up props or keep deprecated props compatible.
|
||||
*/
|
||||
public static function polyfill(array $props): array
|
||||
{
|
||||
return $props;
|
||||
}
|
||||
|
||||
public function render(ModelWithContent $model)
|
||||
{
|
||||
// apply default values
|
||||
$this->defaults();
|
||||
|
||||
$array = [];
|
||||
|
||||
// go through all public properties
|
||||
foreach (get_object_vars($this) as $key => $value) {
|
||||
if (is_object($value) === false && is_resource($value) === false) {
|
||||
$array[$key] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method_exists($value, 'render') === true) {
|
||||
$array[$key] = $value->render($model);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Universal setter for properties
|
||||
*/
|
||||
public function set(string $property, $value): static
|
||||
{
|
||||
$this->$property = Factory::forProperty(static::class, $property, $value);
|
||||
return $this;
|
||||
}
|
||||
}
|
44
kirby/src/Blueprint/NodeI18n.php
Normal file
44
kirby/src/Blueprint/NodeI18n.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Translatable node property
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class NodeI18n extends NodeProperty
|
||||
{
|
||||
public function __construct(
|
||||
public array $translations,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function factory($value = null): static|null
|
||||
{
|
||||
if ($value === false || $value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_array($value) === false) {
|
||||
$value = ['en' => $value];
|
||||
}
|
||||
|
||||
return new static($value);
|
||||
}
|
||||
|
||||
public function render(ModelWithContent $model): string|null
|
||||
{
|
||||
return I18n::translate($this->translations, $this->translations);
|
||||
}
|
||||
}
|
27
kirby/src/Blueprint/NodeIcon.php
Normal file
27
kirby/src/Blueprint/NodeIcon.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
/**
|
||||
* Custom emoji or icon from the Kirby iconset
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class NodeIcon extends NodeString
|
||||
{
|
||||
public static function field()
|
||||
{
|
||||
$field = parent::field();
|
||||
$field->id = 'icon';
|
||||
$field->label->translations = ['en' => 'Icon'];
|
||||
|
||||
return $field;
|
||||
}
|
||||
}
|
27
kirby/src/Blueprint/NodeProperty.php
Normal file
27
kirby/src/Blueprint/NodeProperty.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
|
||||
/**
|
||||
* Represents a property for a node
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class NodeProperty
|
||||
{
|
||||
abstract public static function factory($value = null): static|null;
|
||||
|
||||
public function render(ModelWithContent $model)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
39
kirby/src/Blueprint/NodeString.php
Normal file
39
kirby/src/Blueprint/NodeString.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
|
||||
/**
|
||||
* Simple string blueprint node
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class NodeString extends NodeProperty
|
||||
{
|
||||
public function __construct(
|
||||
public string $value,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function factory($value = null): static|null
|
||||
{
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return new static($value);
|
||||
}
|
||||
|
||||
public function render(ModelWithContent $model): string|null
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
30
kirby/src/Blueprint/NodeText.php
Normal file
30
kirby/src/Blueprint/NodeText.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Blueprint;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
|
||||
/**
|
||||
* The text node is translatable
|
||||
* and will parse query template strings
|
||||
*
|
||||
* @package Kirby Blueprint
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*
|
||||
* // TODO: include in test coverage in 3.9
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class NodeText extends NodeI18n
|
||||
{
|
||||
public function render(ModelWithContent $model): ?string
|
||||
{
|
||||
if ($text = parent::render($model)) {
|
||||
return $model->toSafeString($text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
|
@ -15,11 +15,17 @@ use APCUIterator;
|
|||
*/
|
||||
class ApcuCache extends Cache
|
||||
{
|
||||
/**
|
||||
* Returns whether the cache is ready to
|
||||
* store values
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return apcu_enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an item exists in the cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $key): bool
|
||||
{
|
||||
|
@ -29,24 +35,19 @@ class ApcuCache extends Cache
|
|||
/**
|
||||
* Flushes the entire cache and returns
|
||||
* whether the operation was successful
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush(): bool
|
||||
{
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
return apcu_delete(new APCUIterator('!^' . preg_quote($this->options['prefix']) . '!'));
|
||||
} else {
|
||||
return apcu_clear_cache();
|
||||
}
|
||||
|
||||
return apcu_clear_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the cache and returns
|
||||
* whether the operation was successful
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function remove(string $key): bool
|
||||
{
|
||||
|
@ -56,13 +57,11 @@ class ApcuCache extends Cache
|
|||
/**
|
||||
* Internal method to retrieve the raw cache value;
|
||||
* needs to return a Value object or null if not found
|
||||
*
|
||||
* @param string $key
|
||||
* @return \Kirby\Cache\Value|null
|
||||
*/
|
||||
public function retrieve(string $key)
|
||||
public function retrieve(string $key): Value|null
|
||||
{
|
||||
return Value::fromJson(apcu_fetch($this->key($key)));
|
||||
$value = apcu_fetch($this->key($key));
|
||||
return Value::fromJson($value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,14 +72,12 @@ class ApcuCache extends Cache
|
|||
* // put an item in the cache for 15 minutes
|
||||
* $cache->set('value', 'my value', 15);
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $minutes
|
||||
* @return bool
|
||||
*/
|
||||
public function set(string $key, $value, int $minutes = 0): bool
|
||||
{
|
||||
return apcu_store($this->key($key), (new Value($value, $minutes))->toJson(), $this->expiration($minutes));
|
||||
$key = $this->key($key);
|
||||
$value = (new Value($value, $minutes))->toJson();
|
||||
$expires = $this->expiration($minutes);
|
||||
return apcu_store($key, $value, $expires);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Kirby\Cache;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* Cache foundation
|
||||
* This abstract class is used as
|
||||
|
@ -18,14 +20,11 @@ abstract class Cache
|
|||
{
|
||||
/**
|
||||
* Stores all options for the driver
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
protected array $options = [];
|
||||
|
||||
/**
|
||||
* Sets all parameters which are needed to connect to the cache storage
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
|
@ -33,87 +32,47 @@ abstract class Cache
|
|||
}
|
||||
|
||||
/**
|
||||
* Writes an item to the cache for a given number of minutes and
|
||||
* returns whether the operation was successful;
|
||||
* this needs to be defined by the driver
|
||||
*
|
||||
* <code>
|
||||
* // put an item in the cache for 15 minutes
|
||||
* $cache->set('value', 'my value', 15);
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $minutes
|
||||
* @return bool
|
||||
* Checks when the cache has been created;
|
||||
* returns the creation timestamp on success
|
||||
* and false if the item does not exist
|
||||
*/
|
||||
abstract public function set(string $key, $value, int $minutes = 0): bool;
|
||||
|
||||
/**
|
||||
* Adds the prefix to the key if given
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function key(string $key): string
|
||||
public function created(string $key): int|false
|
||||
{
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
$key = $this->options['prefix'] . '/' . $key;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to retrieve the raw cache value;
|
||||
* needs to return a Value object or null if not found;
|
||||
* this needs to be defined by the driver
|
||||
*
|
||||
* @param string $key
|
||||
* @return \Kirby\Cache\Value|null
|
||||
*/
|
||||
abstract public function retrieve(string $key);
|
||||
|
||||
/**
|
||||
* Gets an item from the cache
|
||||
*
|
||||
* <code>
|
||||
* // get an item from the cache driver
|
||||
* $value = $cache->get('value');
|
||||
*
|
||||
* // return a default value if the requested item isn't cached
|
||||
* $value = $cache->get('value', 'default value');
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string $key, $default = null)
|
||||
{
|
||||
// get the Value
|
||||
// get the Value object
|
||||
$value = $this->retrieve($key);
|
||||
|
||||
// check for a valid cache value
|
||||
if (!is_a($value, 'Kirby\Cache\Value')) {
|
||||
return $default;
|
||||
// check for a valid Value object
|
||||
if ($value instanceof Value === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the item if it is expired
|
||||
if ($value->expires() > 0 && time() >= $value->expires()) {
|
||||
$this->remove($key);
|
||||
return $default;
|
||||
}
|
||||
|
||||
// return the pure value
|
||||
return $value->value();
|
||||
// return the expires timestamp
|
||||
return $value->created();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the cache is ready to
|
||||
* store values
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
// TODO: Make this method abstract in a future
|
||||
// release to ensure that cache drivers override it;
|
||||
// until then, we assume that the cache is enabled
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an item exists in the cache
|
||||
*/
|
||||
public function exists(string $key): bool
|
||||
{
|
||||
return $this->expired($key) === false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the expiration timestamp
|
||||
*
|
||||
* @param int $minutes
|
||||
* @return int
|
||||
*/
|
||||
protected function expiration(int $minutes = 0): int
|
||||
{
|
||||
|
@ -130,17 +89,14 @@ abstract class Cache
|
|||
* Checks when an item in the cache expires;
|
||||
* returns the expiry timestamp on success, null if the
|
||||
* item never expires and false if the item does not exist
|
||||
*
|
||||
* @param string $key
|
||||
* @return int|null|false
|
||||
*/
|
||||
public function expires(string $key)
|
||||
public function expires(string $key): int|false|null
|
||||
{
|
||||
// get the Value object
|
||||
$value = $this->retrieve($key);
|
||||
|
||||
// check for a valid Value object
|
||||
if (!is_a($value, 'Kirby\Cache\Value')) {
|
||||
if ($value instanceof Value === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,9 +106,6 @@ abstract class Cache
|
|||
|
||||
/**
|
||||
* Checks if an item in the cache is expired
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function expired(string $key): bool
|
||||
{
|
||||
|
@ -160,83 +113,126 @@ abstract class Cache
|
|||
|
||||
if ($expires === null) {
|
||||
return false;
|
||||
} elseif (!is_int($expires)) {
|
||||
return true;
|
||||
} else {
|
||||
return time() >= $expires;
|
||||
}
|
||||
|
||||
if (is_int($expires) === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return time() >= $expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks when the cache has been created;
|
||||
* returns the creation timestamp on success
|
||||
* and false if the item does not exist
|
||||
*
|
||||
* @param string $key
|
||||
* @return int|false
|
||||
* Flushes the entire cache and returns
|
||||
* whether the operation was successful;
|
||||
* this needs to be defined by the driver
|
||||
*/
|
||||
public function created(string $key)
|
||||
abstract public function flush(): bool;
|
||||
|
||||
/**
|
||||
* Gets an item from the cache
|
||||
*
|
||||
* <code>
|
||||
* // get an item from the cache driver
|
||||
* $value = $cache->get('value');
|
||||
*
|
||||
* // return a default value if the requested item isn't cached
|
||||
* $value = $cache->get('value', 'default value');
|
||||
* </code>
|
||||
*/
|
||||
public function get(string $key, $default = null)
|
||||
{
|
||||
// get the Value object
|
||||
// get the Value
|
||||
$value = $this->retrieve($key);
|
||||
|
||||
// check for a valid Value object
|
||||
if (!is_a($value, 'Kirby\Cache\Value')) {
|
||||
return false;
|
||||
// check for a valid cache value
|
||||
if ($value instanceof Value === false) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
// return the expires timestamp
|
||||
return $value->created();
|
||||
// remove the item if it is expired
|
||||
if ($value->expires() > 0 && time() >= $value->expires()) {
|
||||
$this->remove($key);
|
||||
return $default;
|
||||
}
|
||||
|
||||
// return the pure value
|
||||
return $value->value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value by either getting it from the cache
|
||||
* or via the callback function which then is stored in
|
||||
* the cache for future retrieval. This method cannot be
|
||||
* used for `null` as value to be cached.
|
||||
* @since 3.8.0
|
||||
*/
|
||||
public function getOrSet(
|
||||
string $key,
|
||||
Closure $result,
|
||||
int $minutes = 0
|
||||
) {
|
||||
$value = $this->get($key);
|
||||
$result = $value ?? $result();
|
||||
|
||||
if ($value === null) {
|
||||
$this->set($key, $result, $minutes);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the prefix to the key if given
|
||||
*/
|
||||
protected function key(string $key): string
|
||||
{
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
$key = $this->options['prefix'] . '/' . $key;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternate version for Cache::created($key)
|
||||
*
|
||||
* @param string $key
|
||||
* @return int|false
|
||||
*/
|
||||
public function modified(string $key)
|
||||
public function modified(string $key): int|false
|
||||
{
|
||||
return static::created($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an item exists in the cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
* Returns all passed cache options
|
||||
*/
|
||||
public function exists(string $key): bool
|
||||
public function options(): array
|
||||
{
|
||||
return $this->expired($key) === false;
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the cache and returns
|
||||
* whether the operation was successful;
|
||||
* this needs to be defined by the driver
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function remove(string $key): bool;
|
||||
|
||||
/**
|
||||
* Flushes the entire cache and returns
|
||||
* whether the operation was successful;
|
||||
* Internal method to retrieve the raw cache value;
|
||||
* needs to return a Value object or null if not found;
|
||||
* this needs to be defined by the driver
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function flush(): bool;
|
||||
abstract public function retrieve(string $key): Value|null;
|
||||
|
||||
/**
|
||||
* Returns all passed cache options
|
||||
* Writes an item to the cache for a given number of minutes and
|
||||
* returns whether the operation was successful;
|
||||
* this needs to be defined by the driver
|
||||
*
|
||||
* @return array
|
||||
* <code>
|
||||
* // put an item in the cache for 15 minutes
|
||||
* $cache->set('value', 'my value', 15);
|
||||
* </code>
|
||||
*/
|
||||
public function options(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
abstract public function set(string $key, $value, int $minutes = 0): bool;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,8 @@ class FileCache extends Cache
|
|||
{
|
||||
/**
|
||||
* Full root including prefix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
protected string $root;
|
||||
|
||||
/**
|
||||
* Sets all parameters which are needed for the file cache
|
||||
|
@ -44,6 +42,7 @@ class FileCache extends Cache
|
|||
|
||||
// build the full root including prefix
|
||||
$this->root = $this->options['root'];
|
||||
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
$this->root .= '/' . $this->options['prefix'];
|
||||
}
|
||||
|
@ -52,10 +51,17 @@ class FileCache extends Cache
|
|||
Dir::make($this->root, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the cache is ready to
|
||||
* store values
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return is_writable($this->root) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full root including prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function root(): string
|
||||
{
|
||||
|
@ -64,9 +70,6 @@ class FileCache extends Cache
|
|||
|
||||
/**
|
||||
* Returns the full path to a file for a given key
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function file(string $key): string
|
||||
{
|
||||
|
@ -108,9 +111,9 @@ class FileCache extends Cache
|
|||
|
||||
if (isset($this->options['extension'])) {
|
||||
return $file . '.' . $this->options['extension'];
|
||||
} else {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,11 +124,6 @@ class FileCache extends Cache
|
|||
* // put an item in the cache for 15 minutes
|
||||
* $cache->set('value', 'my value', 15);
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $minutes
|
||||
* @return bool
|
||||
*/
|
||||
public function set(string $key, $value, int $minutes = 0): bool
|
||||
{
|
||||
|
@ -137,11 +135,8 @@ class FileCache extends Cache
|
|||
/**
|
||||
* Internal method to retrieve the raw cache value;
|
||||
* needs to return a Value object or null if not found
|
||||
*
|
||||
* @param string $key
|
||||
* @return \Kirby\Cache\Value|null
|
||||
*/
|
||||
public function retrieve(string $key)
|
||||
public function retrieve(string $key): Value|null
|
||||
{
|
||||
$file = $this->file($key);
|
||||
$value = F::read($file);
|
||||
|
@ -153,11 +148,8 @@ class FileCache extends Cache
|
|||
* Checks when the cache has been created;
|
||||
* returns the creation timestamp on success
|
||||
* and false if the item does not exist
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function created(string $key)
|
||||
public function created(string $key): int|false
|
||||
{
|
||||
// use the modification timestamp
|
||||
// as indicator when the cache has been created/overwritten
|
||||
|
@ -165,15 +157,12 @@ class FileCache extends Cache
|
|||
|
||||
// get the file for this cache key
|
||||
$file = $this->file($key);
|
||||
return file_exists($file) ? filemtime($this->file($key)) : false;
|
||||
return file_exists($file) ? filemtime($file) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the cache and returns
|
||||
* whether the operation was successful
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function remove(string $key): bool
|
||||
{
|
||||
|
@ -190,9 +179,6 @@ class FileCache extends Cache
|
|||
/**
|
||||
* Removes empty directories safely by checking each directory
|
||||
* up to the root directory
|
||||
*
|
||||
* @param string $dir
|
||||
* @return void
|
||||
*/
|
||||
protected function removeEmptyDirectories(string $dir): void
|
||||
{
|
||||
|
@ -202,7 +188,13 @@ class FileCache extends Cache
|
|||
|
||||
// checks all directory segments until reaching the root directory
|
||||
while (Str::startsWith($dir, $this->root()) === true && $dir !== $this->root()) {
|
||||
$files = array_diff(scandir($dir) ?? [], ['.', '..']);
|
||||
$files = scandir($dir);
|
||||
|
||||
if ($files === false) {
|
||||
$files = []; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$files = array_diff($files, ['.', '..']);
|
||||
|
||||
if (empty($files) === true && Dir::remove($dir) === true) {
|
||||
// continue with the next level up
|
||||
|
@ -212,7 +204,7 @@ class FileCache extends Cache
|
|||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) { // @codeCoverageIgnore
|
||||
} catch (Exception) { // @codeCoverageIgnore
|
||||
// silently stops the process
|
||||
}
|
||||
}
|
||||
|
@ -220,12 +212,13 @@ class FileCache extends Cache
|
|||
/**
|
||||
* Flushes the entire cache and returns
|
||||
* whether the operation was successful
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush(): bool
|
||||
{
|
||||
if (Dir::remove($this->root) === true && Dir::make($this->root) === true) {
|
||||
if (
|
||||
Dir::remove($this->root) === true &&
|
||||
Dir::make($this->root) === true
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue