(Grav GitSync) Automatic Commit from grav
This commit is contained in:
parent
a34430f25b
commit
b38fa6e1ec
|
@ -1,3 +1,16 @@
|
|||
# v1.10.39
|
||||
## 02/19/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Forked and fixed PicoFeed library to support PHP 8.2
|
||||
|
||||
# v1.10.38
|
||||
## 01/02/2023
|
||||
|
||||
1. [](#new)
|
||||
* Update copyright dates
|
||||
* Keep version number in sync with Grav version
|
||||
|
||||
# v1.10.37.1
|
||||
## 10/08/2022
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ edit_mode: normal
|
|||
frontend_preview_target: inline
|
||||
show_github_msg: true
|
||||
admin_icons: line-awesome
|
||||
enable_auto_updates_check: false
|
||||
enable_auto_updates_check: true
|
||||
notifications:
|
||||
feed: true
|
||||
dashboard: true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Admin Panel
|
||||
slug: admin
|
||||
type: plugin
|
||||
version: 1.10.37.1
|
||||
version: 1.10.39
|
||||
description: Adds an advanced administration panel to manage your site
|
||||
icon: empire
|
||||
author:
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use DateTime;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Cache;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Backup\Backups;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Admin\Controllers;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Cache;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Config\Config;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
class ScssList
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin\Twig;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
<?php
|
||||
namespace Grav\Plugin\Admin;
|
||||
|
||||
/**
|
||||
* @package Grav\Plugin\Admin
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Framework\File\File;
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
"require": {
|
||||
"php": "^7.3.6 || ^8.0",
|
||||
"ext-json": "*",
|
||||
"p3k/picofeed": "@stable",
|
||||
"scssphp/scssphp": "^1.7",
|
||||
"laminas/laminas-zendframework-bridge": "^1.4"
|
||||
"laminas/laminas-zendframework-bridge": "^1.4",
|
||||
"p3k/picofeed": "@stable"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^2.4",
|
||||
|
@ -54,5 +54,11 @@
|
|||
"scripts": {
|
||||
"test": "vendor/bin/codecept run unit",
|
||||
"test-windows": "vendor\\bin\\codecept run unit"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/rhukster/picoFeed"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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": "e95b50cceb85b45792cbca45623f6a91",
|
||||
"content-hash": "1f6a6bec99c3a85ac753a1548c22f5d7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "laminas/laminas-xml",
|
||||
|
@ -130,16 +130,16 @@
|
|||
},
|
||||
{
|
||||
"name": "p3k/picofeed",
|
||||
"version": "v0.1.40",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aaronpk/picofeed.git",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c"
|
||||
"url": "https://github.com/rhukster/picofeed.git",
|
||||
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"url": "https://api.github.com/repos/rhukster/picofeed/zipball/8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -171,7 +171,6 @@
|
|||
"PicoFeed": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
|
@ -183,10 +182,9 @@
|
|||
"description": "Modern library to handle RSS/Atom feeds",
|
||||
"homepage": "https://github.com/aaronpk/picoFeed",
|
||||
"support": {
|
||||
"issues": "https://github.com/aaronpk/picofeed/issues",
|
||||
"source": "https://github.com/aaronpk/picofeed/tree/v0.1.40"
|
||||
"source": "https://github.com/rhukster/picofeed/tree/1.0.0"
|
||||
},
|
||||
"time": "2020-04-25T17:48:36+00:00"
|
||||
"time": "2023-02-19T19:58:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "scssphp/scssphp",
|
||||
|
@ -512,30 +510,30 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9",
|
||||
"doctrine/coding-standard": "^9 || ^11",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpbench/phpbench": "^0.16 || ^1",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpstan/phpstan-phpunit": "^1",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.22"
|
||||
"vimeo/psalm": "^4.30 || ^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -562,7 +560,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -578,7 +576,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-03T08:28:38+00:00"
|
||||
"time": "2022-12-30T00:15:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facebook/webdriver",
|
||||
|
@ -1341,27 +1339,28 @@
|
|||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "v1.15.0",
|
||||
"version": "v1.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
|
||||
"reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/15873c65b207b07765dbc3c95d20fdf4a320cbe2",
|
||||
"reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.2",
|
||||
"php": "^7.2 || ~8.0, <8.2",
|
||||
"doctrine/instantiator": "^1.2 || ^2.0",
|
||||
"php": "^7.2 || 8.0.* || 8.1.* || 8.2.*",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"sebastian/comparator": "^3.0 || ^4.0",
|
||||
"sebastian/recursion-context": "^3.0 || ^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^6.0 || ^7.0",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -1402,9 +1401,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
||||
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
|
||||
"source": "https://github.com/phpspec/prophecy/tree/v1.17.0"
|
||||
},
|
||||
"time": "2021-12-08T12:19:24+00:00"
|
||||
"time": "2023-02-02T15:41:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
@ -2668,16 +2667,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v4.4.45",
|
||||
"version": "v4.4.49",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "28b77970939500fb04180166a1f716e75a871ef8"
|
||||
"reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/28b77970939500fb04180166a1f716e75a871ef8",
|
||||
"reference": "28b77970939500fb04180166a1f716e75a871ef8",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9",
|
||||
"reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2738,7 +2737,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.45"
|
||||
"source": "https://github.com/symfony/console/tree/v4.4.49"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2754,7 +2753,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-17T14:50:19+00:00"
|
||||
"time": "2022-11-05T17:10:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
|
@ -3190,16 +3189,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": {
|
||||
|
@ -3214,7 +3213,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3252,7 +3251,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": [
|
||||
{
|
||||
|
@ -3268,20 +3267,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
|
||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3295,7 +3294,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3339,7 +3338,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3355,20 +3354,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
|
@ -3380,7 +3379,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3423,7 +3422,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": [
|
||||
{
|
||||
|
@ -3439,20 +3438,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3467,7 +3466,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3506,7 +3505,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3522,20 +3521,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3544,7 +3543,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3589,7 +3588,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3605,7 +3604,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
|
|
|
@ -3,8 +3,21 @@
|
|||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
|
@ -106,6 +109,7 @@ class ClassLoader
|
|||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,7 +429,8 @@ class ClassLoader
|
|||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -555,6 +560,14 @@ class ClassLoader
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -564,9 +577,9 @@ class ClassLoader
|
|||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,25 +33,18 @@ class ComposerAutoloaderInit98c98c1c3d67f21a128f935fe4a74897
|
|||
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit98c98c1c3d67f21a128f935fe4a74897::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire98c98c1c3d67f21a128f935fe4a74897($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire98c98c1c3d67f21a128f935fe4a74897($fileIdentifier, $file)
|
||||
{
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit98c98c1c3d67f21a128f935fe4a74897::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,17 +130,17 @@
|
|||
},
|
||||
{
|
||||
"name": "p3k/picofeed",
|
||||
"version": "v0.1.40",
|
||||
"version_normalized": "0.1.40.0",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aaronpk/picofeed.git",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c"
|
||||
"url": "https://github.com/rhukster/picofeed.git",
|
||||
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"url": "https://api.github.com/repos/rhukster/picofeed/zipball/8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -163,7 +163,7 @@
|
|||
"suggest": {
|
||||
"ext-curl": "PicoFeed will use cURL if present"
|
||||
},
|
||||
"time": "2020-04-25T17:48:36+00:00",
|
||||
"time": "2023-02-19T19:58:09+00:00",
|
||||
"bin": [
|
||||
"picofeed"
|
||||
],
|
||||
|
@ -174,7 +174,6 @@
|
|||
"PicoFeed": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
|
@ -186,8 +185,7 @@
|
|||
"description": "Modern library to handle RSS/Atom feeds",
|
||||
"homepage": "https://github.com/aaronpk/picoFeed",
|
||||
"support": {
|
||||
"issues": "https://github.com/aaronpk/picofeed/issues",
|
||||
"source": "https://github.com/aaronpk/picofeed/tree/v0.1.40"
|
||||
"source": "https://github.com/rhukster/picofeed/tree/1.0.0"
|
||||
},
|
||||
"install-path": "../p3k/picofeed"
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
'name' => 'getgrav/grav-plugin-admin',
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '97ab52df8179fad32d1190b530c32053b84d5979',
|
||||
'reference' => '0d16602880413bb6cbc2c94b75f02dce3174d215',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
@ -13,7 +13,7 @@
|
|||
'getgrav/grav-plugin-admin' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '97ab52df8179fad32d1190b530c32053b84d5979',
|
||||
'reference' => '0d16602880413bb6cbc2c94b75f02dce3174d215',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
@ -44,9 +44,9 @@
|
|||
),
|
||||
),
|
||||
'p3k/picofeed' => array(
|
||||
'pretty_version' => 'v0.1.40',
|
||||
'version' => '0.1.40.0',
|
||||
'reference' => '356fd66d48779193b10ac28532cb4a4e11bb801c',
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => '8eacaa62f50a0935e26ca33f8d30d283344ca397',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../p3k/picofeed',
|
||||
'aliases' => array(),
|
||||
|
|
|
@ -97,7 +97,7 @@ class DateParser extends Base
|
|||
if ($date !== false) {
|
||||
$errors = DateTime::getLastErrors();
|
||||
|
||||
if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
|
||||
if ($errors === false || ($errors['error_count'] === 0 && $errors['warning_count'] === 0)) {
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
# v1.3.4
|
||||
## 02/19/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Support saving via admin in current language if not translated
|
||||
|
||||
# v1.3.3
|
||||
## 01/04/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Save `post-save` action to session
|
||||
* Set default `post-save` action to `edit` for create and edit
|
||||
|
||||
# v1.3.2
|
||||
## 12/02/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Various translation enhancements
|
||||
1. [](#bugfix)
|
||||
* Fixed frontend editing objects with urlencoded ids
|
||||
|
||||
# v1.3.1
|
||||
## 09/08/2022
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
{# FIXME: Search fields should be passed and individually customizable, right now defaulting to all fields selected #}
|
||||
{% set searchFields = searchFields|merge([key|replace({'.': '_'})]) %}
|
||||
{% endfor %}
|
||||
{% set tableFields = tableFields|merge([{ name: '_actions_', title: 'Actions', titleClass: 'right' }]) %}
|
||||
{% set tableFields = tableFields|merge([{ name: '_actions_', title: "PLUGIN_FLEX_OBJECTS.ACTION.ACTIONS"|tu, titleClass: 'right' }]) %}
|
||||
|
||||
|
||||
{% set list = table.jsonSerialize %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|tu }}
|
||||
</button>
|
||||
{% if can_translate %}
|
||||
{% set untranslated = admin_languages|array_diff(object_languages|merge([language])) %}
|
||||
{% set untranslated = admin_languages|array_diff(object_languages) %}
|
||||
{% if count(untranslated) %}
|
||||
<button id="titlebar-button-save" type="button" class="button success dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fa fa-caret-down"></i>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% set originalValue = value %}
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
{% set isNew = key ? false : true %}
|
||||
{% set savedOption = grav.session.post_entries_save|default('create-new') %}
|
||||
{% set savedOption = grav.session.post_entries_save|default('edit') %}
|
||||
|
||||
{% if isNew %}
|
||||
{% set options = {'create-new':'PLUGIN_FLEX_OBJECTS.ACTION.CREATE_NEW', 'edit':'PLUGIN_FLEX_OBJECTS.ACTION.EDIT_ITEM', 'list':'PLUGIN_FLEX_OBJECTS.ACTION.LIST_ITEMS'} %}
|
||||
|
@ -12,7 +12,6 @@
|
|||
{% endif %}
|
||||
|
||||
{% block input %}
|
||||
{% set savedOption = not isNew and savedOption == 'create-new' ? 'edit' : savedOption %}
|
||||
{% for key, text in options %}
|
||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Flex Objects
|
||||
slug: flex-objects
|
||||
type: plugin
|
||||
version: 1.3.1
|
||||
version: 1.3.4
|
||||
description: Flex Objects plugin allows you to manage Flex Objects in Grav Admin.
|
||||
icon: list-alt
|
||||
author:
|
||||
|
|
|
@ -907,6 +907,7 @@ class AdminController
|
|||
// Set route to point to the current page.
|
||||
if (!$this->redirect) {
|
||||
$postAction = $request->getParsedBody()['_post_entries_save'] ?? 'edit';
|
||||
$this->grav['session']->post_entries_save = $postAction;
|
||||
if ($postAction === 'create-new') {
|
||||
// Create another.
|
||||
$route = $this->referrerRoute->withGravParam('action', null)->withGravParam('', 'add');
|
||||
|
|
|
@ -261,7 +261,7 @@ class FlexObjectsPlugin extends Plugin
|
|||
if (!isset($form['flex']['key']) && $edit === true) {
|
||||
/** @var Route $route */
|
||||
$route = $this->grav['route'];
|
||||
$id = $route->getGravParam('id');
|
||||
$id = rawurldecode($route->getGravParam('id'));
|
||||
if (null !== $id) {
|
||||
$form['flex']['key'] = $id;
|
||||
$event['form'] = $form;
|
||||
|
|
|
@ -13,6 +13,7 @@ PLUGIN_FLEX_OBJECTS:
|
|||
DIRECTORIES: "Verzeichnisse"
|
||||
CSV: "CSV"
|
||||
PARENTS: "Eltern"
|
||||
NEW: "Neu"
|
||||
|
||||
CONTROLLER:
|
||||
TASK_DELETE_SUCCESS: 'Eintrag erfolgreich gelöscht'
|
||||
|
@ -35,6 +36,7 @@ PLUGIN_FLEX_OBJECTS:
|
|||
ADVANCED_OPTIONS: "Erweiterte Optionen"
|
||||
APPLY_FILTERS: "Filter anwenden"
|
||||
RESET_FILTERS: "Filter zurücksetzen"
|
||||
ACTIONS: "Aktionen"
|
||||
|
||||
FILTER:
|
||||
PAGE_ATTRIBUTES: "Seitenattribute"
|
||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
|||
CREATE_NEW: Create New Item
|
||||
EDIT_ITEM: Edit Item
|
||||
LIST_ITEMS: "List Items"
|
||||
LIST_ITEM: List Items
|
||||
DELETE_N: "Delete" # In some languages 'delete OBJECT' may need a special declination
|
||||
REALLY_DELETE: "Are you sure you want to permanently delete the %s?"
|
||||
SEARCH_PLACEHOLDER: "Search…"
|
||||
ADVANCED_OPTIONS: "Advanced Options"
|
||||
APPLY_FILTERS: "Apply Filters"
|
||||
RESET_FILTERS: "Reset to Defaults"
|
||||
ACTIONS: "Actions"
|
||||
|
||||
FILTER:
|
||||
PAGE_ATTRIBUTES: "Page Attributes"
|
||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
|||
CREATE_NEW: "Crear nuevo ítem"
|
||||
EDIT_ITEM: "Editar ítem"
|
||||
LIST_ITEMS: "Listar ítems"
|
||||
LIST_ITEM: "Listar ítem"
|
||||
DELETE_N: "Eliminar"
|
||||
REALLY_DELETE: "¿Realmente quieres eliminar %s permanentemente?"
|
||||
SEARCH_PLACEHOLDER: "Buscar…"
|
||||
ADVANCED_OPTIONS: "Opciones avazadas"
|
||||
APPLY_FILTERS: "Aplicar filtros"
|
||||
RESET_FILTERS: "Restablecer filtros"
|
||||
ACTIONS: "Acciones"
|
||||
|
||||
FILTER:
|
||||
PAGE_ATTRIBUTES: "Atributos de página"
|
||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
|||
CREATE_NEW: 新しいデータを作成
|
||||
EDIT_ITEM: "データの編集"
|
||||
LIST_ITEMS: "データの一覧表示"
|
||||
LIST_ITEM: データの一覧
|
||||
DELETE_N: "削除" # In some languages 'delete OBJECT' may need a special declination
|
||||
REALLY_DELETE: "%s を削除します。復元はできませんがよろしいですか?"
|
||||
SEARCH_PLACEHOLDER: "検索…"
|
||||
ADVANCED_OPTIONS: "詳細設定"
|
||||
APPLY_FILTERS: "フィルターを適用"
|
||||
RESET_FILTERS: "標準にリセットする"
|
||||
ACTIONS: "アクション"
|
||||
|
||||
FILTER:
|
||||
PAGE_ATTRIBUTES: "ページ属性"
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
PLUGIN_FLEX_OBJECTS:
|
||||
PLUGIN_NAME: "Flex Objects"
|
||||
PLUGIN_DESCRIPTION: "De Flex Objects plugin maakt het mogelijk om flexibele objecten te maken en te beheren."
|
||||
|
||||
TITLE: Flex Objects
|
||||
TYPES_TITLE: Mappen
|
||||
AFTER_SAVE: Na opslaan…
|
||||
LIST_INFO: '{from} tot {to} van {total} items weergegeven'
|
||||
EMPTY_RESULT: Deze zoekopdracht geeft geen resultaat
|
||||
|
||||
USE_BUILT_IN_CSS: "Gebruik ingebouwde CSS"
|
||||
EXTRA_ADMIN_TWIG_PATH: "Extra Admin Twig pad"
|
||||
DIRECTORIES: "Mappen"
|
||||
CSV: "CSV"
|
||||
PARENTS: "Ouders"
|
||||
|
||||
CONTROLLER:
|
||||
TASK_DELETE_SUCCESS: 'Item succesvol verwijderd'
|
||||
TASK_DELETE_FAILURE: 'Item verwijderen mislukt: %s'
|
||||
TASK_NEW_FOLDER_SUCCESS: 'Map succesvol aangemaakt'
|
||||
TASK_COPY_SUCCESS: 'Kopie succesvol aangemaakt'
|
||||
TASK_COPY_FAILURE: 'Kopie aanmaken mislukt: %s'
|
||||
TASK_SAVE_SUCCESS: 'Item succesvol opgeslagen'
|
||||
TASK_SAVE_FAILURE: 'Item opslaan mislukt: %s'
|
||||
TASK_CONFIGURE_SUCCESS: 'Configuratie succesvol opgeslagen'
|
||||
TASK_CONFIGURE_FAILURE: 'Configuratie opslaan mislukt: %s'
|
||||
|
||||
ACTION:
|
||||
CREATE_NEW: Nieuw item aanmaken
|
||||
EDIT_ITEM: Item bewerken
|
||||
LIST_ITEMS: Items weergeven
|
||||
DELETE_N: "Verwijderen"
|
||||
REALLY_DELETE: "Weet je zeker dat je %s permanent wilt verwijderen?"
|
||||
SEARCH_PLACEHOLDER: "Zoeken…"
|
||||
ADVANCED_OPTIONS: "Geavanceerde opties"
|
||||
APPLY_FILTERS: "Filters toepassen"
|
||||
RESET_FILTERS: "Filters resetten"
|
||||
|
||||
FILTER:
|
||||
PAGE_ATTRIBUTES: "Pagina attributen"
|
||||
PAGE_TYPES: "Pagina types"
|
||||
MODULAR_TYPES: "Modulaire types"
|
||||
|
||||
LANGUAGE:
|
||||
USING_DEFAULT: "<b>Standaard</b> taalbestand in gebruik."
|
||||
UNUSED_DEFAULT: "Ongebruikt <b>standaard</b> taalbestand aanwezig."
|
||||
USING_OVERRIDE: "<b>%s</b> taalbestand in gebruik."
|
||||
NOT_TRANSLATED_YET: "Deze pagina is nog niet vertaald naar <i class=\"fa fa-flag-o\"></i> <b>%s</b>!"
|
||||
NO_FALLBACK_FOUND: "Geen fallback taalbestand gevonden."
|
||||
FALLING_BACK: "Terugvallen op <b>%s</b> taalbestand."
|
||||
|
||||
STATE:
|
||||
LOADING: "Laden…"
|
||||
CREATED_SUCCESSFULLY: "Succesvol aangemaakt"
|
||||
UPDATED_SUCCESSFULLY: "Succesvol bijgewerkt"
|
||||
DELETED_SUCCESSFULLY: "Succesvol verwijderd"
|
||||
EDITING_DRAFT: "Je bewerkt een concept."
|
||||
NOT_CREATED_YET: "Deze pagina bestaat niet, totdat je hem opslaat."
|
||||
|
||||
ERROR:
|
||||
BAD_DIRECTORY: "Niet bestaande map"
|
||||
PAGE_NOT_FOUND: "Pagina niet gevonden"
|
||||
PAGE_NOT_EXIST: "Oeps! Deze pagina bestaat niet."
|
||||
PAGE_FORBIDDEN: "Oeps! Je hebt geen toegang tot deze pagina."
|
||||
LAYOUT_NOT_FOUND: "Object layout '%s' niet gevonden."
|
||||
BLUEPRINT_NO_LIST: "De blueprint van <i>%s</i> bevat geen velddata of lijst pagina overschrijving."
|
||||
BLUEPRINT_NO_LIST_ADVISE: "Voeg een <i>list</i> sectie toe aan de blueprint of overschrijf de <i>list</i> pagina in de configuratie."
|
||||
BLUEPRINT_NO_LIST_TEMPLATE: "Maak een template bestand voor dit type aan in <b>flex-objects/types/%s/list.html.twig</b>"
|
||||
LIST_EMPTY: "Er zijn geen items gevonden."
|
||||
LIST_EMPTY_ADD: "Er zijn geen items op dit moment. Klik op de knop <a href=\"%s\">Toevoegen</a> om een nieuw item aan te maken."
|
||||
NO_FLEX_DIRECTORIES: "Geen Flex Object mappen gedefinieerd."
|
|
@ -1,165 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"accessor-pairs": 2,
|
||||
"array-bracket-spacing": 0,
|
||||
"block-scoped-var": 0,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"camelcase": 0,
|
||||
"comma-dangle": [2, "never"],
|
||||
"comma-spacing": [2, { "before": false, "after": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"complexity": 0,
|
||||
"computed-property-spacing": 0,
|
||||
"consistent-return": 0,
|
||||
"consistent-this": 0,
|
||||
"constructor-super": 2,
|
||||
"curly": [2, "multi-line"],
|
||||
"default-case": 0,
|
||||
"dot-location": [2, "property"],
|
||||
"dot-notation": 0,
|
||||
"eol-last": 2,
|
||||
"eqeqeq": [2, "allow-null"],
|
||||
"func-names": 0,
|
||||
"func-style": 0,
|
||||
"generator-star-spacing": [2, { "before": true, "after": true }],
|
||||
"guard-for-in": 0,
|
||||
"handle-callback-err": [2, "^(err|error)$" ],
|
||||
"indent": [2, 4, { "SwitchCase": 1 }],
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||
"linebreak-style": 0,
|
||||
"lines-around-comment": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"new-cap": [2, { "newIsCap": true, "capIsNew": false }],
|
||||
"new-parens": 2,
|
||||
"newline-after-var": 0,
|
||||
"no-alert": 0,
|
||||
"no-array-constructor": 2,
|
||||
"no-caller": 2,
|
||||
"no-catch-shadow": 0,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 0,
|
||||
"no-constant-condition": 0,
|
||||
"no-continue": 0,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 0,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-else-return": 0,
|
||||
"no-empty": 0,
|
||||
"no-empty-character-class": 2,
|
||||
"no-eq-null": 0,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 0,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inline-comments": 0,
|
||||
"no-inner-declarations": [2, "functions"],
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 0,
|
||||
"no-loop-func": 0,
|
||||
"no-mixed-requires": 0,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [2, { "max": 1 }],
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-in-lhs": 2,
|
||||
"no-nested-ternary": 0,
|
||||
"no-new": 2,
|
||||
"no-new-func": 0,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-param-reassign": 0,
|
||||
"no-path-concat": 0,
|
||||
"no-process-env": 0,
|
||||
"no-process-exit": 0,
|
||||
"no-proto": 0,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-restricted-modules": 0,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 0,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 0,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-sync": 0,
|
||||
"no-ternary": 0,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unneeded-ternary": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unused-expressions": 0,
|
||||
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
|
||||
"no-use-before-define": 0,
|
||||
"no-var": 0,
|
||||
"no-void": 0,
|
||||
"no-warning-comments": 0,
|
||||
"no-with": 2,
|
||||
"object-curly-spacing": 0,
|
||||
"object-shorthand": 0,
|
||||
"one-var": [2, { "initialized": "never" }],
|
||||
"operator-assignment": 0,
|
||||
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
|
||||
"padded-blocks": 0,
|
||||
"prefer-const": 0,
|
||||
"quote-props": 0,
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"semi": [2, "always"],
|
||||
"semi-spacing": 0,
|
||||
"sort-vars": 0,
|
||||
"keyword-spacing": [2, {"after": true, "overrides": {"throw": { "after": true}, "return": { "before": true }}}],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],
|
||||
"strict": 0,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [2, "any"],
|
||||
"wrap-regex": 0,
|
||||
"yoda": [2, "never"]
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
# OS Generated
|
||||
.DS_Store*
|
||||
/.idea
|
||||
node_modules
|
||||
*.js.map
|
|
@ -1,3 +1,88 @@
|
|||
# v7.1.2
|
||||
## 01/08/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixes issue with multiplication type BasicCaptcha Math Captcha [#587](https://github.com/getgrav/grav-plugin-form/issues/587)
|
||||
|
||||
# v7.1.1
|
||||
## 11/29/2022
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix missing blueprint entries for Turnstile configuration [#583](https://github.com/getgrav/grav-plugin-form/issues/583)
|
||||
|
||||
# v7.1.0
|
||||
## 11/16/2022
|
||||
|
||||
1. [](#new)
|
||||
* Added Cloudflare's `turnstile` captcha integration [documentation](https://learn.getgrav.org/17/forms/forms/fields-available#turnstile-field-cloudflare)
|
||||
|
||||
# v7.0.2
|
||||
## 10/05/2022
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix for modular form definitions at root-level (useful for storing shared forms)
|
||||
|
||||
# v7.0.1
|
||||
## 09/20/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Provided some basic CSS styling for new captcha field
|
||||
|
||||
# v7.0.0
|
||||
## 09/20/2022
|
||||
|
||||
1. [](#new)
|
||||
* Added a new custom `basic-captcha` option with **character** and **math** puzzles. No 3rd-part service required.
|
||||
|
||||
# v6.0.4
|
||||
## 08/08/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Added `attributes` to field [#573](https://github.com/getgrav/grav-plugin-form/pull/573)
|
||||
|
||||
# v6.0.3
|
||||
## 05/05/2022
|
||||
|
||||
1. [](#bugfix)
|
||||
* Regression: Fixed broken `addForm()` method
|
||||
|
||||
# v6.0.2
|
||||
## 05/02/2022
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed `forms({ route: '/forms/_myform' })` not finding form from non-routable pages (second try)
|
||||
|
||||
# v6.0.1
|
||||
## 04/25/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Improved `prepare_form_field()` twig method to include `plain_name`
|
||||
1. [](#bugfix)
|
||||
* Fixed `columns` and `column` fields with `.dotted` variables inside to ignore columns and column names
|
||||
* Fixed `forms({ route: '/forms/_myform' })` not finding forms from non-routable pages
|
||||
|
||||
# v6.0.0
|
||||
## 03/28/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Added log warning when trying to access form by non-unique name
|
||||
* Optimized form caching by not initializing the forms in `onPageProcessed` event anymore
|
||||
* **BACKWARD COMPATIBILITY**: As form initialization has been delayed, logic relaying on `onPageProcessed` with forms may not work anymore
|
||||
1. [](#bugfix)
|
||||
* Fixed select field where option is iterable (#558)
|
||||
* Fixed `FormPlugin::getForm()` to properly search the current page first
|
||||
* Fixed `FormPlugin::getForm()` to ignore fallback if the page was given as parameter
|
||||
* Fixed dynamic forms to work with cache turned on
|
||||
* Fix nested `toggleable`: originalValue now checks with `??` instead of `is defined`
|
||||
|
||||
# v5.1.7
|
||||
## 03/14/2022
|
||||
|
||||
1. [](#new)
|
||||
* Added `access` support for buttons
|
||||
2. [](#bugfix)
|
||||
* Fixed tabs in the frontend to ensure JS is loaded
|
||||
|
||||
# v5.1.6
|
||||
## 02/07/2022
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ Note: when using email functionality in your forms, make sure you have configure
|
|||
|
||||
# NOTES:
|
||||
|
||||
As of version **Form 6.0.0** forms are no longer initialized before caching, but when the form is requested. This has been done to make dynamic forms to work better with caching. There may be some backward compatibility issues for logic that modifies pages with forms as the modification doesn't happen without accessing the form first.
|
||||
|
||||
As of version **Form 5.0.0** Grav 1.7+ is required.
|
||||
|
||||
As of version **Form 4.0.6**, form labels are now being output with the `|raw` filter. If you wish to show HTML in your form label, ie `Root Folder <root>`, then you need to escape that in your form definition:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,8 +1,8 @@
|
|||
name: Form
|
||||
slug: form
|
||||
type: plugin
|
||||
version: 5.1.6
|
||||
description: Enables the forms handling
|
||||
version: 7.1.2
|
||||
description: Enables forms handling and processing
|
||||
icon: check-square
|
||||
author:
|
||||
name: Team Grav
|
||||
|
@ -196,3 +196,150 @@ form:
|
|||
label: PLUGIN_FORM.RECAPTCHA_SECRET_KEY
|
||||
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
|
||||
default: ''
|
||||
|
||||
turnstile_captcha:
|
||||
type: section
|
||||
title: PLUGIN_FORM.TURNSTILE_CAPTCHA
|
||||
|
||||
fields:
|
||||
turnstile.theme:
|
||||
type: select
|
||||
label: PLUGIN_FORM.RECAPTCHA_THEME
|
||||
default: light
|
||||
options:
|
||||
light: PLUGIN_FORM.RECAPTCHA_THEME_LIGHT
|
||||
dark: PLUGIN_FORM.RECAPTCHA_THEME_DARK
|
||||
turnstile.site_key:
|
||||
type: text
|
||||
label: PLUGIN_FORM.RECAPTCHA_SITE_KEY
|
||||
help: PLUGIN_FORM.RECAPTCHA_SITE_KEY_HELP
|
||||
default: ''
|
||||
turnstile.secret_key:
|
||||
type: text
|
||||
label: PLUGIN_FORM.RECAPTCHA_SECRET_KEY
|
||||
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
|
||||
default: ''
|
||||
|
||||
basic_captcha:
|
||||
type: section
|
||||
title: PLUGIN_FORM.BASIC_CAPTCHA
|
||||
|
||||
fields:
|
||||
basic_captcha.type:
|
||||
type: elements
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_TYPE
|
||||
default: 'characters'
|
||||
size: medium
|
||||
options:
|
||||
characters: Random Characters
|
||||
math: Math Puzzle
|
||||
fields:
|
||||
characters:
|
||||
type: element
|
||||
fields:
|
||||
basic_captcha.chars.length:
|
||||
type: range
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_LENGTH
|
||||
default: 6
|
||||
validate:
|
||||
min: 4
|
||||
max: 12
|
||||
append: characters
|
||||
basic_captcha.chars.font:
|
||||
type: select
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_FONT
|
||||
default: zxx-noise.ttf
|
||||
options:
|
||||
'zxx-noise.ttf': zxx-Noise
|
||||
'zxx-xed.ttf': zxx-Xed
|
||||
'zxx-camo.ttf': zxx-Camo
|
||||
'zxx-sans.ttf': zxx-Sans
|
||||
basic_captcha.chars.size:
|
||||
type: range
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_SIZE
|
||||
default: 24
|
||||
append: px
|
||||
validate:
|
||||
min: 12
|
||||
max: 32
|
||||
step: 2
|
||||
basic_captcha.chars.bg:
|
||||
type: colorpicker
|
||||
size: small
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_BG_COLOR
|
||||
default: '#ffffff'
|
||||
basic_captcha.chars.text:
|
||||
type: colorpicker
|
||||
size: small
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_TEXT_COLOR
|
||||
default: '#000000'
|
||||
basic_captcha.chars.start_x:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_START_X
|
||||
default: 5
|
||||
append: px
|
||||
size: small
|
||||
validate:
|
||||
min: 0
|
||||
type: number
|
||||
basic_captcha.chars.start_y:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_START_Y
|
||||
default: 30
|
||||
append: px
|
||||
size: small
|
||||
validate:
|
||||
min: 0
|
||||
type: number
|
||||
basic_captcha.chars.box_width:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_BOX_WIDTH
|
||||
default: 135
|
||||
append: px
|
||||
size: small
|
||||
validate:
|
||||
min: 0
|
||||
type: number
|
||||
basic_captcha.chars.box_height:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_BOX_HEIGHT
|
||||
default: 40
|
||||
append: px
|
||||
size: small
|
||||
validate:
|
||||
min: 0
|
||||
type: number
|
||||
math:
|
||||
type: element
|
||||
fields:
|
||||
basic_captcha.math.min:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_MATH_MIN
|
||||
default: 1
|
||||
size: small
|
||||
validate:
|
||||
min: 0
|
||||
type: number
|
||||
basic_captcha.math.max:
|
||||
type: number
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_MATH_MAX
|
||||
default: 10
|
||||
size: small
|
||||
validate:
|
||||
min: 1
|
||||
type: number
|
||||
basic_captcha.math.operators:
|
||||
type: selectize
|
||||
selectize:
|
||||
options:
|
||||
- value: '+'
|
||||
text: '+ Addition'
|
||||
- value: '-'
|
||||
text: '- Subtraction'
|
||||
- value: '*'
|
||||
text: 'x Multiplication'
|
||||
- value: '/'
|
||||
text: '/ Division'
|
||||
label: PLUGIN_FORM.BASIC_CAPTCHA_MATH_OPERATORS
|
||||
validate:
|
||||
type: commalist
|
||||
|
|
|
@ -40,7 +40,7 @@ class BasicCaptcha
|
|||
}
|
||||
} elseif ($operator === '*') {
|
||||
$result = "{$first_num} x {$second_num}";
|
||||
$captcha_code = $first_num - $second_num;
|
||||
$captcha_code = $first_num * $second_num;
|
||||
} elseif ($operator === '/') {
|
||||
$result = "$first_num / second_num";
|
||||
$captcha_code = $first_num / $second_num;
|
||||
|
|
|
@ -119,7 +119,7 @@ class Form implements FormInterface, ArrayAccess
|
|||
$this->items = $form;
|
||||
} else {
|
||||
// Otherwise get all forms in the page.
|
||||
$forms = $page->forms();
|
||||
$forms = $page->getForms();
|
||||
if ($name) {
|
||||
// If form with given name was found, use that.
|
||||
$this->items = $forms[$name] ?? [];
|
||||
|
|
|
@ -113,7 +113,7 @@ class Forms
|
|||
*/
|
||||
protected function getPageParameters(PageInterface $page, ?string $name): array
|
||||
{
|
||||
$forms = $page->forms();
|
||||
$forms = $page->getForms();
|
||||
|
||||
if ($name) {
|
||||
// If form with given name was found, use that.
|
||||
|
|
|
@ -90,21 +90,28 @@ class TwigExtension extends AbstractExtension
|
|||
return null;
|
||||
}
|
||||
|
||||
// If field has already been prepared, we do not need to do anything.
|
||||
if (!empty($field['prepared'])) {
|
||||
return $field;
|
||||
}
|
||||
|
||||
// Check if we have just a list of fields (no name given).
|
||||
if (is_int($name)) {
|
||||
$fieldName = (string)($field['name'] ?? $name);
|
||||
if (!is_string($name) || $name === '') {
|
||||
// Look at the field.name and if not set, fall back to the key.
|
||||
$name = (string)($field['name'] ?? $name);
|
||||
$name = $fieldName;
|
||||
}
|
||||
|
||||
// Make sure that the field has a name.
|
||||
$name = $name ?? $field['name'] ?? null;
|
||||
if (!is_string($name) || $name === '') {
|
||||
if ($name === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prefix name with the parent name if needed.
|
||||
if (str_starts_with($name, '.')) {
|
||||
$name = $parent ? $parent . $name : (string)substr($name, 1);
|
||||
$plainName = (string)substr($name, 1);
|
||||
$field['plain_name'] = $plainName;
|
||||
$name = $parent ? $parent . $name : $plainName;
|
||||
} elseif (isset($options['key'])) {
|
||||
$name = str_replace('*', $options['key'], $name);
|
||||
}
|
||||
|
@ -125,6 +132,7 @@ class TwigExtension extends AbstractExtension
|
|||
|
||||
// Always set field name.
|
||||
$field['name'] = $name;
|
||||
$field['prepared'] = true;
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
|
|
@ -73,5 +73,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "7.3.6"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.2.0"
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Grav\Plugin;
|
|||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use DateTime;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Exception;
|
||||
use Grav\Common\Data\ValidationException;
|
||||
use Grav\Common\Debugger;
|
||||
|
@ -18,10 +19,13 @@ use Grav\Common\Utils;
|
|||
use Grav\Common\Uri;
|
||||
use Grav\Common\Yaml;
|
||||
use Grav\Framework\Form\Interfaces\FormInterface;
|
||||
use Grav\Framework\Psr7\Response;
|
||||
use Grav\Framework\Route\Route;
|
||||
use Grav\Plugin\Form\BasicCaptcha;
|
||||
use Grav\Plugin\Form\Form;
|
||||
use Grav\Plugin\Form\Forms;
|
||||
use Grav\Plugin\Form\TwigExtension;
|
||||
use Grav\Common\HTTP\Client;
|
||||
use ReCaptcha\ReCaptcha;
|
||||
use ReCaptcha\RequestMethod\CurlPost;
|
||||
use RecursiveArrayIterator;
|
||||
|
@ -31,6 +35,7 @@ use RocketTheme\Toolbox\File\YamlFile;
|
|||
use RocketTheme\Toolbox\File\File;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RuntimeException;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\CoreExtension;
|
||||
use Twig\Extension\EscaperExtension;
|
||||
|
@ -54,11 +59,9 @@ class FormPlugin extends Plugin
|
|||
|
||||
/** @var Form */
|
||||
protected $form;
|
||||
/** @var array */
|
||||
/** @var array[]|FormInterface[] */
|
||||
protected $forms = [];
|
||||
/** @var array */
|
||||
protected $flat_forms = [];
|
||||
/** @var array */
|
||||
/** @var FormInterface[] */
|
||||
protected $active_forms = [];
|
||||
/** @var array */
|
||||
protected $json_response = [];
|
||||
|
@ -70,7 +73,7 @@ class FormPlugin extends Plugin
|
|||
*/
|
||||
public static function checkRequirements(): bool
|
||||
{
|
||||
return version_compare(GRAV_VERSION, '1.6', '>');
|
||||
return version_compare(GRAV_VERSION, '1.7', '>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,18 +86,13 @@ class FormPlugin extends Plugin
|
|||
}
|
||||
|
||||
return [
|
||||
'onPluginsInitialized' => [
|
||||
['autoload', 100000],
|
||||
['onPluginsInitialized', 0]
|
||||
],
|
||||
'onPluginsInitialized' => ['onPluginsInitialized', 0],
|
||||
'onTwigExtensions' => ['onTwigExtensions', 0],
|
||||
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* [onPluginsInitialized:100000] Composer autoload.
|
||||
*
|
||||
* @return ClassLoader
|
||||
*/
|
||||
public function autoload()
|
||||
|
@ -114,10 +112,9 @@ class FormPlugin extends Plugin
|
|||
|
||||
$this->grav['forms'] = function () {
|
||||
$forms = new Forms();
|
||||
|
||||
$grav = Grav::instance();
|
||||
$event = new Event(['forms' => $forms]);
|
||||
$grav->fireEvent('onFormRegisterTypes', $event);
|
||||
|
||||
$this->grav->fireEvent('onFormRegisterTypes', $event);
|
||||
|
||||
return $forms;
|
||||
};
|
||||
|
@ -130,12 +127,19 @@ class FormPlugin extends Plugin
|
|||
return;
|
||||
}
|
||||
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
|
||||
// Mini Keep-Alive Logic
|
||||
$task = $this->grav['uri']->param('task');
|
||||
if ($task && $task === 'keep-alive') {
|
||||
exit;
|
||||
$task = $uri->param('task');
|
||||
if ($task === 'keep-alive') {
|
||||
$response = new Response(200);
|
||||
|
||||
$this->grav->close($response);
|
||||
}
|
||||
|
||||
$this->processBasicCaptchaImage($uri);
|
||||
|
||||
$this->enable([
|
||||
'onPageProcessed' => ['onPageProcessed', 0],
|
||||
'onPagesInitialized' => ['onPagesInitialized', 0],
|
||||
|
@ -161,16 +165,16 @@ class FormPlugin extends Plugin
|
|||
/**
|
||||
* Process forms after page header processing, but before caching
|
||||
*
|
||||
* @param Event $e
|
||||
* @param Event $event
|
||||
* @return void
|
||||
*/
|
||||
public function onPageProcessed(Event $e): void
|
||||
public function onPageProcessed(Event $event): void
|
||||
{
|
||||
/** @var PageInterface $page */
|
||||
$page = $e['page'];
|
||||
$page = $event['page'];
|
||||
|
||||
$pageForms = $page->forms();
|
||||
if (!$pageForms) {
|
||||
$forms = $page->getForms();
|
||||
if (!$forms) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -184,23 +188,18 @@ class FormPlugin extends Plugin
|
|||
}
|
||||
$parent = $current && $current !== $page ? $current : null;
|
||||
|
||||
$page_route = $page->home() ? '/' : $page->route();
|
||||
|
||||
// If the form was in the modular page, we need to add the form into the parent page as well.
|
||||
if ($parent) {
|
||||
$parent->addForms($pageForms);
|
||||
$parent_route = $parent->home() ? '/' : $parent->route();
|
||||
$parent->addForms($forms);
|
||||
}
|
||||
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
// Store the page forms in the forms instance
|
||||
foreach ($pageForms as $name => $form) {
|
||||
if (isset($parent, $parent_route)) {
|
||||
$this->addForm($parent_route, $forms->createPageForm($parent, $name, $form));
|
||||
foreach ($forms as $name => $form) {
|
||||
if ($parent) {
|
||||
$this->addFormDefinition($parent, $name, $form);
|
||||
}
|
||||
$this->addForm($page_route, $forms->createPageForm($page, $name, $form));
|
||||
|
||||
$this->addFormDefinition($page, $name, $form);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +256,7 @@ class FormPlugin extends Plugin
|
|||
if ($form instanceof Form) {
|
||||
// Post the form
|
||||
$isJson = $uri->extension() === 'json';
|
||||
$task = $uri->post('task') ?? $uri->param('task');
|
||||
$task = (string)($uri->post('task') ?? $uri->param('task'));
|
||||
|
||||
if ($isJson) {
|
||||
if ($task === 'store-state') {
|
||||
|
@ -286,10 +285,13 @@ class FormPlugin extends Plugin
|
|||
if ($this->json_response && $page->template() !== 'form') {
|
||||
$status = $this->json_response['status'] ?? null;
|
||||
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($status === 'error' ? 400 : 200);
|
||||
echo json_encode($this->json_response);
|
||||
exit;
|
||||
$response = new Response(
|
||||
$status !== 'error' ? 200 : 400,
|
||||
['Content-Type' => 'application/json'],
|
||||
json_encode($this->json_response, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
|
||||
$this->grav->close($response);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,11 +315,25 @@ class FormPlugin extends Plugin
|
|||
// There is no active form to be posted.
|
||||
// Check all the forms for the current page; we are looking for forms with remember state turned on with random unique id.
|
||||
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
/** @var Route $route */
|
||||
$route = $this->grav['route'];
|
||||
$pageForms = $this->forms[$route->getRoute()] ?? [];
|
||||
|
||||
foreach ($pageForms as $formName => $form) {
|
||||
/**
|
||||
* @var string $name
|
||||
* @var array|FormInterface $form
|
||||
*/
|
||||
foreach ($pageForms as $name => $form) {
|
||||
if (is_array($form)) {
|
||||
$form = $this->createForm($page, $name, $form);
|
||||
}
|
||||
if (!$form instanceof FormInterface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($form->get('remember_redirect')) {
|
||||
// Found one; we need to check if unique id is set.
|
||||
$formParam = $form->get('uniqueid_param', 'fid');
|
||||
|
@ -328,8 +344,6 @@ class FormPlugin extends Plugin
|
|||
$form->setUniqueId($uniqueId);
|
||||
$form->initialize();
|
||||
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
$forms->setActiveForm($form);
|
||||
|
||||
break;
|
||||
|
@ -337,7 +351,7 @@ class FormPlugin extends Plugin
|
|||
|
||||
// Append unique id to the URL and redirect.
|
||||
$route = $route->withGravParam($formParam, $form->getUniqueId());
|
||||
$page->redirect((string)$route->toString());
|
||||
$page->redirect($route->toString());
|
||||
|
||||
// TODO: Do we want to add support for multiple forms with remembered state?
|
||||
break;
|
||||
|
@ -398,7 +412,7 @@ class FormPlugin extends Plugin
|
|||
/**
|
||||
* Make form accessible from twig.
|
||||
*
|
||||
* @param Event $event
|
||||
* @param Event|null $event
|
||||
* @return void
|
||||
*/
|
||||
public function onTwigVariables(Event $event = null): void
|
||||
|
@ -428,6 +442,7 @@ class FormPlugin extends Plugin
|
|||
* @param Event $event
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
public function onFormProcessed(Event $event): void
|
||||
{
|
||||
|
@ -499,6 +514,55 @@ class FormPlugin extends Plugin
|
|||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'basic-captcha':
|
||||
$captcha = new BasicCaptcha();
|
||||
$captcha_value = trim($form->value('basic-captcha'));
|
||||
if (!$captcha->validateCaptcha($captcha_value)) {
|
||||
$message = $params['message'] ?? $this->grav['language']->translate('PLUGIN_FORM.ERROR_BASIC_CAPTCHA');
|
||||
|
||||
$this->grav->fireEvent('onFormValidationError', new Event([
|
||||
'form' => $form,
|
||||
'message' => $message
|
||||
]));
|
||||
|
||||
$event->stopPropagation();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'turnstile':
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
|
||||
$turnstile_config = $this->config->get('plugins.form.turnstile');
|
||||
$secret = $turnstile_config['secret_key'] ?? null;
|
||||
$token = $form->getValue('cf-turnstile-response') ?? null;
|
||||
$ip = Uri::ip();
|
||||
|
||||
$client = Client::getClient();
|
||||
$response = $client->request('POST', 'https://challenges.cloudflare.com/turnstile/v0/siteverify', [
|
||||
'body' => [
|
||||
'secret' => $secret,
|
||||
'response' => $token,
|
||||
'remoteip' => $ip
|
||||
]
|
||||
]);
|
||||
|
||||
$content = $response->toArray();
|
||||
|
||||
if (!$content['success']) {
|
||||
$message = $params['message'] ?? $this->grav['language']->translate('PLUGIN_FORM.ERROR_BASIC_CAPTCHA');
|
||||
|
||||
$this->grav->fireEvent('onFormValidationError', new Event([
|
||||
'form' => $form,
|
||||
'message' => $message
|
||||
]));
|
||||
|
||||
$this->grav['log']->addWarning('Form Turnstile invalid: [' . $uri->route() . '] ' . json_encode($content));
|
||||
$event->stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'timestamp':
|
||||
$label = $params['label'] ?? 'Timestamp';
|
||||
|
@ -544,8 +608,7 @@ class FormPlugin extends Plugin
|
|||
$this->grav['messages']->add($form->message, 'success');
|
||||
}
|
||||
|
||||
$event['redirect'] = $url;
|
||||
$event->stopPropagation();
|
||||
$this->grav->redirect($url);
|
||||
break;
|
||||
case 'reset':
|
||||
if (Utils::isPositive($params)) {
|
||||
|
@ -736,6 +799,7 @@ class FormPlugin extends Plugin
|
|||
*/
|
||||
public function onFormValidationError(Event $event): void
|
||||
{
|
||||
/** @var FormInterface $form */
|
||||
$form = $event['form'];
|
||||
if (isset($event['message'])) {
|
||||
$form->status = 'error';
|
||||
|
@ -743,6 +807,7 @@ class FormPlugin extends Plugin
|
|||
$form->messages = $event['messages'];
|
||||
}
|
||||
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
$route = $uri->route();
|
||||
|
||||
|
@ -752,8 +817,7 @@ class FormPlugin extends Plugin
|
|||
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
$page = $pages->dispatch($route, true);
|
||||
|
||||
$page = $pages->find($route, true);
|
||||
if ($page) {
|
||||
unset($this->grav['page']);
|
||||
$this->grav['page'] = $page;
|
||||
|
@ -762,14 +826,32 @@ class FormPlugin extends Plugin
|
|||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a form definition to the forms plugin
|
||||
*
|
||||
* @param PageInterface $page
|
||||
* @return void
|
||||
*/
|
||||
public function addFormDefinition(PageInterface $page, string $name, array $form): void
|
||||
{
|
||||
$route = ($page->home() ? '/' : $page->route()) ?? '/';
|
||||
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
$form['_page_routable'] = !$page->isModule();
|
||||
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->recache_forms = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a form to the forms plugin
|
||||
*
|
||||
* @param string|null $page_route
|
||||
* @param string|null $route
|
||||
* @param FormInterface|null $form
|
||||
* @return void
|
||||
*/
|
||||
public function addForm(?string $page_route, ?FormInterface $form)
|
||||
public function addForm(?string $route, ?FormInterface $form): void
|
||||
{
|
||||
if (null === $form) {
|
||||
return;
|
||||
|
@ -777,10 +859,10 @@ class FormPlugin extends Plugin
|
|||
|
||||
$name = $form->getName();
|
||||
|
||||
if (!isset($this->forms[$page_route][$name])) {
|
||||
$this->forms[$page_route][$name] = $form;
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
$form['_page_routable'] = true;
|
||||
|
||||
$this->flattenForms();
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->recache_forms = true;
|
||||
}
|
||||
}
|
||||
|
@ -788,45 +870,128 @@ class FormPlugin extends Plugin
|
|||
/**
|
||||
* function to get a specific form
|
||||
*
|
||||
* @param null|array|string $data optional form `name`
|
||||
* @param string|array|null $data Optional form name or ['name' => $name, 'route' => $route]
|
||||
* @return FormInterface|null
|
||||
*/
|
||||
public function getForm($data = null)
|
||||
public function getForm($data = null): ?FormInterface
|
||||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
|
||||
// Handle parameters.
|
||||
if (is_array($data)) {
|
||||
$form_name = $data['name'] ?? null;
|
||||
$page_route = $data['route'] ?? null;
|
||||
$name = (string)($data['name'] ?? '');
|
||||
$route = (string)($data['route'] ?? '');
|
||||
} elseif (is_string($data)) {
|
||||
$form_name = $data;
|
||||
$page_route = null;
|
||||
$name = $data;
|
||||
$route = '';
|
||||
} else {
|
||||
$form_name = null;
|
||||
$page_route = null;
|
||||
$name = '';
|
||||
$route = '';
|
||||
}
|
||||
|
||||
// if no form name, use the first form found in the page
|
||||
if (!$form_name) {
|
||||
// If page route not provided, use the current page
|
||||
if (!$page_route) {
|
||||
// Get page route with a fallback using current URI if page not initialized yet
|
||||
$page_route = $this->grav['page']->route() ?: $this->getCurrentPageRoute();
|
||||
// Return always the same form instance.
|
||||
$form = $this->active_forms[$route][$name] ?? null;
|
||||
if ($form) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
if (!empty($this->forms[$page_route])) {
|
||||
$forms = $this->forms[$page_route];
|
||||
$first_form = reset($forms) ?: null;
|
||||
return $first_form;
|
||||
$unnamed = $name === '';
|
||||
$routed = $route !== '';
|
||||
|
||||
// Get the page.
|
||||
if ($routed) {
|
||||
// Use fixed route for the form.
|
||||
$route_provided = true;
|
||||
|
||||
$page = $pages->find($route, true);
|
||||
} else {
|
||||
// Search form from the current page first.
|
||||
$route_provided = false;
|
||||
|
||||
/** @var PageInterface|null $page */
|
||||
$page = $this->grav['page'] ?? null;
|
||||
if ($page) {
|
||||
$route = $page->route();
|
||||
} else {
|
||||
// Get page route with a fallback using current URI if page is not yet initialized.
|
||||
$route = $this->getCurrentPageRoute();
|
||||
$page = $pages->find($route);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get page by defined route first or get current if not found
|
||||
$page = $this->grav['pages']->find($page_route) ?: $this->grav['page'];
|
||||
// Attempt to find the form from the page.
|
||||
if ('' !== $route) {
|
||||
$forms = $this->forms[$route] ?? [];
|
||||
|
||||
// Try looking up in the defined page
|
||||
return $this->grav['forms']->createPageForm($page);
|
||||
if (!$unnamed) {
|
||||
// Get form by the name.
|
||||
$form = $forms[$name] ?? null;
|
||||
} else {
|
||||
// Get the first form.
|
||||
$form = reset($forms) ?: null;
|
||||
$name = key($forms);
|
||||
}
|
||||
}
|
||||
|
||||
// return the form you are looking for if available
|
||||
return $this->getFormByName($form_name);
|
||||
// Search the form from the other pages.
|
||||
if (null === $form) {
|
||||
// First check if we requested a specific form which didn't exist.
|
||||
if ($route_provided || $unnamed) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Attempt to find any form with given name.
|
||||
$forms = $this->findFormByName($name);
|
||||
$first = reset($forms);
|
||||
if (!$first) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for naming conflicts.
|
||||
if (count($forms) > 1) {
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning');
|
||||
}
|
||||
|
||||
[$route, $name, $form] = $first;
|
||||
|
||||
$page = $pages->find($route);
|
||||
}
|
||||
|
||||
// Form can be saved as an array or an object. If it's an array, we need to create object from it.
|
||||
if (is_array($form)) {
|
||||
// Form was cached as an array, try to create the object.
|
||||
if (null === $page) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$form = $this->createForm($page, $name, $form);
|
||||
}
|
||||
|
||||
// Register form to the active forms to get the same instance back next time.
|
||||
$this->active_forms[$route][$name] = $form;
|
||||
if ($unnamed) {
|
||||
$this->active_forms[$route][''] = $form;
|
||||
}
|
||||
|
||||
// Also make aliases if route was not provided to the method.
|
||||
if (!$routed) {
|
||||
$this->active_forms[''][$name] = $form;
|
||||
if ($unnamed) {
|
||||
$this->active_forms[''][''] = $form;
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -834,7 +999,7 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFormFieldTypes()
|
||||
public function getFormFieldTypes(): array
|
||||
{
|
||||
return [
|
||||
'avatar' => [
|
||||
|
@ -906,7 +1071,7 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* - fillWithCurrentDateTime
|
||||
*
|
||||
* @param Form $form
|
||||
* @param FormInterface $form
|
||||
* @return void
|
||||
*/
|
||||
protected function process($form)
|
||||
|
@ -921,43 +1086,33 @@ class FormPlugin extends Plugin
|
|||
/**
|
||||
* Get current page's route
|
||||
*
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
protected function getCurrentPageRoute()
|
||||
{
|
||||
$path = $this->grav['uri']->route();
|
||||
$path = $path ?: '/';
|
||||
return $path;
|
||||
|
||||
return $path ?: '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a form based on the form name
|
||||
* Return all forms matching the given name.
|
||||
*
|
||||
* @param string $form_name
|
||||
* @param string $unique_id
|
||||
* @return mixed
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function getFormByName($form_name, $unique_id = '')
|
||||
protected function findFormByName(string $name): array
|
||||
{
|
||||
$form = $this->active_forms[$form_name] ?? null;
|
||||
if (!$form) {
|
||||
$form = $this->flat_forms[$form_name] ?? null;
|
||||
|
||||
if (!$form) {
|
||||
return null;
|
||||
$list = [];
|
||||
foreach ($this->forms as $route => $forms) {
|
||||
foreach ($forms as $key => $form) {
|
||||
if ($name === $key && !empty($form['_page_routable'])) {
|
||||
$list[] = [$route, $key, $form];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('' === $unique_id) {
|
||||
// Reset form to change the cached unique id and to fire onFormInitialized event.
|
||||
$form->setUniqueId('');
|
||||
$form->reset();
|
||||
}
|
||||
|
||||
// Register form to the active forms to get the same instance back next time.
|
||||
$this->active_forms[$form_name] = $form;
|
||||
}
|
||||
|
||||
return $form;
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -965,12 +1120,11 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldProcessForm()
|
||||
protected function shouldProcessForm(): bool
|
||||
{
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
$nonce = $uri->post('form-nonce');
|
||||
$status = $nonce ? true : false; // php72 quirk?
|
||||
$refresh_prevention = null;
|
||||
$status = (bool)$uri->post('form-nonce');
|
||||
|
||||
if ($status && $form = $this->form()) {
|
||||
// Make sure form is something we recognize.
|
||||
|
@ -1009,29 +1163,14 @@ class FormPlugin extends Plugin
|
|||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten the forms array into something that can be more easily searched
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function flattenForms()
|
||||
{
|
||||
$this->flat_forms = Utils::arrayFlatten($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current form, should already be processed but can get it directly from the page if necessary
|
||||
*
|
||||
* @param PageInterface|null $page
|
||||
* @return Form|null
|
||||
* @return FormInterface|null
|
||||
*/
|
||||
protected function form(PageInterface $page = null)
|
||||
{
|
||||
// Regenerate list of flat_forms if not already populated
|
||||
if (empty($this->flat_forms)) {
|
||||
$this->flattenForms();
|
||||
}
|
||||
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
|
@ -1050,11 +1189,16 @@ class FormPlugin extends Plugin
|
|||
$form_name = $page ? $page->slug() : null;
|
||||
}
|
||||
|
||||
$form = $this->getFormByName($form_name, $unique_id);
|
||||
$form = $form_name ? $this->getForm($form_name) : null;
|
||||
if ($form && '' === $unique_id) {
|
||||
// Reset form to change the cached unique id and to fire onFormInitialized event.
|
||||
$form->setUniqueId('');
|
||||
$form->reset();
|
||||
}
|
||||
|
||||
// last attempt using current page's form
|
||||
if (!$form && $page) {
|
||||
$form = $forms->createPageForm($page);
|
||||
$form = $this->createForm($page);
|
||||
}
|
||||
|
||||
if ($form) {
|
||||
|
@ -1073,20 +1217,16 @@ class FormPlugin extends Plugin
|
|||
|
||||
/**
|
||||
* @param PageInterface $page
|
||||
* @param string|int|null $name
|
||||
* @param array $form
|
||||
* @return Form|null
|
||||
* @deprecated
|
||||
* @param string|null $name
|
||||
* @param array|null $form
|
||||
* @return FormInterface|null
|
||||
*/
|
||||
protected function createForm(PageInterface $page, $name = null, $form = null)
|
||||
protected function createForm(PageInterface $page, string $name = null, array $form = null): ?FormInterface
|
||||
{
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
$header = $page->header();
|
||||
if (isset($header->form) || isset($header->forms)) {
|
||||
return new Form($page, $name, $form);
|
||||
}
|
||||
|
||||
return null;
|
||||
return $forms->createPageForm($page, $name, $form);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1094,18 +1234,20 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadCachedForms()
|
||||
protected function loadCachedForms(): void
|
||||
{
|
||||
// Get and set the cache of forms if it exists
|
||||
try {
|
||||
[$forms] = $this->grav['cache']->fetch($this->getFormCacheId());
|
||||
} catch (Exception $e) {
|
||||
// Couldn't fetch cached forms.
|
||||
$forms = null;
|
||||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
|
||||
[$forms] = $cache->fetch($this->getFormCacheId());
|
||||
} catch (Exception $e) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = Grav::instance()['debugger'];
|
||||
$debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||
|
||||
$forms = null;
|
||||
}
|
||||
|
||||
if (!is_array($forms)) {
|
||||
|
@ -1113,9 +1255,8 @@ class FormPlugin extends Plugin
|
|||
}
|
||||
|
||||
// Only update the forms if it's not empty
|
||||
if (!empty($forms)) {
|
||||
if ($forms) {
|
||||
$this->forms = array_merge($this->forms, $forms);
|
||||
$this->flattenForms();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1124,13 +1265,19 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function saveCachedForms()
|
||||
protected function saveCachedForms(): void
|
||||
{
|
||||
// Save the current state of the forms to cache
|
||||
if ($this->recache_forms) {
|
||||
$this->recache_forms = false;
|
||||
$this->grav['cache']->save($this->getFormCacheId(), [$this->forms]);
|
||||
if (!$this->recache_forms) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->recache_forms = false;
|
||||
|
||||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
|
||||
$cache->save($this->getFormCacheId(), [$this->forms]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1138,9 +1285,12 @@ class FormPlugin extends Plugin
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFormCacheId()
|
||||
protected function getFormCacheId(): string
|
||||
{
|
||||
return $this->grav['pages']->getPagesCacheId() . '-form-plugin';
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
|
||||
return $pages->getPagesCacheId() . '-form-plugin';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1152,16 +1302,25 @@ class FormPlugin extends Plugin
|
|||
*/
|
||||
protected function udate($format = 'u', $raw = false)
|
||||
{
|
||||
|
||||
$utimestamp = microtime(true);
|
||||
|
||||
if ($raw) {
|
||||
return date($format);
|
||||
}
|
||||
|
||||
$utimestamp = microtime(true);
|
||||
$timestamp = floor($utimestamp);
|
||||
$milliseconds = round(($utimestamp - $timestamp) * 1000000);
|
||||
|
||||
return date(preg_replace('`(?<!\\\\)u`', sprintf('%06d', $milliseconds), $format), $timestamp);
|
||||
}
|
||||
|
||||
protected function processBasicCaptchaImage(Uri $uri)
|
||||
{
|
||||
if ($uri->path() === '/forms-basic-captcha-image.jpg') {
|
||||
$captcha = new BasicCaptcha();
|
||||
$code = $captcha->getCaptchaCode();
|
||||
$image = $captcha->createCaptchaImage($code);
|
||||
$captcha->renderCaptchaImage($image);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,3 +18,24 @@ recaptcha:
|
|||
theme: light
|
||||
site_key:
|
||||
secret_key:
|
||||
turnstile:
|
||||
theme: light # options: [light | dark]
|
||||
site_key:
|
||||
secret_key:
|
||||
|
||||
basic_captcha:
|
||||
type: characters # options: [characters | math]
|
||||
chars:
|
||||
length: 6 # number of chars to output
|
||||
font: zxx-noise.ttf # options: [zxx-noise.ttf | zxx-camo.ttf | zxx-xed.ttf | zxx-sans.ttf]
|
||||
bg: '#cccccc' # 6-char hex color
|
||||
text: '#333333' # 6-char hex color
|
||||
size: 24 # font size in px
|
||||
start_x: 5 # start position in x direction in px
|
||||
start_y: 30 # start position in y direction in px
|
||||
box_width: 135 # box width in px
|
||||
box_height: 40 # box height in px
|
||||
math:
|
||||
min: 1 # smallest digit
|
||||
max: 12 # largest digit
|
||||
operators: ['+','-','*'] # operators that can be used in math
|
||||
|
|
|
@ -10,6 +10,7 @@ en:
|
|||
DESTINATION_HELP: "The location where the files should be uploaded to"
|
||||
ACCEPT: "Allowed MIME Types"
|
||||
ACCEPT_HELP: "A list of MIME Types that are allowed for upload"
|
||||
ERROR_BASIC_CAPTCHA: "Captcha failed for this form, please try again"
|
||||
ERROR_VALIDATING_CAPTCHA: "reCAPTCHA bot protection has identified this form submission is problematic"
|
||||
DATA_SUMMARY: "Here is the summary of what you wrote to us:"
|
||||
NO_FORM_DATA: "No form data available"
|
||||
|
@ -72,6 +73,22 @@ en:
|
|||
DESTINATION_NOT_SPECIFIED: "Destination not specified"
|
||||
INVALID_MIME_TYPE: "The MIME type %s for the file %s is not accepted."
|
||||
INVALID_FILE_EXTENSION: "The File Extension for the file %s is not accepted."
|
||||
BASIC_CAPTCHA: "Basic Captcha"
|
||||
BASIC_CAPTCHA_TYPE: "Captcha challenge type"
|
||||
BASIC_CAPTCHA_LENGTH: "Number of characters"
|
||||
BASIC_CAPTCHA_FONT: "TTF Font"
|
||||
BASIC_CAPTCHA_SIZE: "Font size"
|
||||
BASIC_CAPTCHA_BG_COLOR: "Background color"
|
||||
BASIC_CAPTCHA_TEXT_COLOR: "Text color"
|
||||
BASIC_CAPTCHA_START_X: "Text start x-position"
|
||||
BASIC_CAPTCHA_START_Y: "Text start y-position"
|
||||
BASIC_CAPTCHA_BOX_WIDTH: "Image width"
|
||||
BASIC_CAPTCHA_BOX_HEIGHT: "Image height"
|
||||
BASIC_CAPTCHA_MATH_MIN: "Minimum number"
|
||||
BASIC_CAPTCHA_MATH_MAX: "Maximum number"
|
||||
BASIC_CAPTCHA_MATH_OPERATORS: "Mathematical operators (randomized)"
|
||||
TURNSTILE_CAPTCHA: "Cloudflare Turnstile Captcha"
|
||||
|
||||
eu:
|
||||
PLUGIN_FORM:
|
||||
NOT_VALIDATED: "Formularioa ez da baliozkotu. Beharrezkoa den eremu bat edo gehiago falta dira."
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$form-border-color: #eee;
|
||||
$form-border-color: #ccc;
|
||||
$form-active-color: #000;
|
||||
|
||||
.form-group.has-errors {
|
||||
|
@ -287,3 +287,29 @@ $form-active-color: #000;
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.form-data.basic-captcha {
|
||||
.form-input-wrapper {
|
||||
border: 1px solid $form-border-color;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
.form-input-prepend {
|
||||
display: flex;
|
||||
color: #333;
|
||||
background-color: #ccc;
|
||||
flex-shrink: 0;
|
||||
img {
|
||||
margin: 0;
|
||||
}
|
||||
button > svg {
|
||||
margin: 0 8px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
input.form-input {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{% set default = field.default %}
|
||||
{% set toggleable = field.toggleable ?? false %}
|
||||
{% if toggleable %}
|
||||
{% set originalValue = originalValue is defined ? originalValue : value %}
|
||||
{% set originalValue = originalValue ?? value %}
|
||||
{% set toggleableChecked = originalValue is not null %}
|
||||
{% elseif field.overridable %}
|
||||
{% set toggleable = true %}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{% set fields = prepare_form_fields(fields, name) %}
|
||||
{% set originalValue = null %}
|
||||
{% if fields|length %}
|
||||
{% block outer_markup_field_open %}{% endblock %}
|
||||
{% for field_name, field in fields %}
|
||||
{% set value = form ? form.value(field.name) : data.value(field.name) %}
|
||||
{% set field_templates = include_form_field(field.type, field_layout, fallback_field ?? 'text') %}
|
||||
|
||||
{% block inner_markup_field_open %}{% endblock %}
|
||||
{% block field %}
|
||||
{% include field_templates %}
|
||||
|
|
|
@ -145,6 +145,7 @@
|
|||
|
||||
{% if form.isEnabled() ?? true %}
|
||||
{% for button in form.buttons %}
|
||||
{% if not button.access or authorize(button.access) %}
|
||||
{% if button.outerclasses is defined %}<div class="{{ button.outerclasses }}">{% endif %}
|
||||
|
||||
{% if button.url %}
|
||||
|
@ -190,6 +191,7 @@
|
|||
{% endembed %}
|
||||
|
||||
{% if button.outerclasses is defined %}</div>{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{% block prepend %}
|
||||
<div class="form-input-addon form-input-prepend">
|
||||
<img id="basic-captcha-reload" src="{{ url('/forms-basic-captcha-image.jpg') }}" alt="human test" />
|
||||
<button id="reload-captcha"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="#292D32"><path d="M14.74 22.39c4.68-1.24 8-5.49 8-10.4 0-5.95-4.79-10.75-10.75-10.75 -3.11 0-5.78 1.11-7.99 2.95 -.77.64-1.43 1.32-1.98 2.01 -.34.41-.57.75-.69.95 -.22.35-.1.81.25 1.02 .35.21.81.09 1.02-.26 .08-.15.27-.43.56-.79 .49-.62 1.08-1.23 1.76-1.81C6.87 3.67 9.21 2.7 11.94 2.7c5.13 0 9.25 4.12 9.25 9.25 0 4.22-2.86 7.88-6.9 8.94 -.41.1-.64.51-.54.91 .1.4.51.63.91.53Zm-12-14.84V2.99c-.001-.42-.34-.75-.75-.75 -.42 0-.75.33-.75.75v4.56c0 .41.33.75.75.75 .41 0 .75-.34.75-.75Zm-.75.75H4h2.43c.41 0 .75-.34.75-.75 0-.42-.34-.75-.75-.75H4 1.99c-.42 0-.75.33-.75.75 0 .41.33.75.75.75Z"/><path d="M1.25 12c0 1.09.16 2.16.48 3.18 .12.39.54.61.93.49 .39-.13.61-.55.49-.94 -.28-.89-.42-1.81-.42-2.75 0-.42-.34-.75-.75-.75 -.42 0-.75.33-.75.75Zm1.93 6.15c.61.88 1.36 1.67 2.22 2.33 .32.25.79.19 1.05-.14 .25-.33.19-.8-.14-1.06 -.74-.58-1.38-1.25-1.92-2.02 -.24-.34-.71-.43-1.05-.19 -.34.23-.43.7-.19 1.04Zm5.02 3.91c1 .37 2.06.6 3.15.66 .41.02.76-.3.79-.71 .02-.42-.3-.77-.71-.8 -.94-.06-1.85-.25-2.72-.58 -.39-.15-.83.04-.97.43 -.15.38.04.82.43.96Z"/></g></svg></button>
|
||||
<button id="reload-captcha"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="currentColor"><path d="M14.74 22.39c4.68-1.24 8-5.49 8-10.4 0-5.95-4.79-10.75-10.75-10.75 -3.11 0-5.78 1.11-7.99 2.95 -.77.64-1.43 1.32-1.98 2.01 -.34.41-.57.75-.69.95 -.22.35-.1.81.25 1.02 .35.21.81.09 1.02-.26 .08-.15.27-.43.56-.79 .49-.62 1.08-1.23 1.76-1.81C6.87 3.67 9.21 2.7 11.94 2.7c5.13 0 9.25 4.12 9.25 9.25 0 4.22-2.86 7.88-6.9 8.94 -.41.1-.64.51-.54.91 .1.4.51.63.91.53Zm-12-14.84V2.99c-.001-.42-.34-.75-.75-.75 -.42 0-.75.33-.75.75v4.56c0 .41.33.75.75.75 .41 0 .75-.34.75-.75Zm-.75.75H4h2.43c.41 0 .75-.34.75-.75 0-.42-.34-.75-.75-.75H4 1.99c-.42 0-.75.33-.75.75 0 .41.33.75.75.75Z"/><path d="M1.25 12c0 1.09.16 2.16.48 3.18 .12.39.54.61.93.49 .39-.13.61-.55.49-.94 -.28-.89-.42-1.81-.42-2.75 0-.42-.34-.75-.75-.75 -.42 0-.75.33-.75.75Zm1.93 6.15c.61.88 1.36 1.67 2.22 2.33 .32.25.79.19 1.05-.14 .25-.33.19-.8-.14-1.06 -.74-.58-1.38-1.25-1.92-2.02 -.24-.34-.71-.43-1.05-.19 -.34.23-.43.7-.19 1.04Zm5.02 3.91c1 .37 2.06.6 3.15.66 .41.02.76-.3.79-.71 .02-.42-.3-.77-.71-.8 -.94-.06-1.85-.25-2.72-.58 -.39-.15-.83.04-.97.43 -.15.38.04.82.43.96Z"/></g></svg></button>
|
||||
<script>
|
||||
function stripQueryString(url) {
|
||||
return url.split("?")[0].split("#")[0];
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% set originalValue = value %}
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
{% if field.use == 'keys' and field.default %}
|
||||
{% set value = field.default|merge(value) %}
|
||||
{% endif %}
|
||||
|
||||
{% block global_attributes %}
|
||||
{{ parent() }}
|
||||
data-grav-keys="{{ field.use == 'keys' ? 'true' : 'false' }}"
|
||||
|
@ -13,6 +7,11 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
{% if field.use == 'keys' and field.default %}
|
||||
{% set value = field.default|merge(value) %}
|
||||
{% endif %}
|
||||
|
||||
{% for key, text in field.options %}
|
||||
|
||||
{% set id = field.id|default(field.name)|hyphenize ~ '-' ~ key %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% block field %}
|
||||
{% embed 'forms/default/fields.html.twig' with {name: field.name, fields: field.fields} %}
|
||||
{% embed 'forms/default/fields.html.twig' with {name: name, fields: field.fields} %}
|
||||
{% block outer_markup_field_open %}<div class="form-column {{ field.classes }}">{% endblock %}
|
||||
{% block outer_markup_field_close %}</div>{% endblock %}
|
||||
{% endembed %}
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
{% block field %}
|
||||
<div class="form-columns {{ field.classes }}">
|
||||
{% include 'forms/default/fields.html.twig' with {name: field.name, fields: field.fields} %}
|
||||
{% include 'forms/default/fields.html.twig' with {name: field.name|parent_field, fields: field.fields} %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% set originalValue = value %}
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
|
||||
{% block input %}
|
||||
{% for key, text in field.options %}
|
||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
data-{{ datakey }}="{{ datavalue|e('html_attr') }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if field.attributes %}
|
||||
{% for key, value in field.attributes %}
|
||||
{{ key }}="{{ value|e('html_attr') }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
>
|
||||
{% if field.placeholder %}<option value="" disabled selected>{{ field.placeholder|t|raw }}</option>{% endif %}
|
||||
|
||||
|
@ -43,9 +48,9 @@
|
|||
{% set akey = field.selectize and field.multiple ? item_value : key %}
|
||||
{% set avalue = item_value.value|t %}
|
||||
<option {{ item_value.disabled ? 'disabled="disabled"' : '' }}
|
||||
{{ item_value.selected ? 'selected="selected"' : '' }}
|
||||
{{ item_value.selected or key == value ? 'selected="selected"' : '' }}
|
||||
{{ item_value.label ? 'label=' ~ item_value.label : '' }}
|
||||
value="{{ item_value.akey }}"
|
||||
value="{{ akey }}"
|
||||
>
|
||||
{{ avalue|raw }}
|
||||
</option>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% if grav.admin is not defined %}
|
||||
{% if not grav.admin %}
|
||||
{% do assets.addJs('plugin://form/assets/form.vendor.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
||||
{% do assets.addJs('plugin://form/assets/form.min.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
||||
{% endif %}
|
||||
|
@ -29,7 +29,7 @@
|
|||
{% endfor %}
|
||||
{% else %}
|
||||
{% set tabsKey = form.name ~ '-' ~ fields|keys|join(':')|md5 %}
|
||||
{% set storedValue = grav.admin is defined ? get_cookie('grav-tabs-state')|default('{}')|json_decode : [] %}
|
||||
{% set storedValue = grav.admin ? get_cookie('grav-tabs-state')|default('{}')|json_decode : [] %}
|
||||
{% set storedTab = attribute(storedValue, 'tab-' ~ tabsKey) %}
|
||||
{% if storedTab is empty %}
|
||||
{% set active = uri.params.tab ?? field.active ?? 1 %}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% set config = grav.config %}
|
||||
{% set site_key = field.turnstile_site_key ?? config.plugins.form.turnstile.site_key %}
|
||||
{% set theme = field.theme ?? config.plugins.form.turnstile.theme ?? 'light' %}
|
||||
|
||||
{% block label %}{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% do assets.addJs('https://challenges.cloudflare.com/turnstile/v0/api.js', { defer: '', async: '' }) %}
|
||||
|
||||
<div class="turnstile">
|
||||
<div class="cf-turnstile" data-sitekey="{{ site_key }}" data-theme="{{ theme }}"></div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -42,21 +42,75 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
|
@ -66,28 +120,47 @@ class ClassLoader
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
|
@ -103,8 +176,10 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -148,10 +223,12 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -196,7 +273,9 @@ class ClassLoader
|
|||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
|
@ -212,9 +291,11 @@ class ClassLoader
|
|||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
|
@ -234,6 +315,8 @@ class ClassLoader
|
|||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
|
@ -256,6 +339,8 @@ class ClassLoader
|
|||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
|
@ -276,6 +361,8 @@ class ClassLoader
|
|||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
|
@ -296,25 +383,44 @@ class ClassLoader
|
|||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
|
@ -323,6 +429,8 @@ class ClassLoader
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,6 +475,21 @@ class ClassLoader
|
|||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
|
@ -438,6 +561,10 @@ class ClassLoader
|
|||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
|
|
|
@ -1,97 +1,120 @@
|
|||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
private static $installed = array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
||||
'name' => 'getgrav/grav-plugin-form',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'getgrav/grav-plugin-form' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
||||
),
|
||||
'google/recaptcha' =>
|
||||
array (
|
||||
'pretty_version' => '1.2.4',
|
||||
'version' => '1.2.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '614f25a9038be4f3f2da7cbfd778dc5b357d2419',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
return array_keys(self::$installed['versions']);
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function isInstalled($packageName)
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
return isset(self::$installed['versions'][$packageName]);
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
|
@ -100,129 +123,228 @@ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
|||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['version'])) {
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['version'];
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['pretty_version'];
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['reference'];
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
return self::$installed['root'];
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class ComposerAutoloaderInitd9f2f96e3ad6fd86ce688af0527a1d7b
|
|||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitd9f2f96e3ad6fd86ce688af0527a1d7b', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitd9f2f96e3ad6fd86ce688af0527a1d7b', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
|
|
|
@ -56,6 +56,6 @@
|
|||
"install-path": "../google/recaptcha"
|
||||
}
|
||||
],
|
||||
"dev": false,
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
<?php return array(
|
||||
'root' =>
|
||||
array (
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '2e6d16dbc801d605f56d2d2942cd99a8bf63550c',
|
||||
'name' => 'getgrav/grav-plugin-form',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'getgrav/grav-plugin-form' =>
|
||||
array (
|
||||
'versions' => array(
|
||||
'getgrav/grav-plugin-form' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '2e6d16dbc801d605f56d2d2942cd99a8bf63550c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
||||
),
|
||||
'google/recaptcha' =>
|
||||
array (
|
||||
'google/recaptcha' => array(
|
||||
'pretty_version' => '1.2.4',
|
||||
'version' => '1.2.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../google/recaptcha',
|
||||
'aliases' => array(),
|
||||
'reference' => '614f25a9038be4f3f2da7cbfd778dc5b357d2419',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
/.php_cs.cache
|
||||
/.phpunit.result.cache
|
||||
/build
|
||||
/composer.lock
|
||||
/examples/config.php
|
||||
/nbproject/private/
|
||||
/vendor/
|
|
@ -1,33 +0,0 @@
|
|||
dist: trusty
|
||||
|
||||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- '5.5'
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
|
||||
before_script:
|
||||
- composer install
|
||||
- phpenv version-name | grep ^5.[34] && echo "extension=apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true
|
||||
- phpenv version-name | grep ^5.[34] && echo "apc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
- composer run-script lint
|
||||
- composer run-script test
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/php-coveralls
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- "$HOME/.composer/cache/files"
|
||||
|
||||
git:
|
||||
depth: 5
|
|
@ -1,2 +0,0 @@
|
|||
.idea
|
||||
.DS_Store
|
|
@ -1,3 +1,39 @@
|
|||
# v3.7.3
|
||||
## 02/17/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed an issue where user was not being redirected to the correct page after login
|
||||
|
||||
# v3.7.2
|
||||
## 01/02/2023
|
||||
|
||||
1. [](#new)
|
||||
* Added new `onBeforeSessionStart()` event to store redirect + messages when session is regenerated during login
|
||||
* Requires Grav `1.7.38` for new event availability
|
||||
|
||||
# v3.7.1
|
||||
## 06/14/2022
|
||||
|
||||
1. [](#bugfix)
|
||||
* PHP 8.1 fixes in QR code library
|
||||
|
||||
# v3.7.0
|
||||
## 03/28/2022
|
||||
|
||||
1. [](#new)
|
||||
* Require **Grav 1.7.32**, **Form 6.0.0** and **Email 3.1.6**
|
||||
* Added support for fully customizable email templates
|
||||
* Added `Grav\PluginsLogin\Email` class to simplify sending emails
|
||||
* Added `PageAuthorizeEvent` event for customizing page access
|
||||
1. [](#bugfix)
|
||||
* Removed ACL checks for page modules as they caused unexpected behavior
|
||||
|
||||
# v3.6.3
|
||||
## 03/14/2022
|
||||
|
||||
1. [](#improved)
|
||||
* Improved multi-site support in user emails
|
||||
|
||||
# v3.6.2
|
||||
## 01/12/2022
|
||||
|
||||
|
@ -10,7 +46,7 @@
|
|||
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with forgot password error message translation [#285](https://github.com/getgrav/grav-plugin-login/pull/285)
|
||||
*
|
||||
|
||||
# v3.6.0
|
||||
## 10/26/2021
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Login
|
||||
slug: login
|
||||
type: plugin
|
||||
version: 3.6.2
|
||||
version: 3.7.3
|
||||
testing: false
|
||||
description: Enables user authentication and login screen.
|
||||
icon: sign-in
|
||||
|
@ -15,9 +15,9 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues
|
|||
license: MIT
|
||||
|
||||
dependencies:
|
||||
- { name: grav, version: '>=1.7.27' }
|
||||
- { name: form, version: '>=5.1.0' }
|
||||
- { name: email, version: '>=3.1.0' }
|
||||
- { name: grav, version: '>=1.7.38' }
|
||||
- { name: form, version: '>=6.0.0' }
|
||||
- { name: email, version: '>=3.1.6' }
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
|
|
|
@ -12,12 +12,12 @@ namespace Grav\Plugin\Login;
|
|||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\User\Interfaces\UserCollectionInterface;
|
||||
use Grav\Common\User\Interfaces\UserInterface;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Plugin\Email\Utils as EmailUtils;
|
||||
use Grav\Plugin\Form\Form;
|
||||
use Grav\Plugin\Form\Forms;
|
||||
use Grav\Plugin\Login\Events\UserLoginEvent;
|
||||
use Grav\Plugin\Login\Invitations\Invitation;
|
||||
|
@ -343,7 +343,8 @@ class Controller
|
|||
*/
|
||||
protected function taskForgot()
|
||||
{
|
||||
$param_sep = $this->grav['config']->get('system.param_sep', ':');
|
||||
/** @var Config $config */
|
||||
$config = $this->grav['config'];
|
||||
$data = $this->post;
|
||||
|
||||
/** @var UserCollectionInterface $users */
|
||||
|
@ -386,7 +387,7 @@ class Controller
|
|||
return true;
|
||||
}
|
||||
|
||||
$from = $this->grav['config']->get('plugins.email.from');
|
||||
$from = $config->get('plugins.email.from');
|
||||
|
||||
if (empty($from)) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
|
@ -406,37 +407,18 @@ 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;
|
||||
$user->save();
|
||||
|
||||
$author = $this->grav['config']->get('site.author.name', '');
|
||||
$fullname = $user->fullname ?: $user->username;
|
||||
try {
|
||||
Email::sendResetPasswordEmail($user);
|
||||
|
||||
if ($this->grav['language']->getDefault() != $this->grav['language']->getLanguage()) {
|
||||
$lang = '/'.$this->grav['language']->getLanguage();
|
||||
} else {
|
||||
$lang = '';
|
||||
}
|
||||
|
||||
$resetRoute = $this->login->getRoute('reset');
|
||||
$reset_link = $this->grav['base_url_absolute'] . $lang . $resetRoute . '/task' . $param_sep . 'login.reset/token' . $param_sep . $token . '/user' . $param_sep . $user->username . '/nonce' . $param_sep . Utils::getNonce('reset-form');
|
||||
|
||||
$sitename = $this->grav['config']->get('site.title', 'Website');
|
||||
|
||||
$to = $user->email;
|
||||
|
||||
$subject = $language->translate(['PLUGIN_LOGIN.FORGOT_EMAIL_SUBJECT', $sitename]);
|
||||
$content = $language->translate(['PLUGIN_LOGIN.FORGOT_EMAIL_BODY', $fullname, $reset_link, $author, $sitename]);
|
||||
|
||||
$sent = EmailUtils::sendEmail($subject, $content, $to);
|
||||
|
||||
if ($sent < 1) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
} else {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
|
||||
} catch (\Exception $e) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* @package Grav\Plugin\Login
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2021 RocketTheme, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2014 - 2022 RocketTheme, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
|
@ -19,7 +19,7 @@ use RocketTheme\Toolbox\Event\Event;
|
|||
|
||||
/**
|
||||
* Class UserLoginEvent
|
||||
* @package Grav\Common\User\Events
|
||||
* @package Grav\Plugin\Login\Events
|
||||
*
|
||||
* @property int $status
|
||||
* @property array $credentials
|
||||
|
|
|
@ -24,7 +24,7 @@ use Grav\Common\User\Interfaces\UserCollectionInterface;
|
|||
use Grav\Common\User\Interfaces\UserInterface;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Plugin\Email\Utils as EmailUtils;
|
||||
use Grav\Plugin\Login\Events\PageAuthorizeEvent;
|
||||
use Grav\Plugin\Login\Events\UserLoginEvent;
|
||||
use Grav\Plugin\Login\Invitations\Invitation;
|
||||
use Grav\Plugin\Login\RememberMe\RememberMe;
|
||||
|
@ -445,25 +445,9 @@ class Login
|
|||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.USER_NEEDS_EMAIL_FIELD'));
|
||||
}
|
||||
|
||||
$site_name = $this->config->get('site.title', 'Website');
|
||||
|
||||
$subject = $this->language->translate(['PLUGIN_LOGIN.NOTIFICATION_EMAIL_SUBJECT', $site_name]);
|
||||
$content = $this->language->translate([
|
||||
'PLUGIN_LOGIN.NOTIFICATION_EMAIL_BODY',
|
||||
$site_name,
|
||||
$user->username,
|
||||
$user->email,
|
||||
$this->grav['base_url_absolute'],
|
||||
]);
|
||||
$to = $this->config->get('plugins.email.to');
|
||||
|
||||
if (empty($to)) {
|
||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_NOT_CONFIGURED'));
|
||||
}
|
||||
|
||||
$sent = EmailUtils::sendEmail($subject, $content, $to);
|
||||
|
||||
if ($sent < 1) {
|
||||
try {
|
||||
Email::sendNotificationEmail($user);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||
}
|
||||
|
||||
|
@ -484,22 +468,9 @@ class Login
|
|||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.USER_NEEDS_EMAIL_FIELD'));
|
||||
}
|
||||
|
||||
$site_name = $this->config->get('site.title', 'Website');
|
||||
$author = $this->grav['config']->get('site.author.name', '');
|
||||
$fullname = $user->fullname ?: $user->username;
|
||||
|
||||
$subject = $this->language->translate(['PLUGIN_LOGIN.WELCOME_EMAIL_SUBJECT', $site_name]);
|
||||
$content = $this->language->translate(['PLUGIN_LOGIN.WELCOME_EMAIL_BODY',
|
||||
$fullname,
|
||||
$this->grav['base_url_absolute'],
|
||||
$site_name,
|
||||
$author
|
||||
]);
|
||||
$to = $user->email;
|
||||
|
||||
$sent = EmailUtils::sendEmail($subject, $content, $to);
|
||||
|
||||
if ($sent < 1) {
|
||||
try {
|
||||
Email::sendWelcomeEmail($user);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||
}
|
||||
|
||||
|
@ -525,25 +496,9 @@ class Login
|
|||
$user->activation_token = $token . '::' . $expire;
|
||||
$user->save();
|
||||
|
||||
$param_sep = $this->config->get('system.param_sep', ':');
|
||||
$activationRoute = $this->getRoute('activate');
|
||||
$activation_link = $this->grav['base_url_absolute'] . $activationRoute . '/token' . $param_sep . $token . '/username' . $param_sep . $user->username;
|
||||
|
||||
$site_name = $this->config->get('site.title', 'Website');
|
||||
$author = $this->grav['config']->get('site.author.name', '');
|
||||
$fullname = $user->fullname ?: $user->username;
|
||||
|
||||
$subject = $this->language->translate(['PLUGIN_LOGIN.ACTIVATION_EMAIL_SUBJECT', $site_name]);
|
||||
$content = $this->language->translate(['PLUGIN_LOGIN.ACTIVATION_EMAIL_BODY',
|
||||
$fullname,
|
||||
$activation_link,
|
||||
$site_name,
|
||||
$author
|
||||
]);
|
||||
$to = $user->email;
|
||||
$sent = EmailUtils::sendEmail($subject, $content, $to);
|
||||
|
||||
if ($sent < 1) {
|
||||
try {
|
||||
Email::sendActivationEmail($user);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||
}
|
||||
|
||||
|
@ -561,27 +516,9 @@ class Login
|
|||
*/
|
||||
public function sendInviteEmail(Invitation $invitation, string $message = null, UserInterface $user = null)
|
||||
{
|
||||
/** @var UserInterface $user */
|
||||
$user = $user ?? $this->grav['user'];
|
||||
|
||||
$param_sep = $this->config->get('system.param_sep', ':');
|
||||
$inviteRoute = $this->getRoute('register', true);
|
||||
$invitationLink = $this->grav['base_url_absolute'] . "{$inviteRoute}/{$param_sep}{$invitation->token}";
|
||||
|
||||
$siteName = $this->config->get('site.title', 'Website');
|
||||
|
||||
$subject = $this->language->translate(['PLUGIN_LOGIN.INVITATION_EMAIL_SUBJECT', $siteName]);
|
||||
$message = $message ?? $this->language->translate(['PLUGIN_LOGIN.INVITATION_EMAIL_MESSAGE']);
|
||||
$content = $this->language->translate(['PLUGIN_LOGIN.INVITATION_EMAIL_BODY',
|
||||
$siteName,
|
||||
$message,
|
||||
$invitationLink,
|
||||
$user->fullname
|
||||
]);
|
||||
$to = $invitation->email;
|
||||
$sent = EmailUtils::sendEmail($subject, $content, $to);
|
||||
|
||||
if ($sent < 1) {
|
||||
try {
|
||||
Email::sendInvitationEmail($invitation, $message, $user);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||
}
|
||||
|
||||
|
@ -789,27 +726,15 @@ class Login
|
|||
* @param Data|null $config
|
||||
* @return bool
|
||||
*/
|
||||
public function isUserAuthorizedForPage(UserInterface $user, PageInterface $page, $config = null)
|
||||
public function isUserAuthorizedForPage(UserInterface $user, PageInterface $page, Data $config = null): bool
|
||||
{
|
||||
$header = $page->header();
|
||||
$rules = (array)($header->access ?? []);
|
||||
|
||||
if (!$rules && $config !== null && $config->get('parent_acl')) {
|
||||
// If page has no ACL rules, use its parent's rules
|
||||
$parent = $page->parent();
|
||||
while (!$rules and $parent) {
|
||||
$header = $parent->header();
|
||||
$rules = (array)($header->access ?? []);
|
||||
$parent = $parent->parent();
|
||||
}
|
||||
}
|
||||
|
||||
// Continue to the page if it has no ACL rules.
|
||||
if (!$rules) {
|
||||
/** @var PageAuthorizeEvent $event */
|
||||
$event = $this->grav->dispatchEvent(new PageAuthorizeEvent($page, $user, $config));
|
||||
if (!$event->hasProtectedAccess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// All protected pages have a private cache-control. This includes pages which are for guests only.
|
||||
// All access protected pages have a private cache-control. This includes pages which are for guests only.
|
||||
$cacheControl = $page->cacheControl();
|
||||
if (!$cacheControl) {
|
||||
$cacheControl = 'private, no-cache, must-revalidate';
|
||||
|
@ -831,28 +756,12 @@ class Login
|
|||
$page->cacheControl($cacheControl);
|
||||
|
||||
// Deny access if user has not completed 2FA challenge.
|
||||
$user = $event->user;
|
||||
if ($user->authenticated && !$user->authorized) {
|
||||
return false;
|
||||
$event->deny();
|
||||
}
|
||||
|
||||
// Continue to the page if user is authorized to access the page.
|
||||
foreach ($rules as $rule => $value) {
|
||||
if (is_int($rule)) {
|
||||
if ($user->authorize($value) === true) {
|
||||
return true;
|
||||
}
|
||||
} elseif (\is_array($value)) {
|
||||
foreach ($value as $nested_rule => $nested_value) {
|
||||
if ($user->authorize($rule . '.' . $nested_rule) === Utils::isPositive($nested_value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif ($user->authorize($rule) === Utils::isPositive($value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return $event->isAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
"docs": "https://github.com/getgrav/grav-plugin-login/blob/master/README.md"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"php": ">=7.3.6",
|
||||
"ext-json": "*",
|
||||
"birke/rememberme": "1.*",
|
||||
"robthree/twofactorauth": "^1.6",
|
||||
"birke/rememberme": "^1.0",
|
||||
"robthree/twofactorauth": "^1.8",
|
||||
"bacon/bacon-qr-code": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -43,7 +43,7 @@
|
|||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.1.3"
|
||||
"php": "7.3.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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": "bbcc2f78d1043e3e053994cf79736169",
|
||||
"content-hash": "a76edd1409f49153b8c55e0f6013ae17",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
@ -160,16 +160,16 @@
|
|||
},
|
||||
{
|
||||
"name": "robthree/twofactorauth",
|
||||
"version": "1.8.0",
|
||||
"version": "1.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
|
||||
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
||||
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/65681de5a324eae05140ac58b08648a60212afc0",
|
||||
"reference": "65681de5a324eae05140ac58b08648a60212afc0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -226,7 +226,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-09T18:24:05+00:00"
|
||||
"time": "2022-03-22T16:11:07+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
@ -236,12 +236,12 @@
|
|||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3",
|
||||
"php": ">=7.3.6",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.1.3"
|
||||
"php": "7.3.6"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.2.0"
|
||||
}
|
||||
|
|
|
@ -159,3 +159,4 @@ PLUGIN_LOGIN:
|
|||
INVITATION_EMAIL_MESSAGE: "We welcome you to register an account to on site."
|
||||
INVALID_INVITE_EMAILS: "<strong>Error:</strong> An invalid list of emails was provided"
|
||||
INVALID_FORM: "<strong>Error:</strong> Invalid form"
|
||||
FAILED_TO_SEND_EMAILS: "Failed to send emails to: %s"
|
|
@ -23,13 +23,16 @@ use Grav\Common\User\Interfaces\UserCollectionInterface;
|
|||
use Grav\Common\User\Interfaces\UserInterface;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Events\BeforeSessionStartEvent;
|
||||
use Grav\Events\PluginsLoadedEvent;
|
||||
use Grav\Events\SessionStartEvent;
|
||||
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||
use Grav\Framework\Form\Interfaces\FormInterface;
|
||||
use Grav\Framework\Psr7\Response;
|
||||
use Grav\Framework\Session\SessionInterface;
|
||||
use Grav\Plugin\Form\Form;
|
||||
use Grav\Plugin\Login\Events\PageAuthorizeEvent;
|
||||
use Grav\Plugin\Login\Events\UserLoginEvent;
|
||||
use Grav\Plugin\Login\Invitations\Invitation;
|
||||
use Grav\Plugin\Login\Invitations\Invitations;
|
||||
|
@ -38,6 +41,7 @@ use Grav\Plugin\Login\Controller;
|
|||
use Grav\Plugin\Login\RememberMe\RememberMe;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RocketTheme\Toolbox\Session\Message;
|
||||
use function is_array;
|
||||
|
||||
/**
|
||||
* Class LoginPlugin
|
||||
|
@ -59,6 +63,9 @@ class LoginPlugin extends Plugin
|
|||
/** @var Invitation|null */
|
||||
protected $invitation;
|
||||
|
||||
protected $temp_redirect;
|
||||
protected $temp_messages;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
@ -67,6 +74,8 @@ class LoginPlugin extends Plugin
|
|||
return [
|
||||
PluginsLoadedEvent::class => [['onPluginsLoaded', 10]],
|
||||
SessionStartEvent::class => ['onSessionStart', 0],
|
||||
BeforeSessionStartEvent::class => ['onBeforeSessionStart', 0],
|
||||
PageAuthorizeEvent::class => ['onPageAuthorizeEvent', -10000],
|
||||
'onPluginsInitialized' => [['initializeSession', 10000], ['initializeLogin', 1000]],
|
||||
'onTask.login.login' => ['loginController', 0],
|
||||
'onTask.login.twofa' => ['loginController', 0],
|
||||
|
@ -120,10 +129,35 @@ class LoginPlugin extends Plugin
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BeforeSessionStartEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onBeforeSessionStart(BeforeSessionStartEvent $event): void
|
||||
{
|
||||
$session = $event->session;
|
||||
$this->temp_redirect = $session->redirect_after_login ?? null;
|
||||
$this->temp_messages = $session->messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param SessionStartEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onSessionStart(SessionStartEvent $event): void
|
||||
{
|
||||
$session = $event->session;
|
||||
|
||||
if (isset($this->temp_redirect)) {
|
||||
$session->redirect_after_login = $this->temp_redirect;
|
||||
unset($this->temp_redirect);
|
||||
}
|
||||
if (isset($this->temp_messages)) {
|
||||
$session->messages = $this->temp_messages;
|
||||
unset($this->temp_messages);
|
||||
}
|
||||
|
||||
$user = $session->user ?? null;
|
||||
if ($user && $user->exists() && ($this->config()['session_user_sync'] ?? false)) {
|
||||
// User is stored into the filesystem.
|
||||
|
@ -303,7 +337,7 @@ class LoginPlugin extends Plugin
|
|||
if ($page) {
|
||||
$header = $page->header();
|
||||
|
||||
$allowed = ($header->login_redirect_here ?? true) === false;
|
||||
$allowed = ($header->login_redirect_here ?? true) === true;
|
||||
if ($allowed && $page->routable()) {
|
||||
$redirect = $page->route();
|
||||
foreach ($uri->params(null, true) as $key => $value) {
|
||||
|
@ -577,6 +611,67 @@ class LoginPlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PageAuthorizeEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function onPageAuthorizeEvent(PageAuthorizeEvent $event): void
|
||||
{
|
||||
if ($event->isDenied()) {
|
||||
// Deny access always wins.
|
||||
return;
|
||||
}
|
||||
|
||||
$page = $event->page;
|
||||
$header = $page->header();
|
||||
$rules = (array)($header->access ?? []);
|
||||
|
||||
if (!$rules && $event->config->get('parent_acl')) {
|
||||
// If page has no ACL rules, use its parent's rules
|
||||
$parent = $page->parent();
|
||||
while (!$rules and $parent) {
|
||||
$header = $parent->header();
|
||||
$rules = (array)($header->access ?? []);
|
||||
$parent = $parent->parent();
|
||||
}
|
||||
}
|
||||
|
||||
// Continue to the page if it has no access rules.
|
||||
if (!$rules) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the page to be protected by access rules.
|
||||
$event->setProtectedAccess();
|
||||
|
||||
// Continue to the page if user is authorized to access the page.
|
||||
$user = $event->user;
|
||||
foreach ($rules as $rule => $value) {
|
||||
if (is_int($rule)) {
|
||||
if ($user->authorize($value) === true) {
|
||||
$event->allow();
|
||||
|
||||
return;
|
||||
}
|
||||
} elseif (is_array($value)) {
|
||||
foreach ($value as $nested_rule => $nested_value) {
|
||||
if ($user->authorize($rule . '.' . $nested_rule) === Utils::isPositive($nested_value)) {
|
||||
$event->allow();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
} elseif ($user->authorize($rule) === Utils::isPositive($value)) {
|
||||
$event->allow();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No match, deny access.
|
||||
$event->deny();
|
||||
}
|
||||
|
||||
/**
|
||||
* [onPageInitialized] Authorize Page
|
||||
*/
|
||||
|
@ -590,7 +685,7 @@ class LoginPlugin extends Plugin
|
|||
$user = $this->grav['user'];
|
||||
|
||||
$page = $this->grav['page'] ?? null;
|
||||
if (!$page instanceof PageInterface) {
|
||||
if (!$page instanceof PageInterface || $page->isModule()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -603,8 +698,9 @@ class LoginPlugin extends Plugin
|
|||
$uri_extension = $this->grav['uri']->extension('html');
|
||||
$supported_types = $this->config->get('media.types');
|
||||
if ($uri_extension !== 'html' && array_key_exists($uri_extension, $supported_types)) {
|
||||
header('HTTP/1.0 403 Forbidden');
|
||||
exit;
|
||||
$response = new Response(403);
|
||||
|
||||
$this->grav->close($response);
|
||||
}
|
||||
|
||||
// User is not logged in; redirect to login page.
|
||||
|
@ -783,7 +879,7 @@ class LoginPlugin extends Plugin
|
|||
foreach ($default_values as $key => $param) {
|
||||
|
||||
if ($key === $field) {
|
||||
if (\is_array($param)) {
|
||||
if (is_array($param)) {
|
||||
$values = explode(',', $param);
|
||||
} else {
|
||||
$values = $param;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
composer.lock
|
||||
vendor
|
||||
nbproject
|
||||
.idea
|
||||
.buildpath
|
||||
.project
|
||||
.DS_Store
|
||||
.*.sw*
|
||||
.*.un~
|
|
@ -1,14 +0,0 @@
|
|||
language: php
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- hhvm
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction
|
||||
- composer info -i
|
||||
|
||||
script: vendor/bin/phpunit --bootstrap tests/bootstrap.php --configuration tests/phpunit.xml tests
|
|
@ -1,4 +0,0 @@
|
|||
.idea
|
||||
nbproject
|
||||
example/tokens
|
||||
/vendor/
|
|
@ -42,21 +42,75 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
|
@ -66,28 +120,47 @@ class ClassLoader
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
|
@ -103,8 +176,10 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -148,10 +223,12 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -196,7 +273,9 @@ class ClassLoader
|
|||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
|
@ -212,9 +291,11 @@ class ClassLoader
|
|||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
|
@ -234,6 +315,8 @@ class ClassLoader
|
|||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
|
@ -256,6 +339,8 @@ class ClassLoader
|
|||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
|
@ -276,6 +361,8 @@ class ClassLoader
|
|||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
|
@ -296,25 +383,44 @@ class ClassLoader
|
|||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
|
@ -323,6 +429,8 @@ class ClassLoader
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,6 +475,21 @@ class ClassLoader
|
|||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
|
@ -438,6 +561,10 @@ class ClassLoader
|
|||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
|
|
|
@ -1,124 +1,120 @@
|
|||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
private static $installed = array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517',
|
||||
'name' => 'getgrav/grav-plugin-login',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'bacon/bacon-qr-code' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5a91b62b9d37cee635bbf8d553f4546057250bee',
|
||||
),
|
||||
'birke/rememberme' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.5',
|
||||
'version' => '1.0.5.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '810473852eb4823098e47e23376a19b77ba0c165',
|
||||
),
|
||||
'getgrav/grav-plugin-login' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517',
|
||||
),
|
||||
'paragonie/random_compat' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.4.3',
|
||||
'version' => '1.4.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9b3899e3c3ddde89016f576edb8c489708ad64cd',
|
||||
),
|
||||
'robthree/twofactorauth' =>
|
||||
array (
|
||||
'pretty_version' => '1.8.0',
|
||||
'version' => '1.8.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
return array_keys(self::$installed['versions']);
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static function isInstalled($packageName)
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
return isset(self::$installed['versions'][$packageName]);
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
|
@ -127,129 +123,228 @@ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
|||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['version'])) {
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['version'];
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['pretty_version'];
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
if (!isset(self::$installed['versions'][$packageName])) {
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$installed['versions'][$packageName]['reference'];
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
return self::$installed['root'];
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366
|
|||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
|
@ -65,11 +65,16 @@ class ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequireeed5e5cf0aa1e2139f2db7445511e366($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,17 +150,17 @@
|
|||
},
|
||||
{
|
||||
"name": "robthree/twofactorauth",
|
||||
"version": "1.8.0",
|
||||
"version_normalized": "1.8.0.0",
|
||||
"version": "1.8.2",
|
||||
"version_normalized": "1.8.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
|
||||
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
||||
"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-03-09T18:24:05+00:00",
|
||||
"time": "2022-03-22T16:11:07+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
|
|
@ -1,60 +1,59 @@
|
|||
<?php return array(
|
||||
'root' =>
|
||||
array (
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
|
||||
'name' => 'getgrav/grav-plugin-login',
|
||||
'dev' => false,
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'bacon/bacon-qr-code' =>
|
||||
array (
|
||||
'versions' => array(
|
||||
'bacon/bacon-qr-code' => array(
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
|
||||
'aliases' => array(),
|
||||
'reference' => '5a91b62b9d37cee635bbf8d553f4546057250bee',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'birke/rememberme' =>
|
||||
array (
|
||||
'birke/rememberme' => array(
|
||||
'pretty_version' => '1.0.5',
|
||||
'version' => '1.0.5.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../birke/rememberme',
|
||||
'aliases' => array(),
|
||||
'reference' => '810473852eb4823098e47e23376a19b77ba0c165',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'getgrav/grav-plugin-login' =>
|
||||
array (
|
||||
'getgrav/grav-plugin-login' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'aliases' =>
|
||||
array (
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517',
|
||||
),
|
||||
'paragonie/random_compat' =>
|
||||
array (
|
||||
'paragonie/random_compat' => array(
|
||||
'pretty_version' => 'v1.4.3',
|
||||
'version' => '1.4.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||
'aliases' => array(),
|
||||
'reference' => '9b3899e3c3ddde89016f576edb8c489708ad64cd',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'robthree/twofactorauth' =>
|
||||
array (
|
||||
'pretty_version' => '1.8.0',
|
||||
'version' => '1.8.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
|
||||
'robthree/twofactorauth' => array(
|
||||
'pretty_version' => '1.8.2',
|
||||
'version' => '1.8.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../robthree/twofactorauth',
|
||||
'aliases' => array(),
|
||||
'reference' => '65681de5a324eae05140ac58b08648a60212afc0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70103)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.3". You are running ' . PHP_VERSION . '.';
|
||||
if (!(PHP_VERSION_ID >= 70306)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
coverage_clover: clover.xml
|
||||
json_path: coveralls-upload.json
|
|
@ -1,3 +0,0 @@
|
|||
/composer.lock
|
||||
/phpunit.xml
|
||||
/vendor/
|
|
@ -1,41 +0,0 @@
|
|||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- $HOME/.local
|
||||
- vendor
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 7.1
|
||||
env:
|
||||
- EXECUTE_CS_CHECK=true
|
||||
- EXECUTE_TEST_COVERALLS=true
|
||||
- PATH="$HOME/.local/bin:$PATH"
|
||||
- php: nightly
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
|
||||
before_install:
|
||||
- if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi
|
||||
- composer self-update
|
||||
- if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer require --dev --no-update satooshi/php-coveralls:dev-master ; fi
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction
|
||||
- composer info -i
|
||||
|
||||
script:
|
||||
- if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then vendor/bin/phpunit --coverage-clover clover.xml ; fi
|
||||
- if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then vendor/bin/phpunit ; fi
|
||||
- if [[ $EXECUTE_CS_CHECK == 'true' ]]; then vendor/bin/phpcs ; fi
|
||||
|
||||
after_script:
|
||||
- if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then vendor/bin/coveralls ; fi
|
||||
|
||||
notifications:
|
||||
email: true
|
30
plugins/login/vendor/robthree/twofactorauth/.github/workflows/test-bacon.yml
vendored
Normal file
30
plugins/login/vendor/robthree/twofactorauth/.github/workflows/test-bacon.yml
vendored
Normal 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
|
46
plugins/login/vendor/robthree/twofactorauth/.github/workflows/test-endroid.yml
vendored
Normal file
46
plugins/login/vendor/robthree/twofactorauth/.github/workflows/test-endroid.yml
vendored
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# If using the old MSBuild-Integrated Package Restore, uncomment this:
|
||||
#!**/packages/repositories.config
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# Composer
|
||||
/vendor
|
||||
composer.lock
|
||||
|
||||
# .vs
|
||||
.vs/
|
||||
|
||||
.phpunit.result.cache
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue