(Grav GitSync) Automatic Commit from dan

This commit is contained in:
dan 2022-06-28 08:19:42 +12:00 committed by GitSync
parent 3ca0db5219
commit 9671828f28
50 changed files with 1471 additions and 892 deletions

View File

@ -0,0 +1,25 @@
---
title: 'Matrix retentions - messages & media'
published: true
date: '27-06-2022 20:13'
taxonomy:
category:
- news
tag:
- matrix
- cleanup
- server
- service
aura:
author: dan
---
"No news, no new tutorials!?" That's right!
We're working more behind the scenes at the moment and have been cleaning up the server a bit, mainly our Matrix instance. It's taking up a little of space and it was time to start doing something about it soon enough before it grew too fast. The backups were also growing rapidly, of course, so it was definitely time to do something about that.
So we looked around for projects like [synatainer](https://gitlab.com/mb-saces/synatainer/), but then the new version 1.61 of synapse came along, which also includes [media_retention](https://matrix-org.github.io/synapse/develop/usage/configuration/config_documentation.html#media_retention).
We started a poll in our [main group](https://matrix.to/#/#welcome:techsaviours.org) and we actually all chose something else, but as you can see in the picture, it was a fair decision for everyone.
After some ups and downs, we got rid of about 11 GB. Not a huge amount, but better than nothing.
We have also updated the [Privacy Policy](https://techsaviours.org/privacy-policy.html) (under Matrix users) to match the latest changes to our Matrix instance.

View File

@ -14,3 +14,4 @@ tests/_support/_generated/*
tests/cache/*
tests/error.log
/crowdin.yaml
.vscode

View File

@ -1,8 +1,16 @@
# v1.10.34
## 06/22/2022
1. [](#improved)
* Exposed `UriToMarkdown` util (`Grav.default.Utils.UriToMarkdown`) in admin, to convert links/images
1. [](#bugfix)
* Fixed `Latest Page Updates` permissions [#2294](https://github.com/getgrav/grav-plugin-admin/pull/2294)
# v1.10.33.1
## 04/25/2022
1. [](#bugfix)
* Reverted [PR#2265](https://github.com/getgrav/grav-plugin-admin/pull/2265) as it broke sections output.
* Reverted [PR#2265](https://github.com/getgrav/grav-plugin-admin/pull/2265) as it broke sections output
# v1.10.33
## 04/25/2022

View File

@ -1,7 +1,7 @@
name: Admin Panel
slug: admin
type: plugin
version: 1.10.33.1
version: 1.10.34
description: Adds an advanced administration panel to manage your site
icon: empire
author:

View File

@ -190,16 +190,16 @@
},
{
"name": "scssphp/scssphp",
"version": "v1.10.2",
"version": "v1.10.3",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
"reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46"
"reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/387f4f4abf5d99f16be16314c5ab856f81c82f46",
"reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/0f1e1516ed2412ad43e42a6a319e77624ba1f713",
"reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713",
"shasum": ""
},
"require": {
@ -258,9 +258,9 @@
],
"support": {
"issues": "https://github.com/scssphp/scssphp/issues",
"source": "https://github.com/scssphp/scssphp/tree/v1.10.2"
"source": "https://github.com/scssphp/scssphp/tree/v1.10.3"
},
"time": "2022-03-02T21:15:09+00:00"
"time": "2022-05-16T07:22:18+00:00"
}
],
"packages-dev": [
@ -425,16 +425,16 @@
},
{
"name": "codeception/phpunit-wrapper",
"version": "7.8.2",
"version": "7.8.4",
"source": {
"type": "git",
"url": "https://github.com/Codeception/phpunit-wrapper.git",
"reference": "cafed18048826790c527843f9b85e8cc79b866f1"
"reference": "dd44fc152433d27d3de03d59b4945449b3407af0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/cafed18048826790c527843f9b85e8cc79b866f1",
"reference": "cafed18048826790c527843f9b85e8cc79b866f1",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/dd44fc152433d27d3de03d59b4945449b3407af0",
"reference": "dd44fc152433d27d3de03d59b4945449b3407af0",
"shasum": ""
},
"require": {
@ -466,9 +466,9 @@
"description": "PHPUnit classes used by Codeception",
"support": {
"issues": "https://github.com/Codeception/phpunit-wrapper/issues",
"source": "https://github.com/Codeception/phpunit-wrapper/tree/7.8.2"
"source": "https://github.com/Codeception/phpunit-wrapper/tree/7.8.4"
},
"time": "2020-12-28T14:00:26+00:00"
"time": "2022-05-23T06:09:22+00:00"
},
{
"name": "codeception/stub",
@ -697,16 +697,16 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.5",
"version": "6.5.7",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
"reference": "724562fa861e21a4071c652c8a159934e4f05592"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/724562fa861e21a4071c652c8a159934e4f05592",
"reference": "724562fa861e21a4071c652c8a159934e4f05592",
"shasum": ""
},
"require": {
@ -743,10 +743,40 @@
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
@ -762,9 +792,23 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/6.5"
"source": "https://github.com/guzzle/guzzle/tree/6.5.7"
},
"time": "2020-06-16T21:01:06+00:00"
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
"type": "tidelift"
}
],
"time": "2022-06-09T21:36:50+00:00"
},
{
"name": "guzzlehttp/promises",
@ -1241,16 +1285,16 @@
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.0",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706"
"reference": "77a32518733312af16a44300404e945338981de3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706",
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
"reference": "77a32518733312af16a44300404e945338981de3",
"shasum": ""
},
"require": {
@ -1285,9 +1329,9 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0"
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
},
"time": "2022-01-04T19:58:01+00:00"
"time": "2022-03-15T21:29:03+00:00"
},
{
"name": "phpspec/prophecy",
@ -2618,16 +2662,16 @@
},
{
"name": "symfony/console",
"version": "v4.4.38",
"version": "v4.4.42",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5a50085bf5460f0c0d60a50b58388c1249826b8a"
"reference": "cce7a9f99e22937a71a16b23afa762558808d587"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5a50085bf5460f0c0d60a50b58388c1249826b8a",
"reference": "5a50085bf5460f0c0d60a50b58388c1249826b8a",
"url": "https://api.github.com/repos/symfony/console/zipball/cce7a9f99e22937a71a16b23afa762558808d587",
"reference": "cce7a9f99e22937a71a16b23afa762558808d587",
"shasum": ""
},
"require": {
@ -2688,7 +2732,7 @@
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/console/tree/v4.4.38"
"source": "https://github.com/symfony/console/tree/v4.4.42"
},
"funding": [
{
@ -2704,7 +2748,7 @@
"type": "tidelift"
}
],
"time": "2022-01-30T21:23:57+00:00"
"time": "2022-05-14T12:35:33+00:00"
},
{
"name": "symfony/css-selector",
@ -2774,16 +2818,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.0",
"version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"shasum": ""
},
"require": {
@ -2821,7 +2865,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
},
"funding": [
{
@ -2837,20 +2881,20 @@
"type": "tidelift"
}
],
"time": "2021-07-12T14:48:14+00:00"
"time": "2022-01-02T09:53:40+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v4.4.39",
"version": "v4.4.42",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "4e9215a8b533802ba84a3cc5bd3c43103e7a6dc3"
"reference": "be5a04618e5d44e71d013f177df80d3ec4b192a0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/4e9215a8b533802ba84a3cc5bd3c43103e7a6dc3",
"reference": "4e9215a8b533802ba84a3cc5bd3c43103e7a6dc3",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/be5a04618e5d44e71d013f177df80d3ec4b192a0",
"reference": "be5a04618e5d44e71d013f177df80d3ec4b192a0",
"shasum": ""
},
"require": {
@ -2895,7 +2939,7 @@
"description": "Eases DOM navigation for HTML and XML documents",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/dom-crawler/tree/v4.4.39"
"source": "https://github.com/symfony/dom-crawler/tree/v4.4.42"
},
"funding": [
{
@ -2911,20 +2955,20 @@
"type": "tidelift"
}
],
"time": "2022-02-25T10:38:15+00:00"
"time": "2022-04-30T18:34:00+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.4.37",
"version": "v4.4.42",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc"
"reference": "708e761740c16b02c86e3f0c932018a06b895d40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ccfcfb96ecce1217d7b0875a0736976bc6e63dc",
"reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/708e761740c16b02c86e3f0c932018a06b895d40",
"reference": "708e761740c16b02c86e3f0c932018a06b895d40",
"shasum": ""
},
"require": {
@ -2979,7 +3023,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v4.4.37"
"source": "https://github.com/symfony/event-dispatcher/tree/v4.4.42"
},
"funding": [
{
@ -2995,20 +3039,20 @@
"type": "tidelift"
}
],
"time": "2022-01-02T09:41:36+00:00"
"time": "2022-05-05T15:33:49+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v1.1.11",
"version": "v1.1.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c"
"reference": "1d5cd762abaa6b2a4169d3e77610193a7157129e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/01e9a4efac0ee33a05dfdf93b346f62e7d0e998c",
"reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/1d5cd762abaa6b2a4169d3e77610193a7157129e",
"reference": "1d5cd762abaa6b2a4169d3e77610193a7157129e",
"shasum": ""
},
"require": {
@ -3058,7 +3102,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.11"
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.12"
},
"funding": [
{
@ -3074,20 +3118,20 @@
"type": "tidelift"
}
],
"time": "2021-03-23T15:25:38+00:00"
"time": "2022-01-02T09:41:36+00:00"
},
{
"name": "symfony/finder",
"version": "v4.4.37",
"version": "v4.4.41",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "b17d76d7ed179f017aad646e858c90a2771af15d"
"reference": "40790bdf293b462798882ef6da72bb49a4a6633a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/b17d76d7ed179f017aad646e858c90a2771af15d",
"reference": "b17d76d7ed179f017aad646e858c90a2771af15d",
"url": "https://api.github.com/repos/symfony/finder/zipball/40790bdf293b462798882ef6da72bb49a4a6633a",
"reference": "40790bdf293b462798882ef6da72bb49a4a6633a",
"shasum": ""
},
"require": {
@ -3120,7 +3164,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v4.4.37"
"source": "https://github.com/symfony/finder/tree/v4.4.41"
},
"funding": [
{
@ -3136,20 +3180,20 @@
"type": "tidelift"
}
],
"time": "2022-01-02T09:41:36+00:00"
"time": "2022-04-14T15:36:10+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.25.0",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"shasum": ""
},
"require": {
@ -3164,7 +3208,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -3202,7 +3246,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
},
"funding": [
{
@ -3218,20 +3262,20 @@
"type": "tidelift"
}
],
"time": "2021-10-20T20:35:02+00:00"
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.25.0",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "749045c69efb97c70d25d7463abba812e91f3a44"
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44",
"reference": "749045c69efb97c70d25d7463abba812e91f3a44",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"shasum": ""
},
"require": {
@ -3245,7 +3289,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -3289,7 +3333,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
},
"funding": [
{
@ -3305,20 +3349,20 @@
"type": "tidelift"
}
],
"time": "2021-09-14T14:02:44+00:00"
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.25.0",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"shasum": ""
},
"require": {
@ -3330,7 +3374,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -3373,7 +3417,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
},
"funding": [
{
@ -3389,20 +3433,20 @@
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.25.0",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": ""
},
"require": {
@ -3417,7 +3461,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -3456,7 +3500,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
},
"funding": [
{
@ -3472,20 +3516,20 @@
"type": "tidelift"
}
],
"time": "2021-11-30T18:21:41+00:00"
"time": "2022-05-24T11:49:31+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.25.0",
"version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"shasum": ""
},
"require": {
@ -3494,7 +3538,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -3539,7 +3583,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
},
"funding": [
{
@ -3555,20 +3599,20 @@
"type": "tidelift"
}
],
"time": "2022-03-04T08:16:47+00:00"
"time": "2022-05-10T07:21:04+00:00"
},
{
"name": "symfony/process",
"version": "v4.4.37",
"version": "v4.4.41",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "b2d924e5a4cb284f293d5092b1dbf0d364cb8b67"
"reference": "9eedd60225506d56e42210a70c21bb80ca8456ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/b2d924e5a4cb284f293d5092b1dbf0d364cb8b67",
"reference": "b2d924e5a4cb284f293d5092b1dbf0d364cb8b67",
"url": "https://api.github.com/repos/symfony/process/zipball/9eedd60225506d56e42210a70c21bb80ca8456ce",
"reference": "9eedd60225506d56e42210a70c21bb80ca8456ce",
"shasum": ""
},
"require": {
@ -3601,7 +3645,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v4.4.37"
"source": "https://github.com/symfony/process/tree/v4.4.41"
},
"funding": [
{
@ -3617,26 +3661,26 @@
"type": "tidelift"
}
],
"time": "2022-01-27T17:14:04+00:00"
"time": "2022-04-04T10:19:07+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.0",
"version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
"symfony/deprecation-contracts": "^2.1|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
@ -3684,7 +3728,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
},
"funding": [
{
@ -3700,7 +3744,7 @@
"type": "tidelift"
}
],
"time": "2021-11-04T16:48:04+00:00"
"time": "2022-03-13T20:07:29+00:00"
},
{
"name": "symfony/yaml",
@ -3825,21 +3869,21 @@
},
{
"name": "webmozart/assert",
"version": "1.10.0",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"symfony/polyfill-ctype": "^1.8"
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
@ -3877,9 +3921,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2021-03-09T10:59:23+00:00"
"time": "2022-06-03T18:03:27+00:00"
}
],
"aliases": [],

View File

@ -454,8 +454,11 @@ PLUGIN_ADMIN:
IMAGES_DEBUG_HELP: "Show an overlay over images indicating the pixel depth of the image when working with retina for example"
IMAGES_LOADING: "Image loading behavior"
IMAGES_LOADING_HELP: "The loading attribute allows a browser to defer loading offscreen images and iframes until users scroll near them. loading supports three values: auto, lazy, eager"
# Removed in Grav 1.8
IMAGES_SEOFRIENDLY: "SEO-Friendly Image names"
IMAGES_SEOFRIENDLY_HELP: "When enabled, the image name is displayed first, then a smaller hash to reflect processed operations"
UPLOAD_LIMIT: "File upload limit"
UPLOAD_LIMIT_HELP: "Set maximum upload size in bytes (0 is unlimited)"
ENABLE_MEDIA_TIMESTAMP: "Enable timestamps on media"
@ -1142,3 +1145,7 @@ PLUGIN_ADMIN:
AVATAR: "Avatar Generator"
AVATAR_HELP: "Multiavatar is a locally generated avatar. Gravatar is an external service that uses your email address to pull a preconfigured Avatar remotely"
AVATAR_HASH: "NOTE: Optional Avatar custom 'hash' string"
IMAGES_TITLE: "Images"
LEGACY_MEDIA_MUTATION: "Legacy Media Manipulation Compatibility"
LEGACY_MEDIA_MUTATION_HELP: "Enable this setting only if image manipulation broke after Grav update."
BACKWARD_COMPATIBILITY: "Backward Compatibility"

View File

@ -4,6 +4,7 @@ import '@babel/polyfill';
import $ from 'jquery';
import './utils/remodal';
import 'simplebar/dist/simplebar.min.js';
import { UriToMarkdown } from './forms/fields/files.js';
import GPM, { Instance as gpm } from './utils/gpm';
import KeepAlive from './utils/keepalive';
import Updates, { Instance as updates, Notifications, Feed } from './updates';
@ -68,5 +69,5 @@ export default {
Instance: MediaFilterInstance
},
Scrollbar: { Scrollbar: { deprecated: true }, Instance: { deprecated: true } },
Utils: { request, toastr, Cookies }
Utils: { request, toastr, Cookies, UriToMarkdown }
};

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
{% if authorize(['admin.pages', 'admin.super']) %}
{% if authorize(['admin.pages.list', 'admin.pages', 'admin.super']) %}
<div id="latest">
<div class="button-bar">
<a class="button" href="{{ admin_route('/pages') }}"><i class="fa fa-fw fa-file-text-o"></i>{{ "PLUGIN_ADMIN.MANAGE_PAGES"|t }}</a>
@ -15,6 +15,4 @@
{% endfor %}
</table>
</div>
{% else %}
<div class="padding">You don't have sufficient access to view the dashboard...</div>
{% endif %}

View File

@ -193,17 +193,17 @@
},
{
"name": "scssphp/scssphp",
"version": "v1.10.2",
"version_normalized": "1.10.2.0",
"version": "v1.10.3",
"version_normalized": "1.10.3.0",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
"reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46"
"reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/387f4f4abf5d99f16be16314c5ab856f81c82f46",
"reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/0f1e1516ed2412ad43e42a6a319e77624ba1f713",
"reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713",
"shasum": ""
},
"require": {
@ -226,7 +226,7 @@
"ext-iconv": "Can be used as fallback when ext-mbstring is not available",
"ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv"
},
"time": "2022-03-02T21:15:09+00:00",
"time": "2022-05-16T07:22:18+00:00",
"bin": [
"bin/pscss"
],
@ -264,7 +264,7 @@
],
"support": {
"issues": "https://github.com/scssphp/scssphp/issues",
"source": "https://github.com/scssphp/scssphp/tree/v1.10.2"
"source": "https://github.com/scssphp/scssphp/tree/v1.10.3"
},
"install-path": "../scssphp/scssphp"
}

View File

@ -5,7 +5,7 @@
'type' => 'grav-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '5c1e6d6d52f8fc8e0540b5599e736e25ea20c446',
'reference' => '0a5b51b9e2c2eb9626b17c8b164dcfc3296ccf3c',
'name' => 'getgrav/grav-plugin-admin',
'dev' => false,
),
@ -16,7 +16,7 @@
'type' => 'grav-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '5c1e6d6d52f8fc8e0540b5599e736e25ea20c446',
'reference' => '0a5b51b9e2c2eb9626b17c8b164dcfc3296ccf3c',
'dev_requirement' => false,
),
'laminas/laminas-xml' => array(
@ -53,12 +53,12 @@
'dev_requirement' => false,
),
'scssphp/scssphp' => array(
'pretty_version' => 'v1.10.2',
'version' => '1.10.2.0',
'pretty_version' => 'v1.10.3',
'version' => '1.10.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../scssphp/scssphp',
'aliases' => array(),
'reference' => '387f4f4abf5d99f16be16314c5ab856f81c82f46',
'reference' => '0f1e1516ed2412ad43e42a6a319e77624ba1f713',
'dev_requirement' => false,
),
'symfony/polyfill-php72' => array(

View File

@ -2350,9 +2350,9 @@ class Compiler
}
/**
* Compile children and throw exception if unexpected `@return`
* Compile children and throw exception if unexpected at-return
*
* @param array $stms
* @param array[] $stms
* @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
* @param \ScssPhp\ScssPhp\Block $selfParent
* @param string $traceName
@ -2367,13 +2367,13 @@ class Compiler
foreach ($stms as $stm) {
if ($selfParent && isset($stm[1]) && \is_object($stm[1]) && $stm[1] instanceof Block) {
$oldSelfParent = $stm[1]->selfParent;
$stm[1]->selfParent = $selfParent;
$ret = $this->compileChild($stm, $out);
$stm[1]->selfParent = null;
$stm[1]->selfParent = $oldSelfParent;
} elseif ($selfParent && \in_array($stm[0], [Type::T_INCLUDE, Type::T_EXTEND])) {
$stm['selfParent'] = $selfParent;
$ret = $this->compileChild($stm, $out);
unset($stm['selfParent']);
} else {
$ret = $this->compileChild($stm, $out);
}

View File

@ -14,6 +14,8 @@ namespace ScssPhp\ScssPhp\Logger;
/**
* A logger that silently ignores all messages.
*
* @final
*/
class QuietLogger implements LoggerInterface
{

View File

@ -14,6 +14,8 @@ namespace ScssPhp\ScssPhp\Logger;
/**
* A logger that prints to a PHP stream (for instance stderr)
*
* @final
*/
class StreamLogger implements LoggerInterface
{

View File

@ -19,5 +19,5 @@ namespace ScssPhp\ScssPhp;
*/
class Version
{
const VERSION = '1.10.2';
const VERSION = '1.10.3';
}

View File

@ -1,3 +1,16 @@
# v1.3.0
## 06/14/2022
1. [](#new)
* Added user object to `onFlexTask.*` and `onFlexAction.*` events
* Added tasks `MediaUploadMeta` and `MediaReorder` to support remote media fields
* Added support to remove media defined in a field
2. [](#improved)
* Refactored admin controller tasks and actions
* Added image preview support for 3rd party editors
1. [](#bugfix)
* Fixed broken error responses in object media tasks
# v1.2.0
## 03/28/2022

View File

@ -1,7 +1,7 @@
name: Flex Objects
slug: flex-objects
type: plugin
version: 1.2.0
version: 1.3.0
description: Flex Objects plugin allows you to manage Flex Objects in Grav Admin.
icon: list-alt
author:

View File

@ -12,6 +12,7 @@ use Grav\Common\Flex\Types\Pages\PageCollection;
use Grav\Common\Flex\Types\Pages\PageIndex;
use Grav\Common\Flex\Types\Pages\PageObject;
use Grav\Common\Grav;
use Grav\Common\Helpers\Excerpts;
use Grav\Common\Language\Language;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Uri;
@ -120,9 +121,9 @@ class AdminController
/**
* Unknown task, call onFlexTask[NAME] event.
*
* @return bool
* @return void
*/
public function taskDefault(): bool
public function taskDefault(): void
{
$type = $this->target;
$directory = $this->getDirectory($type);
@ -143,6 +144,7 @@ class AdminController
'directory' => $directory,
'object' => $object,
'data' => $this->data,
'user' => $this->user,
'redirect' => $this->redirect
]
);
@ -160,19 +162,15 @@ class AdminController
if ($redirect) {
$this->setRedirect($redirect);
}
return $event->isPropagationStopped();
}
return false;
}
/**
* Default action, onFlexAction[NAME] event.
*
* @return bool
* @return void
*/
public function actionDefault(): bool
public function actionDefault(): void
{
$type = $this->target;
$directory = $this->getDirectory($type);
@ -192,6 +190,7 @@ class AdminController
'flex' => $this->getFlex(),
'directory' => $directory,
'object' => $object,
'user' => $this->user,
'redirect' => $this->redirect
]
);
@ -209,19 +208,15 @@ class AdminController
if ($redirect) {
$this->setRedirect($redirect);
}
return $event->isPropagationStopped();
}
return false;
}
/**
* Get datatable for list view.
*
* @return void
* @return ResponseInterface|null
*/
public function actionList(): void
public function actionList(): ?ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
@ -248,28 +243,28 @@ class AdminController
$table = $this->getFlex()->getDataTable($directory, $options);
$response = $this->createJsonResponse($table->jsonSerialize());
$this->close($response);
return $this->createJsonResponse($table->jsonSerialize());
}
return null;
}
/**
* Alias for Export action.
*
* @return void
* @return ResponseInterface|null
*/
public function actionCsv(): void
public function actionCsv(): ?ResponseInterface
{
$this->actionExport();
return $this->actionExport();
}
/**
* Export action. Defaults to CVS export.
*
* @return void
* @return ResponseInterface|null
*/
public function actionExport(): void
public function actionExport(): ?ResponseInterface
{
$collection = $this->getCollection();
if (!$collection) {
@ -341,15 +336,15 @@ class AdminController
$formatter->encode($list)
);
$this->close($response);
return $response;
}
/**
* Delete object from directory.
*
* @return ObjectInterface|bool
* @return void
*/
public function taskDelete()
public function taskDelete(): void
{
$directory = $this->getDirectory();
if (!$directory) {
@ -386,8 +381,6 @@ class AdminController
$this->setRedirect($this->referrerRoute->toString(true), 302);
}
return $object !== null;
}
/**
@ -482,6 +475,10 @@ class AdminController
}
}
/**
* @param FlexDirectoryInterface $directory
* @return void
*/
protected function continue(FlexDirectoryInterface $directory): void
{
$config = $directory->getConfig('admin');
@ -625,10 +622,10 @@ class AdminController
*
* Route: /pages
*
* @return bool True if the action was performed.
* @return void
* @throws RuntimeException
*/
protected function taskCopy(): bool
protected function taskCopy(): void
{
try {
$directory = $this->getDirectory();
@ -680,8 +677,6 @@ class AdminController
$this->admin->setMessage($this->admin::translate(['PLUGIN_FLEX_OBJECTS.CONTROLLER.TASK_COPY_FAILURE', $e->getMessage()]), 'error');
$this->setRedirect($this->referrerRoute->toString(true), 302);
}
return true;
}
/**
@ -821,17 +816,17 @@ class AdminController
}
/**
* @return bool
* @return void
*/
public function taskSaveas(): bool
public function taskSaveas(): void
{
return $this->taskSave();
$this->taskSave();
}
/**
* @return bool
* @return void
*/
public function taskSave(): bool
public function taskSave(): void
{
$directory = $this->getDirectory();
if (!$directory) {
@ -985,14 +980,12 @@ class AdminController
// $this->setRedirect($this->referrerRoute->withQueryParam('uid', $flash->getUniqueId())->toString(true), 302);
$this->setRedirect($this->referrerRoute->toString(true), 302);
}
return true;
}
/**
* @return bool
* @return void
*/
public function taskConfigure(): bool
public function taskConfigure(): void
{
$directory = $this->getDirectory();
if (!$directory) {
@ -1040,161 +1033,152 @@ class AdminController
$this->admin->setMessage($this->admin::translate(['PLUGIN_FLEX_OBJECTS.CONTROLLER.TASK_CONFIGURE_FAILURE', $e->getMessage()]), 'error');
$this->setRedirect($this->referrerRoute->toString(true), 302);
}
return true;
}
/**
* @return bool
* Used in 3rd party editors (e.g. next-gen).
*
* @return ResponseInterface
*/
public function taskMediaList(): bool
public function taskConvertUrls(): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('action', 'media.list');
$key = $this->id;
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
die($e->getMessage());
}
return true;
}
/**
* @return bool
*/
public function taskMediaUpload(): bool
{
$directory = $this->getDirectory();
if (!$directory) {
$object = $this->getObject($key);
if (!$object instanceof PageInterface) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('task', 'media.upload');
$authorized = $object instanceof FlexAuthorizeInterface
? $object->isAuthorized('read', 'admin', $this->user)
: $directory->isAuthorized($object->exists() ? 'read' : 'create', 'admin', $this->user);
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
die($e->getMessage());
if (!$authorized) {
throw new RuntimeException($this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' save.',
403);
}
return true;
$request = $this->getRequest();
$data = $request->getParsedBody();
$data['data'] = json_decode($data['data'] ?? '{}', true, 512, JSON_THROW_ON_ERROR);
if (!isset($data['data'])) {
throw new RequestException($request, 'Bad Request', 400);
}
$converted_links = [];
foreach ($data['data']['a'] ?? [] as $link) {
$converted_links[$link] = Excerpts::processLinkHtml($link, $object);
}
$converted_images = [];
foreach ($data['data']['img'] ?? [] as $image) {
$converted_images[$image] = Excerpts::processImageHtml($image, $object);
}
$json = [
'status' => 'success',
'message' => 'All links converted',
'data' => ['links' => $converted_links, 'images' => $converted_images]
];
return $this->createJsonResponse($json, 200);
}
/**
* @return bool
* @return ResponseInterface
*/
public function taskMediaDelete(): bool
public function taskMediaList(): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('task', 'media.delete');
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
die($e->getMessage());
}
return true;
return $this->forwardMediaTask('action', 'media.list');
}
/**
* @return bool
* @return ResponseInterface
*/
public function taskListmedia(): bool
public function taskMediaUpload(): ResponseInterface
{
return $this->forwardMediaTask('task', 'media.upload');
}
/**
* @return ResponseInterface
*/
public function taskMediaUploadMeta(): ResponseInterface
{
return $this->forwardMediaTask('task', 'media.upload.meta');
}
/**
* @return ResponseInterface
*/
public function taskMediaReorder(): ResponseInterface
{
return $this->forwardMediaTask('task', 'media.reorder');
}
/**
* @return ResponseInterface
*/
public function taskMediaDelete(): ResponseInterface
{
return $this->forwardMediaTask('task', 'media.delete');
}
/**
* @return ResponseInterface
*/
public function taskListmedia(): ResponseInterface
{
return $this->taskMediaList();
}
/**
* @return bool
* @return ResponseInterface
*/
public function taskAddmedia(): bool
public function taskAddmedia(): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('task', 'media.copy');
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
die($e->getMessage());
}
return true;
return $this->forwardMediaTask('task', 'media.copy');
}
/**
* @return bool
* @return ResponseInterface
*/
public function taskDelmedia(): bool
public function taskDelmedia(): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('task', 'media.remove');
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
die($e->getMessage());
}
return true;
return $this->forwardMediaTask('task', 'media.remove');
}
/**
* @return bool
* @return ResponseInterface
* @deprecated Do not use
*/
public function taskFilesUpload(): bool
public function taskFilesUpload(): ResponseInterface
{
throw new RuntimeException('Task filesUpload should not be called!');
}
/**
* @param string|null $filename
* @return bool
* @return ResponseInterface
* @deprecated Do not use
*/
public function taskRemoveMedia($filename = null): bool
public function taskRemoveMedia($filename = null): ResponseInterface
{
throw new RuntimeException('Task removeMedia should not be called!');
}
/**
* @return bool
* @return ResponseInterface
*/
public function taskGetFilesInFolder(): bool
public function taskGetFilesInFolder(): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
try {
$response = $this->forwardMediaTask('action', 'media.picker');
$this->admin->json_response = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR);
} catch (Exception $e) {
$this->admin->json_response = ['success' => false, 'error' => $e->getMessage()];
}
return true;
return $this->forwardMediaTask('action', 'media.picker');
}
/**
@ -1204,12 +1188,18 @@ class AdminController
*/
protected function forwardMediaTask(string $type, string $name): ResponseInterface
{
$route = Uri::getCurrentRoute()->withGravParam('task', null)->withGravParam($type, $name);
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
$route = Uri::getCurrentRoute()->withGravParam('task', null);
$object = $this->getObject();
/** @var ServerRequest $request */
$request = $this->grav['request'];
$request = $request
->withAttribute($type, $name)
->withAttribute('type', $this->target)
->withAttribute('key', $this->id)
->withAttribute('storage_key', $object && $object->exists() ? $object->getStorageKey() : null)
@ -1320,7 +1310,11 @@ class AdminController
// Post
$post = $_POST;
if (isset($post['data'])) {
$this->data = $this->getPost($post['data']);
$data = $post['data'];
if (is_string($data)) {
$data = json_decode($data, true);
}
$this->data = $this->getPost($data);
unset($post['data']);
}

View File

@ -290,14 +290,16 @@ abstract class AbstractController implements RequestHandlerInterface
/**
* @param string $string
* @param array $args
* @return string
*/
public function translate(string $string): string
public function translate(string $string, ...$args): string
{
/** @var Language $language */
$language = $this->grav['language'];
array_unshift($args, $string);
return $language->translate($string);
return $language->translate($args);
}
/**

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Grav\Plugin\FlexObjects\Controllers;
use Exception;
use Grav\Common\Debugger;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Page\Medium\MediumFactory;
@ -132,40 +133,165 @@ class MediaController extends AbstractController
return $this->createJsonResponse($response);
}
/**
* @return ResponseInterface
*/
public function taskMediaUploadMeta(): ResponseInterface
{
$this->checkAuthorization('media.create');
try {
$this->checkAuthorization('media.create');
$object = $this->getObject();
if (null === $object) {
throw new RuntimeException('Not Found', 404);
$object = $this->getObject();
if (null === $object) {
throw new RuntimeException('Not Found', 404);
}
if (!method_exists($object, 'getMediaField')) {
throw new RuntimeException('Not Found', 404);
}
$object->refresh();
// Get updated object from Form Flash.
$flash = $this->getFormFlash($object);
if ($flash->exists()) {
$object = $flash->getObject() ?? $object;
$object->update([], $flash->getFilesByFields());
}
// Get field and data for the uploaded media.
$field = (string)$this->getPost('field');
$media = $object->getMediaField($field);
if (!$media) {
throw new RuntimeException('Media field not found: ' . $field, 404);
}
$data = $this->getPost('data');
if (is_string($data)) {
$data = json_decode($data, true);
}
$filename = Utils::basename($data['name'] ?? '');
// Update field.
$files = $object->getNestedProperty($field, []);
// FIXME: Do we want to save something into the field as well?
$files[$filename] = [];
$object->setNestedProperty($field, $files);
$info = [
'modified' => $data['modified'] ?? null,
'size' => $data['size'] ?? null,
'mime' => $data['mime'] ?? null,
'width' => $data['width'] ?? null,
'height' => $data['height'] ?? null,
'duration' => $data['duration'] ?? null,
'orientation' => $data['orientation'] ?? null,
'meta' => array_filter($data, static function ($val) { return $val !== null; })
];
$info = array_filter($info, static function ($val) { return $val !== null; });
// As the file may not be saved locally, we need to update the index.
$media->updateIndex([$filename => $info]);
$object->save();
$flash->save();
$response = [
'code' => 200,
'status' => 'success',
'message' => $this->translate('PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY'),
'field' => $field,
'filename' => $filename,
'metadata' => $data
];
} catch (\Exception $e) {
/** @var Debugger $debugger */
$debugger = $this->grav['debugger'];
$debugger->addException($e);
return $this->createJsonErrorResponse($e);
}
if (!method_exists($object, 'checkUploadedMediaFile')) {
throw new RuntimeException('Not Found', 404);
return $this->createJsonResponse($response);
}
/**
* @return ResponseInterface
*/
public function taskMediaReorder(): ResponseInterface
{
try {
$this->checkAuthorization('media.update');
$object = $this->getObject();
if (null === $object) {
throw new RuntimeException('Not Found', 404);
}
if (!method_exists($object, 'getMediaField')) {
throw new RuntimeException('Not Found', 404);
}
$object->refresh();
// Get updated object from Form Flash.
$flash = $this->getFormFlash($object);
if ($flash->exists()) {
$object = $flash->getObject() ?? $object;
$object->update([], $flash->getFilesByFields());
}
// Get field and data for the uploaded media.
$field = (string)$this->getPost('field');
$media = $object->getMediaField($field);
if (!$media) {
throw new RuntimeException('Media field not found: ' . $field, 404);
}
// Create id => filename map from all files in the media.
$map = [];
foreach ($media as $name => $medium) {
$id = $medium->get('meta.id');
if ($id) {
$map[$id] = $name;
}
}
// Get reorder list and reorder the map.
$data = $this->getPost('data');
if (is_string($data)) {
$data = json_decode($data, true);
}
$data = array_fill_keys($data, null);
$map = array_filter(array_merge($data, $map), static function($val) { return $val !== null; });
// Reorder the files.
$files = $object->getNestedProperty($field, []);
$map = array_fill_keys($map, null);
$files = array_filter(array_merge($map, $files), static function($val) { return $val !== null; });
// Update field.
$object->setNestedProperty($field, $files);
$object->save();
$flash->save();
$response = [
'code' => 200,
'status' => 'success',
'message' => $this->translate('PLUGIN_ADMIN.FIELD_REORDER_SUCCESSFUL'),
'field' => $field,
'ordering' => array_keys($files)
];
} catch (\Exception $e) {
/** @var Debugger $debugger */
$debugger = $this->grav['debugger'];
$debugger->addException($e);
$ex = new RuntimeException($this->translate('PLUGIN_ADMIN.FIELD_REORDER_FAILED', $field), $e->getCode(), $e);
return $this->createJsonErrorResponse($ex);
}
// Get updated object from Form Flash.
$flash = $this->getFormFlash($object);
if ($flash->exists()) {
$object = $flash->getObject() ?? $object;
$object->update([], $flash->getFilesByFields());
}
// Get field and data for the uploaded media.
$field = $this->getPost('field');
$data = $this->getPost('data');
$filename = Utils::basename($data['name']);
$response = [
'code' => 200,
'status' => 'success',
'message' => $this->translate('PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY'),
'field' => $field,
'filename' => $filename,
'metadata' => $data
];
return $this->createJsonResponse($response);
}
@ -288,6 +414,7 @@ class MediaController extends AbstractController
throw new RuntimeException('Not Found', 404);
}
$field = $this->getPost('field');
$filename = $this->getPost('filename');
// Handle bad filenames.
@ -295,7 +422,13 @@ class MediaController extends AbstractController
throw new RuntimeException($this->translate('PLUGIN_ADMIN.NO_FILE_FOUND'), 400);
}
$object->deleteMediaFile($filename);
$object->deleteMediaFile($filename, $field);
if ($field) {
$order = $object->getNestedProperty($field);
unset($order[$filename]);
$object->setNestedProperty($field, $order);
$object->save();
}
if ($object instanceof PageInterface) {
// Backwards compatibility to existing plugins.
@ -526,6 +659,7 @@ class MediaController extends AbstractController
break;
case 'media.create':
case 'media.update':
case 'media.delete':
$action = $object->exists() ? 'update' : 'create';
break;

View File

@ -339,6 +339,34 @@ class ObjectController extends AbstractController
return $this->forwardMediaTask('task', 'media.upload');
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function taskMediaUploadMeta(ServerRequestInterface $request): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
return $this->forwardMediaTask('task', 'media.upload.meta');
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function taskMediaReorder(ServerRequestInterface $request): ResponseInterface
{
$directory = $this->getDirectory();
if (!$directory) {
throw new RuntimeException('Not Found', 404);
}
return $this->forwardMediaTask('task', 'media.reorder');
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface

View File

@ -21,5 +21,5 @@
"platform-overrides": {
"php": "7.3.6"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.2.0"
}

View File

@ -21,9 +21,15 @@
{% set route = admin ? admin.route : grav.uri.route() %}
<div class="form-field grid vertical {% if field.classes is defined %}{{ field.classes }}{% endif %}">
<div class="pagemedia-field form-field grid vertical {% if field.classes is defined %}{{ field.classes }}{% endif %}">
<div class="form-label">
<label>{{ field.label|tu }}</label>
<label class="media-collapser">
<i class="fa fa-fw small fa-chevron-{{ pageMediaStore.collapsed ? 'right' : 'down' }}"></i>
{{ field.label|t }} <span data-pagemedia-count>({{ admin.page.media|length }})</span>
</label>
<div class="{{ pageMediaStore.collapsed ? 'hidden' : '' }}">
<input type="range" min="70" step="10" max="200" value="{{ pageMediaStore.width }}" class="media-resizer">
</div>
</div>
<div class="form-data form-uploads-wrapper">
{% set uploadLimit = grav.config.system.media.upload_limit / 1024 / 1024 %}

View File

@ -149,7 +149,7 @@ class ClassLoader
/**
* @return string[] Array of classname => path
* @psalm-var array<string, string>
* @psalm-return array<string, string>
*/
public function getClassMap()
{

View File

@ -5,7 +5,7 @@
'type' => 'grav-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'b6f98fd714995cd3097e8d93f1e08994579430c9',
'reference' => 'dfa9760987bbf2cdd61038bca5a7928b31a9dcff',
'name' => 'getgrav/grav-plugin-flex-objects',
'dev' => false,
),
@ -16,7 +16,7 @@
'type' => 'grav-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'b6f98fd714995cd3097e8d93f1e08994579430c9',
'reference' => 'dfa9760987bbf2cdd61038bca5a7928b31a9dcff',
'dev_requirement' => false,
),
),

View File

@ -1,3 +1,9 @@
# v3.7.1
## 06/14/2022
1. [](#bugfix)
* PHP 8.1 fixes in QR code library
# v3.7.0
## 03/28/2022

View File

@ -1,7 +1,7 @@
name: Login
slug: login
type: plugin
version: 3.7.0
version: 3.7.1
testing: false
description: Enables user authentication and login screen.
icon: sign-in

View File

@ -407,7 +407,7 @@ class Controller
return true;
}
$token = md5(uniqid(mt_rand(), true));
$token = md5(uniqid((string)mt_rand(), true));
$expire = time() + 604800; // next week
$user->reset = $token . '::' . $expire;

View File

@ -160,16 +160,16 @@
},
{
"name": "robthree/twofactorauth",
"version": "1.8.1",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
"reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b"
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5afcb45282f1c75562a48d479ecd1732c9bdb11b",
"reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/65681de5a324eae05140ac58b08648a60212afc0",
"reference": "65681de5a324eae05140ac58b08648a60212afc0",
"shasum": ""
},
"require": {
@ -226,7 +226,7 @@
"type": "github"
}
],
"time": "2021-10-20T12:19:55+00:00"
"time": "2022-03-22T16:11:07+00:00"
}
],
"packages-dev": [],

View File

@ -0,0 +1,46 @@
{% extends 'email/base.html.twig' %}
{# Magic login link email (login by email link) #}
{%- set subject = 'PLUGIN_LOGIN.MAGIC_LOGIN_EMAIL_SUBJECT'|t(site_name) %}
{%- set message = message ?? 'PLUGIN_LOGIN.MAGIC_LOGIN_EMAIL_MESSAGE'|t %}
{%- do email.message.setSubject(subject) %}
{%- block content -%}
{{ 'PLUGIN_LOGIN.MAGIC_LOGIN_EMAIL_BODY'|t(site_name, message, login_link, actor.fullname)|raw }}
{%- endblock content -%}
{# https://workos.com/blog/a-guide-to-magic-links
<h1>Account Invitation</h1>
<p>
Hi,
</p>
<p>
You have been invited to join <b>{{ site_name }}</b>.
</p>
<p>
{{ message }}
</p>
<p>
<br/>
<a href="{{ login_link }}" class="btn-primary">Create Your Account Now</a>
<br/>
<br/>
</p>
<p>
Alternatively, copy the following URL into your browser's address bar:
</p>
<p class="word-break">
<a href="{{ login_link }}">{{ login_link }}</a>
</p>
<p>
<br/>
Kind regards,
<br/>
<br/>
{{ actor.fullname }}
</p>
#}

View File

@ -150,17 +150,17 @@
},
{
"name": "robthree/twofactorauth",
"version": "1.8.1",
"version_normalized": "1.8.1.0",
"version": "1.8.2",
"version_normalized": "1.8.2.0",
"source": {
"type": "git",
"url": "https://github.com/RobThree/TwoFactorAuth.git",
"reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b"
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/5afcb45282f1c75562a48d479ecd1732c9bdb11b",
"reference": "5afcb45282f1c75562a48d479ecd1732c9bdb11b",
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/65681de5a324eae05140ac58b08648a60212afc0",
"reference": "65681de5a324eae05140ac58b08648a60212afc0",
"shasum": ""
},
"require": {
@ -174,7 +174,7 @@
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
},
"time": "2021-10-20T12:19:55+00:00",
"time": "2022-03-22T16:11:07+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {

View File

@ -5,7 +5,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '5bff0ca6fbc27f5d7795fdb1b4a86b62ce233af3',
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
'name' => 'getgrav/grav-plugin-login',
'dev' => false,
),
@ -34,7 +34,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '5bff0ca6fbc27f5d7795fdb1b4a86b62ce233af3',
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
'dev_requirement' => false,
),
'paragonie/random_compat' => array(
@ -47,12 +47,12 @@
'dev_requirement' => false,
),
'robthree/twofactorauth' => array(
'pretty_version' => '1.8.1',
'version' => '1.8.1.0',
'pretty_version' => '1.8.2',
'version' => '1.8.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../robthree/twofactorauth',
'aliases' => array(),
'reference' => '5afcb45282f1c75562a48d479ecd1732c9bdb11b',
'reference' => '65681de5a324eae05140ac58b08648a60212afc0',
'dev_requirement' => false,
),
),

View File

@ -0,0 +1,30 @@
name: Test Bacon QR Code Provider
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1
- run: composer require bacon/bacon-qr-code
- run: composer lint
- run: composer test testsDependency/BaconQRCodeTest.php

View File

@ -0,0 +1,46 @@
name: Test Endroid QR Code Provider
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.0', '8.1']
endroid-version: ["^4"]
include:
- php-version: 5.6
# earliest supported version
endroid-version: 2.2.1
- php-version: 7.0
endroid-version: 2.5.1
- php-version: 7.1
# this version is 7.1+
endroid-version: 3.0.0
- php-version: 7.2
# all later versions are 7.3+
endroid-version: 3.5.9
- php-version: 7.3
endroid-version: 3.9.7
- php-version: 7.4
endroid-version: 4.0.0
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1
- run: composer require endroid/qrcode:${{ matrix.endroid-version }}
- run: composer test testsDependency/EndroidQRCodeTest.php

View File

@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
steps:
- uses: actions/checkout@v2
@ -20,6 +20,7 @@ jobs:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: xdebug
ini-values: error_reporting=E_ALL
- uses: ramsey/composer-install@v1

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Rob Janssen
Copyright (c) 2014-2021 Rob Janssen and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,7 +1,7 @@
{
"name": "robthree/twofactorauth",
"description": "Two Factor Authentication",
"version": "1.8.1",
"version": "1.8.2",
"type": "library",
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
"homepage": "https://github.com/RobThree/TwoFactorAuth",

View File

@ -125,12 +125,19 @@ class BaconQrCodeProvider implements IQRCodeProvider
{
if (is_string($colour) && $colour[0] == '#') {
$hexToRGB = function ($input) {
// ensure input no longer has a # for more predictable division
// PHP 8.1 does not like implicitly casting a float to an int
$input = trim($input, '#');
if (strlen($input) != 3 && strlen($input) != 6) {
throw new \RuntimeException('Colour should be a 3 or 6 character value after the #');
}
// split the array into three chunks
$split = str_split(trim($input, '#'), strlen($input) / 3);
$split = str_split($input, strlen($input) / 3);
// cope with three character hex reference
// three characters plus a # = 4
if (strlen($input) == 4) {
if (strlen($input) == 3) {
array_walk($split, function (&$character) {
$character = str_repeat($character, 2);
});

View File

@ -1,8 +1,14 @@
<?php
namespace RobThree\Auth\Providers\Qr;
use Endroid\QrCode\Color\Color;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelMedium;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelQuartile;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
class EndroidQrCodeProvider implements IQRCodeProvider
{
@ -11,8 +17,12 @@ class EndroidQrCodeProvider implements IQRCodeProvider
public $margin;
public $errorcorrectionlevel;
protected $endroid4 = false;
public function __construct($bgcolor = 'ffffff', $color = '000000', $margin = 0, $errorcorrectionlevel = 'H')
{
$this->endroid4 = method_exists(QrCode::class, 'create');
$this->bgcolor = $this->handleColor($bgcolor);
$this->color = $this->handleColor($color);
$this->margin = $margin;
@ -26,7 +36,12 @@ class EndroidQrCodeProvider implements IQRCodeProvider
public function getQRCodeImage($qrtext, $size)
{
return $this->qrCodeInstance($qrtext, $size)->writeString();
if (!$this->endroid4) {
return $this->qrCodeInstance($qrtext, $size)->writeString();
}
$writer = new PngWriter();
return $writer->write($this->qrCodeInstance($qrtext, $size))->getString();
}
protected function qrCodeInstance($qrtext, $size)
@ -49,22 +64,21 @@ class EndroidQrCodeProvider implements IQRCodeProvider
$g = hexdec($split[1]);
$b = hexdec($split[2]);
return ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0];
return $this->endroid4 ? new Color($r, $g, $b, 0) : ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0];
}
private function handleErrorCorrectionLevel($level)
{
switch ($level) {
case 'L':
return ErrorCorrectionLevel::LOW();
return $this->endroid4 ? new ErrorCorrectionLevelLow() : ErrorCorrectionLevel::LOW();
case 'M':
return ErrorCorrectionLevel::MEDIUM();
return $this->endroid4 ? new ErrorCorrectionLevelMedium() : ErrorCorrectionLevel::MEDIUM();
case 'Q':
return ErrorCorrectionLevel::QUARTILE();
return $this->endroid4 ? new ErrorCorrectionLevelQuartile() : ErrorCorrectionLevel::QUARTILE();
case 'H':
return ErrorCorrectionLevel::HIGH();
default:
return ErrorCorrectionLevel::HIGH();
return $this->endroid4 ? new ErrorCorrectionLevelHigh() : ErrorCorrectionLevel::HIGH();
}
}
}

View File

@ -1,8 +1,8 @@
<?php
namespace RobThree\Auth\Providers\Qr;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Logo\Logo;
use Endroid\QrCode\Writer\PngWriter;
class EndroidQrCodeWithLogoProvider extends EndroidQrCodeProvider
{
@ -20,13 +20,33 @@ class EndroidQrCodeWithLogoProvider extends EndroidQrCodeProvider
$this->logoSize = (array)$size;
}
public function getQRCodeImage($qrtext, $size)
{
if (!$this->endroid4) {
return $this->qrCodeInstance($qrtext, $size)->writeString();
}
$logo = null;
if ($this->logoPath) {
$logo = Logo::create($this->logoPath);
if ($this->logoSize) {
$logo->setResizeToWidth($this->logoSize[0]);
if (isset($this->logoSize[1])) {
$logo->setResizeToHeight($this->logoSize[1]);
}
}
}
$writer = new PngWriter();
return $writer->write($this->qrCodeInstance($qrtext, $size), $logo)->getString();
}
protected function qrCodeInstance($qrtext, $size) {
$qrCode = parent::qrCodeInstance($qrtext, $size);
if ($this->logoPath) {
if (!$this->endroid4 && $this->logoPath) {
$qrCode->setLogoPath($this->logoPath);
if ($this->logoSize) {
$qrCode->setLogoSize($this->logoSize[0], $this->logoSize[1]);
$qrCode->setLogoSize($this->logoSize[0], isset($this->logoSize[1]) ? $this->logoSize[1] : null);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace RobThree\Auth\Providers\Qr;
trait HandlesDataUri
{
/**
* @param string $datauri
*
* @return null|array
*/
private function DecodeDataUri($datauri)
{
if (preg_match('/data:(?P<mimetype>[\w\.\-\+\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
return array(
'mimetype' => $m['mimetype'],
'encoding' => $m['encoding'],
'data' => base64_decode($m['data'])
);
}
return null;
}
}

View File

@ -272,7 +272,7 @@ class TwoFactorAuth
{
return 'otpauth://totp/' . rawurlencode($label)
. '?secret=' . rawurlencode($secret)
. '&issuer=' . rawurlencode($this->issuer)
. '&issuer=' . rawurlencode((string)$this->issuer)
. '&period=' . intval($this->period)
. '&algorithm=' . rawurlencode(strtoupper($this->algorithm))
. '&digits=' . intval($this->digits);

View File

@ -2,6 +2,7 @@
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertDeprecationsToExceptions="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"

View File

@ -5,26 +5,11 @@ namespace Tests\Providers\Qr;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\TwoFactorAuthException;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class IQRCodeProviderTest extends TestCase
{
/**
* @param string $datauri
*
* @return null|array
*/
private function DecodeDataUri($datauri)
{
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
return array(
'mimetype' => $m['mimetype'],
'encoding' => $m['encoding'],
'data' => base64_decode($m['data'])
);
}
return null;
}
use HandlesDataUri;
/**
* @return void
@ -40,6 +25,25 @@ class IQRCodeProviderTest extends TestCase
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
}
/**
* @return void
*/
public function testTotpUriIsCorrectNoIssuer()
{
$qr = new TestQrProvider();
/**
* The library specifies the issuer is null by default however in PHP 8.1
* there is a deprecation warning for passing null as a string argument to rawurlencode
*/
$tfa = new TwoFactorAuth(null, 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('test/test', $data['mimetype']);
$this->assertEquals('base64', $data['encoding']);
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=&period=30&algorithm=SHA1&digits=6@200', $data['data']);
}
/**
* @return void
*/

View File

@ -0,0 +1,61 @@
<?php
namespace TestsDependency;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\Providers\Qr\BaconQrCodeProvider;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class BaconQRCodeTest extends TestCase
{
use HandlesDataUri;
public function testDependency()
{
// php < 7.1 will install an older Bacon QR Code
if (! class_exists(ImagickImageBackEnd::class)) {
$this->expectException(\RuntimeException::class);
$qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg');
} else {
$qr = new BaconQrCodeProvider(1, '#000', '#FFF', 'svg');
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('image/svg+xml', $data['mimetype']);
}
}
public function testBadTextColour()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, 'not-a-colour', '#FFF');
}
public function testBadBackgroundColour()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#000', 'not-a-colour');
}
public function testBadTextColourHexRef()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#AAAA', '#FFF');
}
public function testBadBackgroundColourHexRef()
{
$this->expectException(\RuntimeException::class);
new BaconQrCodeProvider(1, '#000', '#AAAA');
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace TestsDependency;
use PHPUnit\Framework\TestCase;
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\Providers\Qr\EndroidQrCodeProvider;
use RobThree\Auth\Providers\Qr\HandlesDataUri;
class EndroidQRCodeTest extends TestCase
{
use HandlesDataUri;
public function testDependency()
{
$qr = new EndroidQrCodeProvider();
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
$this->assertEquals('image/png', $data['mimetype']);
$this->assertEquals('base64', $data['encoding']);
$this->assertNotEmpty($data['data']);
}
}

View File

@ -1,3 +1,11 @@
# v3.0.2
## 06/14/2022
1. [](#new)
* Added new `route:` field to JSON format sitemap
1. [](#bugfix)
* Fixed an issue with `x-default` entry not working with non-string based language code
# v3.0.1
## 02/23/2021

View File

@ -1,7 +1,7 @@
name: Sitemap
type: plugin
slug: sitemap
version: 3.0.1
version: 3.0.2
description: "Provide automatically generated **XML sitemaps** with this very useful, but simple to configure, Grav plugin."
icon: map-marker
author:

View File

@ -4,6 +4,7 @@ namespace Grav\Plugin\Sitemap;
class SitemapEntry
{
public $title;
public $route;
public $lang;
public $translated = false;
public $location;
@ -83,6 +84,24 @@ class SitemapEntry
return $this;
}
/**
* @return mixed
*/
public function getRoute()
{
return $this->route;
}
/**
* @param mixed $route
* @return SitemapEntry
*/
public function setRoute($route): SitemapEntry
{
$this->route = $route;
return $this;
}
/**
* @return mixed
*/

View File

@ -148,12 +148,12 @@ class SitemapPlugin extends Plugin
if ($language->enabled()) {
foreach ($route_data as $l => $l_data) {
$entry->addHreflangs(['hreflang' => $l, 'href' => $l_data['location']]);
if ($l === $default_lang) {
if ($l == $default_lang) {
$entry->addHreflangs(['hreflang' => 'x-default', 'href' => $l_data['location']]);
}
}
}
$this->sitemap[$data['route']] = $entry;
$this->sitemap[$data['url']] = $entry;
}
}
}
@ -275,11 +275,12 @@ class SitemapPlugin extends Plugin
$page_languages = array_keys($page->translatedLanguages());
$include_lang = $this->multilang_skiplang_prefix !== $lang;
$location = $page->canonical($include_lang);
$page_route = $page->url(false, $include_lang);
$url = $page->url(false, $include_lang);
$lang_route = [
'title' => $page->title(),
'route' => $page_route,
'url' => $url,
'route' => $route,
'lang' => $lang,
'translated' => in_array($lang, $page_languages),
'location' => $location,