(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
|
# v1.10.37.1
|
||||||
## 10/08/2022
|
## 10/08/2022
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ edit_mode: normal
|
||||||
frontend_preview_target: inline
|
frontend_preview_target: inline
|
||||||
show_github_msg: true
|
show_github_msg: true
|
||||||
admin_icons: line-awesome
|
admin_icons: line-awesome
|
||||||
enable_auto_updates_check: false
|
enable_auto_updates_check: true
|
||||||
notifications:
|
notifications:
|
||||||
feed: true
|
feed: true
|
||||||
dashboard: true
|
dashboard: true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Admin Panel
|
name: Admin Panel
|
||||||
slug: admin
|
slug: admin
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 1.10.37.1
|
version: 1.10.39
|
||||||
description: Adds an advanced administration panel to manage your site
|
description: Adds an advanced administration panel to manage your site
|
||||||
icon: empire
|
icon: empire
|
||||||
author:
|
author:
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Cache;
|
use Grav\Common\Cache;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Backup\Backups;
|
use Grav\Common\Backup\Backups;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @package Grav\Plugin\Admin
|
* @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.
|
* @license MIT License; see LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Grav\Plugin\Admin;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Grav\Plugin\Admin\Controllers;
|
namespace Grav\Plugin\Admin\Controllers;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @package Grav\Plugin\Admin
|
* @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.
|
* @license MIT License; see LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @package Grav\Plugin\Admin
|
* @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.
|
* @license MIT License; see LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Cache;
|
use Grav\Common\Cache;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Config\Config;
|
use Grav\Common\Config\Config;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @package Grav\Plugin\Admin
|
* @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.
|
* @license MIT License; see LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use ScssPhp\ScssPhp\Compiler;
|
use ScssPhp\ScssPhp\Compiler;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
class ScssList
|
class ScssList
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin\Twig;
|
||||||
|
|
||||||
use Grav\Common\Data\Data;
|
use Grav\Common\Data\Data;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<?php
|
<?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;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Grav\Plugin\Admin;
|
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\Filesystem\Folder;
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
use Grav\Framework\File\File;
|
use Grav\Framework\File\File;
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.3.6 || ^8.0",
|
"php": "^7.3.6 || ^8.0",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"p3k/picofeed": "@stable",
|
|
||||||
"scssphp/scssphp": "^1.7",
|
"scssphp/scssphp": "^1.7",
|
||||||
"laminas/laminas-zendframework-bridge": "^1.4"
|
"laminas/laminas-zendframework-bridge": "^1.4",
|
||||||
|
"p3k/picofeed": "@stable"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"codeception/codeception": "^2.4",
|
"codeception/codeception": "^2.4",
|
||||||
|
@ -54,5 +54,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "vendor/bin/codecept run unit",
|
"test": "vendor/bin/codecept run unit",
|
||||||
"test-windows": "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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e95b50cceb85b45792cbca45623f6a91",
|
"content-hash": "1f6a6bec99c3a85ac753a1548c22f5d7",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "laminas/laminas-xml",
|
"name": "laminas/laminas-xml",
|
||||||
|
@ -130,16 +130,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "p3k/picofeed",
|
"name": "p3k/picofeed",
|
||||||
"version": "v0.1.40",
|
"version": "1.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aaronpk/picofeed.git",
|
"url": "https://github.com/rhukster/picofeed.git",
|
||||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c"
|
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/356fd66d48779193b10ac28532cb4a4e11bb801c",
|
"url": "https://api.github.com/repos/rhukster/picofeed/zipball/8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c",
|
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -171,7 +171,6 @@
|
||||||
"PicoFeed": "lib/"
|
"PicoFeed": "lib/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
"license": [
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
|
@ -183,10 +182,9 @@
|
||||||
"description": "Modern library to handle RSS/Atom feeds",
|
"description": "Modern library to handle RSS/Atom feeds",
|
||||||
"homepage": "https://github.com/aaronpk/picoFeed",
|
"homepage": "https://github.com/aaronpk/picoFeed",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/aaronpk/picofeed/issues",
|
"source": "https://github.com/rhukster/picofeed/tree/1.0.0"
|
||||||
"source": "https://github.com/aaronpk/picofeed/tree/v0.1.40"
|
|
||||||
},
|
},
|
||||||
"time": "2020-04-25T17:48:36+00:00"
|
"time": "2023-02-19T19:58:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "scssphp/scssphp",
|
"name": "scssphp/scssphp",
|
||||||
|
@ -512,30 +510,30 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.4.1",
|
"version": "1.5.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/instantiator.git",
|
"url": "https://github.com/doctrine/instantiator.git",
|
||||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1 || ^8.0"
|
"php": "^7.1 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9",
|
"doctrine/coding-standard": "^9 || ^11",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"phpbench/phpbench": "^0.16 || ^1",
|
"phpbench/phpbench": "^0.16 || ^1",
|
||||||
"phpstan/phpstan": "^1.4",
|
"phpstan/phpstan": "^1.4",
|
||||||
"phpstan/phpstan-phpunit": "^1",
|
"phpstan/phpstan-phpunit": "^1",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||||
"vimeo/psalm": "^4.22"
|
"vimeo/psalm": "^4.30 || ^5.4"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -562,7 +560,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -578,7 +576,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-03-03T08:28:38+00:00"
|
"time": "2022-12-30T00:15:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "facebook/webdriver",
|
"name": "facebook/webdriver",
|
||||||
|
@ -1341,27 +1339,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpspec/prophecy",
|
"name": "phpspec/prophecy",
|
||||||
"version": "v1.15.0",
|
"version": "v1.17.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpspec/prophecy.git",
|
"url": "https://github.com/phpspec/prophecy.git",
|
||||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
|
"reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/15873c65b207b07765dbc3c95d20fdf4a320cbe2",
|
||||||
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
|
"reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/instantiator": "^1.2",
|
"doctrine/instantiator": "^1.2 || ^2.0",
|
||||||
"php": "^7.2 || ~8.0, <8.2",
|
"php": "^7.2 || 8.0.* || 8.1.* || 8.2.*",
|
||||||
"phpdocumentor/reflection-docblock": "^5.2",
|
"phpdocumentor/reflection-docblock": "^5.2",
|
||||||
"sebastian/comparator": "^3.0 || ^4.0",
|
"sebastian/comparator": "^3.0 || ^4.0",
|
||||||
"sebastian/recursion-context": "^3.0 || ^4.0"
|
"sebastian/recursion-context": "^3.0 || ^4.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpspec/phpspec": "^6.0 || ^7.0",
|
"phpspec/phpspec": "^6.0 || ^7.0",
|
||||||
|
"phpstan/phpstan": "^1.9",
|
||||||
"phpunit/phpunit": "^8.0 || ^9.0"
|
"phpunit/phpunit": "^8.0 || ^9.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
@ -1402,9 +1401,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
"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",
|
"name": "phpunit/php-code-coverage",
|
||||||
|
@ -2668,16 +2667,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v4.4.45",
|
"version": "v4.4.49",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "28b77970939500fb04180166a1f716e75a871ef8"
|
"reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/28b77970939500fb04180166a1f716e75a871ef8",
|
"url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9",
|
||||||
"reference": "28b77970939500fb04180166a1f716e75a871ef8",
|
"reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2738,7 +2737,7 @@
|
||||||
"description": "Eases the creation of beautiful and testable command line interfaces",
|
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v4.4.45"
|
"source": "https://github.com/symfony/console/tree/v4.4.49"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2754,7 +2753,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-08-17T14:50:19+00:00"
|
"time": "2022-11-05T17:10:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
|
@ -3190,16 +3189,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.26.0",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3214,7 +3213,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.26-dev"
|
"dev-main": "1.27-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -3252,7 +3251,7 @@
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3268,20 +3267,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-24T11:49:31+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-idn",
|
"name": "symfony/polyfill-intl-idn",
|
||||||
"version": "v1.26.0",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
|
||||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3295,7 +3294,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.26-dev"
|
"dev-main": "1.27-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -3339,7 +3338,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3355,20 +3354,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-24T11:49:31+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-normalizer",
|
"name": "symfony/polyfill-intl-normalizer",
|
||||||
"version": "v1.26.0",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3380,7 +3379,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.26-dev"
|
"dev-main": "1.27-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -3423,7 +3422,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3439,20 +3438,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-24T11:49:31+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
"version": "v1.26.0",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3467,7 +3466,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.26-dev"
|
"dev-main": "1.27-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -3506,7 +3505,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3522,20 +3521,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-24T11:49:31+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php80",
|
"name": "symfony/polyfill-php80",
|
||||||
"version": "v1.26.0",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3544,7 +3543,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.26-dev"
|
"dev-main": "1.27-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -3589,7 +3588,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3605,7 +3604,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-05-10T07:21:04+00:00"
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
|
|
|
@ -3,8 +3,21 @@
|
||||||
// autoload.php @generated by Composer
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
if (PHP_VERSION_ID < 50600) {
|
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;
|
if (!headers_sent()) {
|
||||||
exit(1);
|
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';
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
|
@ -42,6 +42,9 @@ namespace Composer\Autoload;
|
||||||
*/
|
*/
|
||||||
class ClassLoader
|
class ClassLoader
|
||||||
{
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
/** @var ?string */
|
/** @var ?string */
|
||||||
private $vendorDir;
|
private $vendorDir;
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ class ClassLoader
|
||||||
public function __construct($vendorDir = null)
|
public function __construct($vendorDir = null)
|
||||||
{
|
{
|
||||||
$this->vendorDir = $vendorDir;
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -425,7 +429,8 @@ class ClassLoader
|
||||||
public function loadClass($class)
|
public function loadClass($class)
|
||||||
{
|
{
|
||||||
if ($file = $this->findFile($class)) {
|
if ($file = $this->findFile($class)) {
|
||||||
includeFile($file);
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -555,18 +560,26 @@ class ClassLoader
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scope isolated include.
|
* @return void
|
||||||
*
|
*/
|
||||||
* Prevents access to $this/self from included files.
|
private static function initializeIncludeClosure()
|
||||||
*
|
{
|
||||||
* @param string $file
|
if (self::$includeFile !== null) {
|
||||||
* @return void
|
return;
|
||||||
* @private
|
}
|
||||||
*/
|
|
||||||
function includeFile($file)
|
/**
|
||||||
{
|
* Scope isolated include.
|
||||||
include $file;
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,25 +33,18 @@ class ComposerAutoloaderInit98c98c1c3d67f21a128f935fe4a74897
|
||||||
|
|
||||||
$loader->register(true);
|
$loader->register(true);
|
||||||
|
|
||||||
$includeFiles = \Composer\Autoload\ComposerStaticInit98c98c1c3d67f21a128f935fe4a74897::$files;
|
$filesToLoad = \Composer\Autoload\ComposerStaticInit98c98c1c3d67f21a128f935fe4a74897::$files;
|
||||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||||
composerRequire98c98c1c3d67f21a128f935fe4a74897($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;
|
return $loader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $fileIdentifier
|
|
||||||
* @param string $file
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function composerRequire98c98c1c3d67f21a128f935fe4a74897($fileIdentifier, $file)
|
|
||||||
{
|
|
||||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
|
||||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
|
||||||
|
|
||||||
require $file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -130,17 +130,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "p3k/picofeed",
|
"name": "p3k/picofeed",
|
||||||
"version": "v0.1.40",
|
"version": "1.0.0",
|
||||||
"version_normalized": "0.1.40.0",
|
"version_normalized": "1.0.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aaronpk/picofeed.git",
|
"url": "https://github.com/rhukster/picofeed.git",
|
||||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c"
|
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/356fd66d48779193b10ac28532cb4a4e11bb801c",
|
"url": "https://api.github.com/repos/rhukster/picofeed/zipball/8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c",
|
"reference": "8eacaa62f50a0935e26ca33f8d30d283344ca397",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -163,7 +163,7 @@
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-curl": "PicoFeed will use cURL if present"
|
"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": [
|
"bin": [
|
||||||
"picofeed"
|
"picofeed"
|
||||||
],
|
],
|
||||||
|
@ -174,7 +174,6 @@
|
||||||
"PicoFeed": "lib/"
|
"PicoFeed": "lib/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
"license": [
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
|
@ -186,8 +185,7 @@
|
||||||
"description": "Modern library to handle RSS/Atom feeds",
|
"description": "Modern library to handle RSS/Atom feeds",
|
||||||
"homepage": "https://github.com/aaronpk/picoFeed",
|
"homepage": "https://github.com/aaronpk/picoFeed",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/aaronpk/picofeed/issues",
|
"source": "https://github.com/rhukster/picofeed/tree/1.0.0"
|
||||||
"source": "https://github.com/aaronpk/picofeed/tree/v0.1.40"
|
|
||||||
},
|
},
|
||||||
"install-path": "../p3k/picofeed"
|
"install-path": "../p3k/picofeed"
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
'name' => 'getgrav/grav-plugin-admin',
|
'name' => 'getgrav/grav-plugin-admin',
|
||||||
'pretty_version' => 'dev-develop',
|
'pretty_version' => 'dev-develop',
|
||||||
'version' => 'dev-develop',
|
'version' => 'dev-develop',
|
||||||
'reference' => '97ab52df8179fad32d1190b530c32053b84d5979',
|
'reference' => '0d16602880413bb6cbc2c94b75f02dce3174d215',
|
||||||
'type' => 'grav-plugin',
|
'type' => 'grav-plugin',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
'getgrav/grav-plugin-admin' => array(
|
'getgrav/grav-plugin-admin' => array(
|
||||||
'pretty_version' => 'dev-develop',
|
'pretty_version' => 'dev-develop',
|
||||||
'version' => 'dev-develop',
|
'version' => 'dev-develop',
|
||||||
'reference' => '97ab52df8179fad32d1190b530c32053b84d5979',
|
'reference' => '0d16602880413bb6cbc2c94b75f02dce3174d215',
|
||||||
'type' => 'grav-plugin',
|
'type' => 'grav-plugin',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
@ -44,9 +44,9 @@
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'p3k/picofeed' => array(
|
'p3k/picofeed' => array(
|
||||||
'pretty_version' => 'v0.1.40',
|
'pretty_version' => '1.0.0',
|
||||||
'version' => '0.1.40.0',
|
'version' => '1.0.0.0',
|
||||||
'reference' => '356fd66d48779193b10ac28532cb4a4e11bb801c',
|
'reference' => '8eacaa62f50a0935e26ca33f8d30d283344ca397',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../p3k/picofeed',
|
'install_path' => __DIR__ . '/../p3k/picofeed',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
|
@ -97,7 +97,7 @@ class DateParser extends Base
|
||||||
if ($date !== false) {
|
if ($date !== false) {
|
||||||
$errors = DateTime::getLastErrors();
|
$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;
|
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
|
# v1.3.1
|
||||||
## 09/08/2022
|
## 09/08/2022
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
{# FIXME: Search fields should be passed and individually customizable, right now defaulting to all fields selected #}
|
{# FIXME: Search fields should be passed and individually customizable, right now defaulting to all fields selected #}
|
||||||
{% set searchFields = searchFields|merge([key|replace({'.': '_'})]) %}
|
{% set searchFields = searchFields|merge([key|replace({'.': '_'})]) %}
|
||||||
{% endfor %}
|
{% 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 %}
|
{% set list = table.jsonSerialize %}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|tu }}
|
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|tu }}
|
||||||
</button>
|
</button>
|
||||||
{% if can_translate %}
|
{% if can_translate %}
|
||||||
{% set untranslated = admin_languages|array_diff(object_languages|merge([language])) %}
|
{% set untranslated = admin_languages|array_diff(object_languages) %}
|
||||||
{% if count(untranslated) %}
|
{% if count(untranslated) %}
|
||||||
<button id="titlebar-button-save" type="button" class="button success dropdown-toggle" data-toggle="dropdown">
|
<button id="titlebar-button-save" type="button" class="button success dropdown-toggle" data-toggle="dropdown">
|
||||||
<i class="fa fa-caret-down"></i>
|
<i class="fa fa-caret-down"></i>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{% set originalValue = value %}
|
{% set originalValue = value %}
|
||||||
{% set value = (value is null ? field.default : value) %}
|
{% set value = (value is null ? field.default : value) %}
|
||||||
{% set isNew = key ? false : true %}
|
{% 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 %}
|
{% 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'} %}
|
{% 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 %}
|
{% endif %}
|
||||||
|
|
||||||
{% block input %}
|
{% block input %}
|
||||||
{% set savedOption = not isNew and savedOption == 'create-new' ? 'edit' : savedOption %}
|
|
||||||
{% for key, text in options %}
|
{% for key, text in options %}
|
||||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Flex Objects
|
name: Flex Objects
|
||||||
slug: flex-objects
|
slug: flex-objects
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 1.3.1
|
version: 1.3.4
|
||||||
description: Flex Objects plugin allows you to manage Flex Objects in Grav Admin.
|
description: Flex Objects plugin allows you to manage Flex Objects in Grav Admin.
|
||||||
icon: list-alt
|
icon: list-alt
|
||||||
author:
|
author:
|
||||||
|
|
|
@ -907,6 +907,7 @@ class AdminController
|
||||||
// Set route to point to the current page.
|
// Set route to point to the current page.
|
||||||
if (!$this->redirect) {
|
if (!$this->redirect) {
|
||||||
$postAction = $request->getParsedBody()['_post_entries_save'] ?? 'edit';
|
$postAction = $request->getParsedBody()['_post_entries_save'] ?? 'edit';
|
||||||
|
$this->grav['session']->post_entries_save = $postAction;
|
||||||
if ($postAction === 'create-new') {
|
if ($postAction === 'create-new') {
|
||||||
// Create another.
|
// Create another.
|
||||||
$route = $this->referrerRoute->withGravParam('action', null)->withGravParam('', 'add');
|
$route = $this->referrerRoute->withGravParam('action', null)->withGravParam('', 'add');
|
||||||
|
|
|
@ -261,7 +261,7 @@ class FlexObjectsPlugin extends Plugin
|
||||||
if (!isset($form['flex']['key']) && $edit === true) {
|
if (!isset($form['flex']['key']) && $edit === true) {
|
||||||
/** @var Route $route */
|
/** @var Route $route */
|
||||||
$route = $this->grav['route'];
|
$route = $this->grav['route'];
|
||||||
$id = $route->getGravParam('id');
|
$id = rawurldecode($route->getGravParam('id'));
|
||||||
if (null !== $id) {
|
if (null !== $id) {
|
||||||
$form['flex']['key'] = $id;
|
$form['flex']['key'] = $id;
|
||||||
$event['form'] = $form;
|
$event['form'] = $form;
|
||||||
|
|
|
@ -13,6 +13,7 @@ PLUGIN_FLEX_OBJECTS:
|
||||||
DIRECTORIES: "Verzeichnisse"
|
DIRECTORIES: "Verzeichnisse"
|
||||||
CSV: "CSV"
|
CSV: "CSV"
|
||||||
PARENTS: "Eltern"
|
PARENTS: "Eltern"
|
||||||
|
NEW: "Neu"
|
||||||
|
|
||||||
CONTROLLER:
|
CONTROLLER:
|
||||||
TASK_DELETE_SUCCESS: 'Eintrag erfolgreich gelöscht'
|
TASK_DELETE_SUCCESS: 'Eintrag erfolgreich gelöscht'
|
||||||
|
@ -35,6 +36,7 @@ PLUGIN_FLEX_OBJECTS:
|
||||||
ADVANCED_OPTIONS: "Erweiterte Optionen"
|
ADVANCED_OPTIONS: "Erweiterte Optionen"
|
||||||
APPLY_FILTERS: "Filter anwenden"
|
APPLY_FILTERS: "Filter anwenden"
|
||||||
RESET_FILTERS: "Filter zurücksetzen"
|
RESET_FILTERS: "Filter zurücksetzen"
|
||||||
|
ACTIONS: "Aktionen"
|
||||||
|
|
||||||
FILTER:
|
FILTER:
|
||||||
PAGE_ATTRIBUTES: "Seitenattribute"
|
PAGE_ATTRIBUTES: "Seitenattribute"
|
||||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
||||||
CREATE_NEW: Create New Item
|
CREATE_NEW: Create New Item
|
||||||
EDIT_ITEM: Edit Item
|
EDIT_ITEM: Edit Item
|
||||||
LIST_ITEMS: "List Items"
|
LIST_ITEMS: "List Items"
|
||||||
LIST_ITEM: List Items
|
|
||||||
DELETE_N: "Delete" # In some languages 'delete OBJECT' may need a special declination
|
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?"
|
REALLY_DELETE: "Are you sure you want to permanently delete the %s?"
|
||||||
SEARCH_PLACEHOLDER: "Search…"
|
SEARCH_PLACEHOLDER: "Search…"
|
||||||
ADVANCED_OPTIONS: "Advanced Options"
|
ADVANCED_OPTIONS: "Advanced Options"
|
||||||
APPLY_FILTERS: "Apply Filters"
|
APPLY_FILTERS: "Apply Filters"
|
||||||
RESET_FILTERS: "Reset to Defaults"
|
RESET_FILTERS: "Reset to Defaults"
|
||||||
|
ACTIONS: "Actions"
|
||||||
|
|
||||||
FILTER:
|
FILTER:
|
||||||
PAGE_ATTRIBUTES: "Page Attributes"
|
PAGE_ATTRIBUTES: "Page Attributes"
|
||||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
||||||
CREATE_NEW: "Crear nuevo ítem"
|
CREATE_NEW: "Crear nuevo ítem"
|
||||||
EDIT_ITEM: "Editar ítem"
|
EDIT_ITEM: "Editar ítem"
|
||||||
LIST_ITEMS: "Listar ítems"
|
LIST_ITEMS: "Listar ítems"
|
||||||
LIST_ITEM: "Listar ítem"
|
|
||||||
DELETE_N: "Eliminar"
|
DELETE_N: "Eliminar"
|
||||||
REALLY_DELETE: "¿Realmente quieres eliminar %s permanentemente?"
|
REALLY_DELETE: "¿Realmente quieres eliminar %s permanentemente?"
|
||||||
SEARCH_PLACEHOLDER: "Buscar…"
|
SEARCH_PLACEHOLDER: "Buscar…"
|
||||||
ADVANCED_OPTIONS: "Opciones avazadas"
|
ADVANCED_OPTIONS: "Opciones avazadas"
|
||||||
APPLY_FILTERS: "Aplicar filtros"
|
APPLY_FILTERS: "Aplicar filtros"
|
||||||
RESET_FILTERS: "Restablecer filtros"
|
RESET_FILTERS: "Restablecer filtros"
|
||||||
|
ACTIONS: "Acciones"
|
||||||
|
|
||||||
FILTER:
|
FILTER:
|
||||||
PAGE_ATTRIBUTES: "Atributos de página"
|
PAGE_ATTRIBUTES: "Atributos de página"
|
||||||
|
|
|
@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
|
||||||
CREATE_NEW: 新しいデータを作成
|
CREATE_NEW: 新しいデータを作成
|
||||||
EDIT_ITEM: "データの編集"
|
EDIT_ITEM: "データの編集"
|
||||||
LIST_ITEMS: "データの一覧表示"
|
LIST_ITEMS: "データの一覧表示"
|
||||||
LIST_ITEM: データの一覧
|
|
||||||
DELETE_N: "削除" # In some languages 'delete OBJECT' may need a special declination
|
DELETE_N: "削除" # In some languages 'delete OBJECT' may need a special declination
|
||||||
REALLY_DELETE: "%s を削除します。復元はできませんがよろしいですか?"
|
REALLY_DELETE: "%s を削除します。復元はできませんがよろしいですか?"
|
||||||
SEARCH_PLACEHOLDER: "検索…"
|
SEARCH_PLACEHOLDER: "検索…"
|
||||||
ADVANCED_OPTIONS: "詳細設定"
|
ADVANCED_OPTIONS: "詳細設定"
|
||||||
APPLY_FILTERS: "フィルターを適用"
|
APPLY_FILTERS: "フィルターを適用"
|
||||||
RESET_FILTERS: "標準にリセットする"
|
RESET_FILTERS: "標準にリセットする"
|
||||||
|
ACTIONS: "アクション"
|
||||||
|
|
||||||
FILTER:
|
FILTER:
|
||||||
PAGE_ATTRIBUTES: "ページ属性"
|
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,9 +1,94 @@
|
||||||
|
# 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
|
# v5.1.6
|
||||||
## 02/07/2022
|
## 02/07/2022
|
||||||
|
|
||||||
1. [](#bugfix)
|
1. [](#bugfix)
|
||||||
* Fixed Select field when using OptGroups, not allowing key/values [#541](https://github.com/getgrav/grav-plugin-form/issues/541)
|
* Fixed Select field when using OptGroups, not allowing key/values [#541](https://github.com/getgrav/grav-plugin-form/issues/541)
|
||||||
* Support for translatable OptGroup labels in Select field [#540](https://github.com/getgrav/grav-plugin-form/issues/540)
|
* Support for translatable OptGroup labels in Select field [#540](https://github.com/getgrav/grav-plugin-form/issues/540)
|
||||||
|
|
||||||
# v5.1.5
|
# v5.1.5
|
||||||
## 01/24/2022
|
## 01/24/2022
|
||||||
|
|
|
@ -30,6 +30,8 @@ Note: when using email functionality in your forms, make sure you have configure
|
||||||
|
|
||||||
# NOTES:
|
# 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 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:
|
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
|
name: Form
|
||||||
slug: form
|
slug: form
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 5.1.6
|
version: 7.1.2
|
||||||
description: Enables the forms handling
|
description: Enables forms handling and processing
|
||||||
icon: check-square
|
icon: check-square
|
||||||
author:
|
author:
|
||||||
name: Team Grav
|
name: Team Grav
|
||||||
|
@ -196,3 +196,150 @@ form:
|
||||||
label: PLUGIN_FORM.RECAPTCHA_SECRET_KEY
|
label: PLUGIN_FORM.RECAPTCHA_SECRET_KEY
|
||||||
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
|
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
|
||||||
default: ''
|
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
|
||||||
|
|
|
@ -32,20 +32,20 @@ class BasicCaptcha
|
||||||
// calculator
|
// calculator
|
||||||
if ($operator === '-') {
|
if ($operator === '-') {
|
||||||
if ($first_num < $second_num) {
|
if ($first_num < $second_num) {
|
||||||
$result = "$second_num-$first_num";
|
$result = "$second_num - $first_num";
|
||||||
$captcha_code = $second_num-$first_num;
|
$captcha_code = $second_num - $first_num;
|
||||||
} else {
|
} else {
|
||||||
$result = "$first_num-$second_num";
|
$result = "$first_num-$second_num";
|
||||||
$captcha_code = $first_num - $second_num;
|
$captcha_code = $first_num - $second_num;
|
||||||
}
|
}
|
||||||
} elseif ($operator === '*') {
|
} elseif ($operator === '*') {
|
||||||
$result = "{$first_num}x{$second_num}";
|
$result = "{$first_num} x {$second_num}";
|
||||||
$captcha_code = $first_num - $second_num;
|
$captcha_code = $first_num * $second_num;
|
||||||
} elseif ($operator === '/') {
|
} elseif ($operator === '/') {
|
||||||
$result = "$first_num/ second_num";
|
$result = "$first_num / second_num";
|
||||||
$captcha_code = $first_num / $second_num;
|
$captcha_code = $first_num / $second_num;
|
||||||
} elseif ($operator === '+') {
|
} elseif ($operator === '+') {
|
||||||
$result = "$first_num+$second_num";
|
$result = "$first_num + $second_num";
|
||||||
$captcha_code = $first_num + $second_num;
|
$captcha_code = $first_num + $second_num;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Form implements FormInterface, ArrayAccess
|
||||||
$this->items = $form;
|
$this->items = $form;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise get all forms in the page.
|
// Otherwise get all forms in the page.
|
||||||
$forms = $page->forms();
|
$forms = $page->getForms();
|
||||||
if ($name) {
|
if ($name) {
|
||||||
// If form with given name was found, use that.
|
// If form with given name was found, use that.
|
||||||
$this->items = $forms[$name] ?? [];
|
$this->items = $forms[$name] ?? [];
|
||||||
|
|
|
@ -113,7 +113,7 @@ class Forms
|
||||||
*/
|
*/
|
||||||
protected function getPageParameters(PageInterface $page, ?string $name): array
|
protected function getPageParameters(PageInterface $page, ?string $name): array
|
||||||
{
|
{
|
||||||
$forms = $page->forms();
|
$forms = $page->getForms();
|
||||||
|
|
||||||
if ($name) {
|
if ($name) {
|
||||||
// If form with given name was found, use that.
|
// If form with given name was found, use that.
|
||||||
|
|
|
@ -90,21 +90,28 @@ class TwigExtension extends AbstractExtension
|
||||||
return null;
|
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).
|
// 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.
|
// 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.
|
// Make sure that the field has a name.
|
||||||
$name = $name ?? $field['name'] ?? null;
|
if ($name === '') {
|
||||||
if (!is_string($name) || $name === '') {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefix name with the parent name if needed.
|
// Prefix name with the parent name if needed.
|
||||||
if (str_starts_with($name, '.')) {
|
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'])) {
|
} elseif (isset($options['key'])) {
|
||||||
$name = str_replace('*', $options['key'], $name);
|
$name = str_replace('*', $options['key'], $name);
|
||||||
}
|
}
|
||||||
|
@ -125,6 +132,7 @@ class TwigExtension extends AbstractExtension
|
||||||
|
|
||||||
// Always set field name.
|
// Always set field name.
|
||||||
$field['name'] = $name;
|
$field['name'] = $name;
|
||||||
|
$field['prepared'] = true;
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,5 +73,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.3.6"
|
"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 Composer\Autoload\ClassLoader;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use Doctrine\Common\Cache\Cache;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Grav\Common\Data\ValidationException;
|
use Grav\Common\Data\ValidationException;
|
||||||
use Grav\Common\Debugger;
|
use Grav\Common\Debugger;
|
||||||
|
@ -18,10 +19,13 @@ use Grav\Common\Utils;
|
||||||
use Grav\Common\Uri;
|
use Grav\Common\Uri;
|
||||||
use Grav\Common\Yaml;
|
use Grav\Common\Yaml;
|
||||||
use Grav\Framework\Form\Interfaces\FormInterface;
|
use Grav\Framework\Form\Interfaces\FormInterface;
|
||||||
|
use Grav\Framework\Psr7\Response;
|
||||||
use Grav\Framework\Route\Route;
|
use Grav\Framework\Route\Route;
|
||||||
|
use Grav\Plugin\Form\BasicCaptcha;
|
||||||
use Grav\Plugin\Form\Form;
|
use Grav\Plugin\Form\Form;
|
||||||
use Grav\Plugin\Form\Forms;
|
use Grav\Plugin\Form\Forms;
|
||||||
use Grav\Plugin\Form\TwigExtension;
|
use Grav\Plugin\Form\TwigExtension;
|
||||||
|
use Grav\Common\HTTP\Client;
|
||||||
use ReCaptcha\ReCaptcha;
|
use ReCaptcha\ReCaptcha;
|
||||||
use ReCaptcha\RequestMethod\CurlPost;
|
use ReCaptcha\RequestMethod\CurlPost;
|
||||||
use RecursiveArrayIterator;
|
use RecursiveArrayIterator;
|
||||||
|
@ -31,6 +35,7 @@ use RocketTheme\Toolbox\File\YamlFile;
|
||||||
use RocketTheme\Toolbox\File\File;
|
use RocketTheme\Toolbox\File\File;
|
||||||
use RocketTheme\Toolbox\Event\Event;
|
use RocketTheme\Toolbox\Event\Event;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
use Twig\Environment;
|
use Twig\Environment;
|
||||||
use Twig\Extension\CoreExtension;
|
use Twig\Extension\CoreExtension;
|
||||||
use Twig\Extension\EscaperExtension;
|
use Twig\Extension\EscaperExtension;
|
||||||
|
@ -54,11 +59,9 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
/** @var Form */
|
/** @var Form */
|
||||||
protected $form;
|
protected $form;
|
||||||
/** @var array */
|
/** @var array[]|FormInterface[] */
|
||||||
protected $forms = [];
|
protected $forms = [];
|
||||||
/** @var array */
|
/** @var FormInterface[] */
|
||||||
protected $flat_forms = [];
|
|
||||||
/** @var array */
|
|
||||||
protected $active_forms = [];
|
protected $active_forms = [];
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $json_response = [];
|
protected $json_response = [];
|
||||||
|
@ -70,7 +73,7 @@ class FormPlugin extends Plugin
|
||||||
*/
|
*/
|
||||||
public static function checkRequirements(): bool
|
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 [
|
return [
|
||||||
'onPluginsInitialized' => [
|
'onPluginsInitialized' => ['onPluginsInitialized', 0],
|
||||||
['autoload', 100000],
|
|
||||||
['onPluginsInitialized', 0]
|
|
||||||
],
|
|
||||||
'onTwigExtensions' => ['onTwigExtensions', 0],
|
'onTwigExtensions' => ['onTwigExtensions', 0],
|
||||||
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0]
|
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [onPluginsInitialized:100000] Composer autoload.
|
|
||||||
*
|
|
||||||
* @return ClassLoader
|
* @return ClassLoader
|
||||||
*/
|
*/
|
||||||
public function autoload()
|
public function autoload()
|
||||||
|
@ -114,10 +112,9 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
$this->grav['forms'] = function () {
|
$this->grav['forms'] = function () {
|
||||||
$forms = new Forms();
|
$forms = new Forms();
|
||||||
|
|
||||||
$grav = Grav::instance();
|
|
||||||
$event = new Event(['forms' => $forms]);
|
$event = new Event(['forms' => $forms]);
|
||||||
$grav->fireEvent('onFormRegisterTypes', $event);
|
|
||||||
|
$this->grav->fireEvent('onFormRegisterTypes', $event);
|
||||||
|
|
||||||
return $forms;
|
return $forms;
|
||||||
};
|
};
|
||||||
|
@ -130,12 +127,19 @@ class FormPlugin extends Plugin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Uri $uri */
|
||||||
|
$uri = $this->grav['uri'];
|
||||||
|
|
||||||
// Mini Keep-Alive Logic
|
// Mini Keep-Alive Logic
|
||||||
$task = $this->grav['uri']->param('task');
|
$task = $uri->param('task');
|
||||||
if ($task && $task === 'keep-alive') {
|
if ($task === 'keep-alive') {
|
||||||
exit;
|
$response = new Response(200);
|
||||||
|
|
||||||
|
$this->grav->close($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->processBasicCaptchaImage($uri);
|
||||||
|
|
||||||
$this->enable([
|
$this->enable([
|
||||||
'onPageProcessed' => ['onPageProcessed', 0],
|
'onPageProcessed' => ['onPageProcessed', 0],
|
||||||
'onPagesInitialized' => ['onPagesInitialized', 0],
|
'onPagesInitialized' => ['onPagesInitialized', 0],
|
||||||
|
@ -161,16 +165,16 @@ class FormPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* Process forms after page header processing, but before caching
|
* Process forms after page header processing, but before caching
|
||||||
*
|
*
|
||||||
* @param Event $e
|
* @param Event $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onPageProcessed(Event $e): void
|
public function onPageProcessed(Event $event): void
|
||||||
{
|
{
|
||||||
/** @var PageInterface $page */
|
/** @var PageInterface $page */
|
||||||
$page = $e['page'];
|
$page = $event['page'];
|
||||||
|
|
||||||
$pageForms = $page->forms();
|
$forms = $page->getForms();
|
||||||
if (!$pageForms) {
|
if (!$forms) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,23 +188,18 @@ class FormPlugin extends Plugin
|
||||||
}
|
}
|
||||||
$parent = $current && $current !== $page ? $current : null;
|
$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 the form was in the modular page, we need to add the form into the parent page as well.
|
||||||
if ($parent) {
|
if ($parent) {
|
||||||
$parent->addForms($pageForms);
|
$parent->addForms($forms);
|
||||||
$parent_route = $parent->home() ? '/' : $parent->route();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Forms $forms */
|
|
||||||
$forms = $this->grav['forms'];
|
|
||||||
|
|
||||||
// Store the page forms in the forms instance
|
// Store the page forms in the forms instance
|
||||||
foreach ($pageForms as $name => $form) {
|
foreach ($forms as $name => $form) {
|
||||||
if (isset($parent, $parent_route)) {
|
if ($parent) {
|
||||||
$this->addForm($parent_route, $forms->createPageForm($parent, $name, $form));
|
$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) {
|
if ($form instanceof Form) {
|
||||||
// Post the form
|
// Post the form
|
||||||
$isJson = $uri->extension() === 'json';
|
$isJson = $uri->extension() === 'json';
|
||||||
$task = $uri->post('task') ?? $uri->param('task');
|
$task = (string)($uri->post('task') ?? $uri->param('task'));
|
||||||
|
|
||||||
if ($isJson) {
|
if ($isJson) {
|
||||||
if ($task === 'store-state') {
|
if ($task === 'store-state') {
|
||||||
|
@ -286,10 +285,13 @@ class FormPlugin extends Plugin
|
||||||
if ($this->json_response && $page->template() !== 'form') {
|
if ($this->json_response && $page->template() !== 'form') {
|
||||||
$status = $this->json_response['status'] ?? null;
|
$status = $this->json_response['status'] ?? null;
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
$response = new Response(
|
||||||
http_response_code($status === 'error' ? 400 : 200);
|
$status !== 'error' ? 200 : 400,
|
||||||
echo json_encode($this->json_response);
|
['Content-Type' => 'application/json'],
|
||||||
exit;
|
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.
|
// 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.
|
// 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 */
|
/** @var Route $route */
|
||||||
$route = $this->grav['route'];
|
$route = $this->grav['route'];
|
||||||
$pageForms = $this->forms[$route->getRoute()] ?? [];
|
$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')) {
|
if ($form->get('remember_redirect')) {
|
||||||
// Found one; we need to check if unique id is set.
|
// Found one; we need to check if unique id is set.
|
||||||
$formParam = $form->get('uniqueid_param', 'fid');
|
$formParam = $form->get('uniqueid_param', 'fid');
|
||||||
|
@ -328,8 +344,6 @@ class FormPlugin extends Plugin
|
||||||
$form->setUniqueId($uniqueId);
|
$form->setUniqueId($uniqueId);
|
||||||
$form->initialize();
|
$form->initialize();
|
||||||
|
|
||||||
/** @var Forms $forms */
|
|
||||||
$forms = $this->grav['forms'];
|
|
||||||
$forms->setActiveForm($form);
|
$forms->setActiveForm($form);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -337,7 +351,7 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
// Append unique id to the URL and redirect.
|
// Append unique id to the URL and redirect.
|
||||||
$route = $route->withGravParam($formParam, $form->getUniqueId());
|
$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?
|
// TODO: Do we want to add support for multiple forms with remembered state?
|
||||||
break;
|
break;
|
||||||
|
@ -398,7 +412,7 @@ class FormPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* Make form accessible from twig.
|
* Make form accessible from twig.
|
||||||
*
|
*
|
||||||
* @param Event $event
|
* @param Event|null $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onTwigVariables(Event $event = null): void
|
public function onTwigVariables(Event $event = null): void
|
||||||
|
@ -428,6 +442,7 @@ class FormPlugin extends Plugin
|
||||||
* @param Event $event
|
* @param Event $event
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
* @throws TransportExceptionInterface
|
||||||
*/
|
*/
|
||||||
public function onFormProcessed(Event $event): void
|
public function onFormProcessed(Event $event): void
|
||||||
{
|
{
|
||||||
|
@ -499,6 +514,55 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
return;
|
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;
|
break;
|
||||||
case 'timestamp':
|
case 'timestamp':
|
||||||
$label = $params['label'] ?? 'Timestamp';
|
$label = $params['label'] ?? 'Timestamp';
|
||||||
|
@ -544,8 +608,7 @@ class FormPlugin extends Plugin
|
||||||
$this->grav['messages']->add($form->message, 'success');
|
$this->grav['messages']->add($form->message, 'success');
|
||||||
}
|
}
|
||||||
|
|
||||||
$event['redirect'] = $url;
|
$this->grav->redirect($url);
|
||||||
$event->stopPropagation();
|
|
||||||
break;
|
break;
|
||||||
case 'reset':
|
case 'reset':
|
||||||
if (Utils::isPositive($params)) {
|
if (Utils::isPositive($params)) {
|
||||||
|
@ -736,6 +799,7 @@ class FormPlugin extends Plugin
|
||||||
*/
|
*/
|
||||||
public function onFormValidationError(Event $event): void
|
public function onFormValidationError(Event $event): void
|
||||||
{
|
{
|
||||||
|
/** @var FormInterface $form */
|
||||||
$form = $event['form'];
|
$form = $event['form'];
|
||||||
if (isset($event['message'])) {
|
if (isset($event['message'])) {
|
||||||
$form->status = 'error';
|
$form->status = 'error';
|
||||||
|
@ -743,6 +807,7 @@ class FormPlugin extends Plugin
|
||||||
$form->messages = $event['messages'];
|
$form->messages = $event['messages'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Uri $uri */
|
||||||
$uri = $this->grav['uri'];
|
$uri = $this->grav['uri'];
|
||||||
$route = $uri->route();
|
$route = $uri->route();
|
||||||
|
|
||||||
|
@ -752,8 +817,7 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
/** @var Pages $pages */
|
/** @var Pages $pages */
|
||||||
$pages = $this->grav['pages'];
|
$pages = $this->grav['pages'];
|
||||||
$page = $pages->dispatch($route, true);
|
$page = $pages->find($route, true);
|
||||||
|
|
||||||
if ($page) {
|
if ($page) {
|
||||||
unset($this->grav['page']);
|
unset($this->grav['page']);
|
||||||
$this->grav['page'] = $page;
|
$this->grav['page'] = $page;
|
||||||
|
@ -762,14 +826,32 @@ class FormPlugin extends Plugin
|
||||||
$event->stopPropagation();
|
$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
|
* Add a form to the forms plugin
|
||||||
*
|
*
|
||||||
* @param string|null $page_route
|
* @param string|null $route
|
||||||
* @param FormInterface|null $form
|
* @param FormInterface|null $form
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addForm(?string $page_route, ?FormInterface $form)
|
public function addForm(?string $route, ?FormInterface $form): void
|
||||||
{
|
{
|
||||||
if (null === $form) {
|
if (null === $form) {
|
||||||
return;
|
return;
|
||||||
|
@ -777,10 +859,10 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
$name = $form->getName();
|
$name = $form->getName();
|
||||||
|
|
||||||
if (!isset($this->forms[$page_route][$name])) {
|
if (!isset($this->forms[$route][$name])) {
|
||||||
$this->forms[$page_route][$name] = $form;
|
$form['_page_routable'] = true;
|
||||||
|
|
||||||
$this->flattenForms();
|
$this->forms[$route][$name] = $form;
|
||||||
$this->recache_forms = true;
|
$this->recache_forms = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,45 +870,128 @@ class FormPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* function to get a specific form
|
* 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
|
* @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)) {
|
if (is_array($data)) {
|
||||||
$form_name = $data['name'] ?? null;
|
$name = (string)($data['name'] ?? '');
|
||||||
$page_route = $data['route'] ?? null;
|
$route = (string)($data['route'] ?? '');
|
||||||
} elseif (is_string($data)) {
|
} elseif (is_string($data)) {
|
||||||
$form_name = $data;
|
$name = $data;
|
||||||
$page_route = null;
|
$route = '';
|
||||||
} else {
|
} else {
|
||||||
$form_name = null;
|
$name = '';
|
||||||
$page_route = null;
|
$route = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no form name, use the first form found in the page
|
// Return always the same form instance.
|
||||||
if (!$form_name) {
|
$form = $this->active_forms[$route][$name] ?? null;
|
||||||
// If page route not provided, use the current page
|
if ($form) {
|
||||||
if (!$page_route) {
|
return $form;
|
||||||
// Get page route with a fallback using current URI if page not initialized yet
|
|
||||||
$page_route = $this->grav['page']->route() ?: $this->getCurrentPageRoute();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->forms[$page_route])) {
|
|
||||||
$forms = $this->forms[$page_route];
|
|
||||||
$first_form = reset($forms) ?: null;
|
|
||||||
return $first_form;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get page by defined route first or get current if not found
|
|
||||||
$page = $this->grav['pages']->find($page_route) ?: $this->grav['page'];
|
|
||||||
|
|
||||||
// Try looking up in the defined page
|
|
||||||
return $this->grav['forms']->createPageForm($page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the form you are looking for if available
|
$unnamed = $name === '';
|
||||||
return $this->getFormByName($form_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to find the form from the page.
|
||||||
|
if ('' !== $route) {
|
||||||
|
$forms = $this->forms[$route] ?? [];
|
||||||
|
|
||||||
|
if (!$unnamed) {
|
||||||
|
// Get form by the name.
|
||||||
|
$form = $forms[$name] ?? null;
|
||||||
|
} else {
|
||||||
|
// Get the first form.
|
||||||
|
$form = reset($forms) ?: null;
|
||||||
|
$name = key($forms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getFormFieldTypes()
|
public function getFormFieldTypes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'avatar' => [
|
'avatar' => [
|
||||||
|
@ -906,7 +1071,7 @@ class FormPlugin extends Plugin
|
||||||
*
|
*
|
||||||
* - fillWithCurrentDateTime
|
* - fillWithCurrentDateTime
|
||||||
*
|
*
|
||||||
* @param Form $form
|
* @param FormInterface $form
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function process($form)
|
protected function process($form)
|
||||||
|
@ -921,43 +1086,33 @@ class FormPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* Get current page's route
|
* Get current page's route
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getCurrentPageRoute()
|
protected function getCurrentPageRoute()
|
||||||
{
|
{
|
||||||
$path = $this->grav['uri']->route();
|
$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 $name
|
||||||
* @param string $unique_id
|
* @return array
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
protected function getFormByName($form_name, $unique_id = '')
|
protected function findFormByName(string $name): array
|
||||||
{
|
{
|
||||||
$form = $this->active_forms[$form_name] ?? null;
|
$list = [];
|
||||||
if (!$form) {
|
foreach ($this->forms as $route => $forms) {
|
||||||
$form = $this->flat_forms[$form_name] ?? null;
|
foreach ($forms as $key => $form) {
|
||||||
|
if ($name === $key && !empty($form['_page_routable'])) {
|
||||||
if (!$form) {
|
$list[] = [$route, $key, $form];
|
||||||
return null;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function shouldProcessForm()
|
protected function shouldProcessForm(): bool
|
||||||
{
|
{
|
||||||
|
/** @var Uri $uri */
|
||||||
$uri = $this->grav['uri'];
|
$uri = $this->grav['uri'];
|
||||||
$nonce = $uri->post('form-nonce');
|
$status = (bool)$uri->post('form-nonce');
|
||||||
$status = $nonce ? true : false; // php72 quirk?
|
|
||||||
$refresh_prevention = null;
|
|
||||||
|
|
||||||
if ($status && $form = $this->form()) {
|
if ($status && $form = $this->form()) {
|
||||||
// Make sure form is something we recognize.
|
// Make sure form is something we recognize.
|
||||||
|
@ -1009,29 +1163,14 @@ class FormPlugin extends Plugin
|
||||||
return $status;
|
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
|
* Get the current form, should already be processed but can get it directly from the page if necessary
|
||||||
*
|
*
|
||||||
* @param PageInterface|null $page
|
* @param PageInterface|null $page
|
||||||
* @return Form|null
|
* @return FormInterface|null
|
||||||
*/
|
*/
|
||||||
protected function form(PageInterface $page = 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 */
|
/** @var Forms $forms */
|
||||||
$forms = $this->grav['forms'];
|
$forms = $this->grav['forms'];
|
||||||
|
|
||||||
|
@ -1050,11 +1189,16 @@ class FormPlugin extends Plugin
|
||||||
$form_name = $page ? $page->slug() : null;
|
$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
|
// last attempt using current page's form
|
||||||
if (!$form && $page) {
|
if (!$form && $page) {
|
||||||
$form = $forms->createPageForm($page);
|
$form = $this->createForm($page);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($form) {
|
if ($form) {
|
||||||
|
@ -1073,20 +1217,16 @@ class FormPlugin extends Plugin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PageInterface $page
|
* @param PageInterface $page
|
||||||
* @param string|int|null $name
|
* @param string|null $name
|
||||||
* @param array $form
|
* @param array|null $form
|
||||||
* @return Form|null
|
* @return FormInterface|null
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
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();
|
return $forms->createPageForm($page, $name, $form);
|
||||||
if (isset($header->form) || isset($header->forms)) {
|
|
||||||
return new Form($page, $name, $form);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1094,18 +1234,20 @@ class FormPlugin extends Plugin
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function loadCachedForms()
|
protected function loadCachedForms(): void
|
||||||
{
|
{
|
||||||
// Get and set the cache of forms if it exists
|
// Get and set the cache of forms if it exists
|
||||||
try {
|
try {
|
||||||
[$forms] = $this->grav['cache']->fetch($this->getFormCacheId());
|
/** @var Cache $cache */
|
||||||
} catch (Exception $e) {
|
$cache = $this->grav['cache'];
|
||||||
// Couldn't fetch cached forms.
|
|
||||||
$forms = null;
|
|
||||||
|
|
||||||
|
[$forms] = $cache->fetch($this->getFormCacheId());
|
||||||
|
} catch (Exception $e) {
|
||||||
/** @var Debugger $debugger */
|
/** @var Debugger $debugger */
|
||||||
$debugger = Grav::instance()['debugger'];
|
$debugger = Grav::instance()['debugger'];
|
||||||
$debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
$debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||||
|
|
||||||
|
$forms = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_array($forms)) {
|
if (!is_array($forms)) {
|
||||||
|
@ -1113,9 +1255,8 @@ class FormPlugin extends Plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only update the forms if it's not empty
|
// Only update the forms if it's not empty
|
||||||
if (!empty($forms)) {
|
if ($forms) {
|
||||||
$this->forms = array_merge($this->forms, $forms);
|
$this->forms = array_merge($this->forms, $forms);
|
||||||
$this->flattenForms();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,13 +1265,19 @@ class FormPlugin extends Plugin
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function saveCachedForms()
|
protected function saveCachedForms(): void
|
||||||
{
|
{
|
||||||
// Save the current state of the forms to cache
|
// Save the current state of the forms to cache
|
||||||
if ($this->recache_forms) {
|
if (!$this->recache_forms) {
|
||||||
$this->recache_forms = false;
|
return;
|
||||||
$this->grav['cache']->save($this->getFormCacheId(), [$this->forms]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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
|
* @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)
|
protected function udate($format = 'u', $raw = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
$utimestamp = microtime(true);
|
|
||||||
|
|
||||||
if ($raw) {
|
if ($raw) {
|
||||||
return date($format);
|
return date($format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$utimestamp = microtime(true);
|
||||||
$timestamp = floor($utimestamp);
|
$timestamp = floor($utimestamp);
|
||||||
$milliseconds = round(($utimestamp - $timestamp) * 1000000);
|
$milliseconds = round(($utimestamp - $timestamp) * 1000000);
|
||||||
|
|
||||||
return date(preg_replace('`(?<!\\\\)u`', sprintf('%06d', $milliseconds), $format), $timestamp);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,25 @@ recaptcha:
|
||||||
version: 2-checkbox
|
version: 2-checkbox
|
||||||
theme: light
|
theme: light
|
||||||
site_key:
|
site_key:
|
||||||
secret_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"
|
DESTINATION_HELP: "The location where the files should be uploaded to"
|
||||||
ACCEPT: "Allowed MIME Types"
|
ACCEPT: "Allowed MIME Types"
|
||||||
ACCEPT_HELP: "A list of MIME Types that are allowed for upload"
|
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"
|
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:"
|
DATA_SUMMARY: "Here is the summary of what you wrote to us:"
|
||||||
NO_FORM_DATA: "No form data available"
|
NO_FORM_DATA: "No form data available"
|
||||||
|
@ -72,6 +73,22 @@ en:
|
||||||
DESTINATION_NOT_SPECIFIED: "Destination not specified"
|
DESTINATION_NOT_SPECIFIED: "Destination not specified"
|
||||||
INVALID_MIME_TYPE: "The MIME type %s for the file %s is not accepted."
|
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."
|
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:
|
eu:
|
||||||
PLUGIN_FORM:
|
PLUGIN_FORM:
|
||||||
NOT_VALIDATED: "Formularioa ez da baliozkotu. Beharrezkoa den eremu bat edo gehiago falta dira."
|
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-active-color: #000;
|
||||||
|
|
||||||
.form-group.has-errors {
|
.form-group.has-errors {
|
||||||
|
@ -287,3 +287,29 @@ $form-active-color: #000;
|
||||||
display: inline-block;
|
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 default = field.default %}
|
||||||
{% set toggleable = field.toggleable ?? false %}
|
{% set toggleable = field.toggleable ?? false %}
|
||||||
{% if toggleable %}
|
{% if toggleable %}
|
||||||
{% set originalValue = originalValue is defined ? originalValue : value %}
|
{% set originalValue = originalValue ?? value %}
|
||||||
{% set toggleableChecked = originalValue is not null %}
|
{% set toggleableChecked = originalValue is not null %}
|
||||||
{% elseif field.overridable %}
|
{% elseif field.overridable %}
|
||||||
{% set toggleable = true %}
|
{% set toggleable = true %}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{% set fields = prepare_form_fields(fields, name) %}
|
{% set fields = prepare_form_fields(fields, name) %}
|
||||||
|
{% set originalValue = null %}
|
||||||
{% if fields|length %}
|
{% if fields|length %}
|
||||||
{% block outer_markup_field_open %}{% endblock %}
|
{% block outer_markup_field_open %}{% endblock %}
|
||||||
{% for field_name, field in fields %}
|
{% for field_name, field in fields %}
|
||||||
{% set value = form ? form.value(field.name) : data.value(field.name) %}
|
{% set value = form ? form.value(field.name) : data.value(field.name) %}
|
||||||
{% set field_templates = include_form_field(field.type, field_layout, fallback_field ?? 'text') %}
|
{% set field_templates = include_form_field(field.type, field_layout, fallback_field ?? 'text') %}
|
||||||
|
|
||||||
{% block inner_markup_field_open %}{% endblock %}
|
{% block inner_markup_field_open %}{% endblock %}
|
||||||
{% block field %}
|
{% block field %}
|
||||||
{% include field_templates %}
|
{% include field_templates %}
|
||||||
|
|
|
@ -145,6 +145,7 @@
|
||||||
|
|
||||||
{% if form.isEnabled() ?? true %}
|
{% if form.isEnabled() ?? true %}
|
||||||
{% for button in form.buttons %}
|
{% 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.outerclasses is defined %}<div class="{{ button.outerclasses }}">{% endif %}
|
||||||
|
|
||||||
{% if button.url %}
|
{% if button.url %}
|
||||||
|
@ -190,6 +191,7 @@
|
||||||
{% endembed %}
|
{% endembed %}
|
||||||
|
|
||||||
{% if button.outerclasses is defined %}</div>{% endif %}
|
{% if button.outerclasses is defined %}</div>{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% block prepend %}
|
{% block prepend %}
|
||||||
<div class="form-input-addon form-input-prepend">
|
<div class="form-input-addon form-input-prepend">
|
||||||
<img id="basic-captcha-reload" src="{{ url('/forms-basic-captcha-image.jpg') }}" alt="human test" />
|
<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>
|
<script>
|
||||||
function stripQueryString(url) {
|
function stripQueryString(url) {
|
||||||
return url.split("?")[0].split("#")[0];
|
return url.split("?")[0].split("#")[0];
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
{% extends "forms/field.html.twig" %}
|
{% 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 %}
|
{% block global_attributes %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
data-grav-keys="{{ field.use == 'keys' ? 'true' : 'false' }}"
|
data-grav-keys="{{ field.use == 'keys' ? 'true' : 'false' }}"
|
||||||
|
@ -13,6 +7,11 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block input %}
|
{% 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 %}
|
{% for key, text in field.options %}
|
||||||
|
|
||||||
{% set id = field.id|default(field.name)|hyphenize ~ '-' ~ key %}
|
{% set id = field.id|default(field.name)|hyphenize ~ '-' ~ key %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "forms/field.html.twig" %}
|
{% extends "forms/field.html.twig" %}
|
||||||
|
|
||||||
{% block field %}
|
{% 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_open %}<div class="form-column {{ field.classes }}">{% endblock %}
|
||||||
{% block outer_markup_field_close %}</div>{% endblock %}
|
{% block outer_markup_field_close %}</div>{% endblock %}
|
||||||
{% endembed %}
|
{% endembed %}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
{% block field %}
|
{% block field %}
|
||||||
<div class="form-columns {{ field.classes }}">
|
<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>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
{% extends "forms/field.html.twig" %}
|
{% extends "forms/field.html.twig" %}
|
||||||
|
|
||||||
{% set originalValue = value %}
|
|
||||||
{% set value = (value is null ? field.default : value) %}
|
|
||||||
|
|
||||||
{% block input %}
|
{% block input %}
|
||||||
{% for key, text in field.options %}
|
{% for key, text in field.options %}
|
||||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
data-{{ datakey }}="{{ datavalue|e('html_attr') }}"
|
data-{{ datakey }}="{{ datavalue|e('html_attr') }}"
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% 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 %}
|
{% 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 akey = field.selectize and field.multiple ? item_value : key %}
|
||||||
{% set avalue = item_value.value|t %}
|
{% set avalue = item_value.value|t %}
|
||||||
<option {{ item_value.disabled ? 'disabled="disabled"' : '' }}
|
<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 : '' }}
|
{{ item_value.label ? 'label=' ~ item_value.label : '' }}
|
||||||
value="{{ item_value.akey }}"
|
value="{{ akey }}"
|
||||||
>
|
>
|
||||||
{{ avalue|raw }}
|
{{ avalue|raw }}
|
||||||
</option>
|
</option>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends "forms/field.html.twig" %}
|
{% 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.vendor.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
||||||
{% do assets.addJs('plugin://form/assets/form.min.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
{% do assets.addJs('plugin://form/assets/form.min.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set tabsKey = form.name ~ '-' ~ fields|keys|join(':')|md5 %}
|
{% 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) %}
|
{% set storedTab = attribute(storedValue, 'tab-' ~ tabsKey) %}
|
||||||
{% if storedTab is empty %}
|
{% if storedTab is empty %}
|
||||||
{% set active = uri.params.tab ?? field.active ?? 1 %}
|
{% 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
|
class ClassLoader
|
||||||
{
|
{
|
||||||
|
/** @var ?string */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
// PSR-4
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
private $prefixLengthsPsr4 = array();
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<int, string>>
|
||||||
|
*/
|
||||||
private $prefixDirsPsr4 = array();
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $fallbackDirsPsr4 = array();
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
// PSR-0
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, string[]>>
|
||||||
|
*/
|
||||||
private $prefixesPsr0 = array();
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $fallbackDirsPsr0 = array();
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $useIncludePath = false;
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $classMap = array();
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $classMapAuthoritative = false;
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool[]
|
||||||
|
* @psalm-var array<string, bool>
|
||||||
|
*/
|
||||||
private $missingClasses = array();
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
private $apcuPrefix;
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var self[]
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ?string $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
public function getPrefixes()
|
public function getPrefixes()
|
||||||
{
|
{
|
||||||
if (!empty($this->prefixesPsr0)) {
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
@ -66,28 +120,47 @@ class ClassLoader
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
public function getPrefixesPsr4()
|
public function getPrefixesPsr4()
|
||||||
{
|
{
|
||||||
return $this->prefixDirsPsr4;
|
return $this->prefixDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getFallbackDirs()
|
public function getFallbackDirs()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr0;
|
return $this->fallbackDirsPsr0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getFallbackDirsPsr4()
|
public function getFallbackDirsPsr4()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr4;
|
return $this->fallbackDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] Array of classname => path
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getClassMap()
|
public function getClassMap()
|
||||||
{
|
{
|
||||||
return $this->classMap;
|
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)
|
public function addClassMap(array $classMap)
|
||||||
{
|
{
|
||||||
|
@ -102,9 +175,11 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix, either
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
* appending or prepending to the ones previously set for this prefix.
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The 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
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($prefix, $paths, $prepend = false)
|
public function add($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
@ -147,11 +222,13 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace, either
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
* appending or prepending to the ones previously set for this namespace.
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @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
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addPsr4($prefix, $paths, $prepend = false)
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
@ -195,8 +272,10 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix,
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
* replacing any others previously set for this prefix.
|
* replacing any others previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The 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)
|
public function set($prefix, $paths)
|
||||||
{
|
{
|
||||||
|
@ -211,10 +290,12 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace,
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
* replacing any others previously set for this namespace.
|
* replacing any others previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @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
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPsr4($prefix, $paths)
|
public function setPsr4($prefix, $paths)
|
||||||
{
|
{
|
||||||
|
@ -234,6 +315,8 @@ class ClassLoader
|
||||||
* Turns on searching the include path for class files.
|
* Turns on searching the include path for class files.
|
||||||
*
|
*
|
||||||
* @param bool $useIncludePath
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setUseIncludePath($useIncludePath)
|
public function setUseIncludePath($useIncludePath)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +339,8 @@ class ClassLoader
|
||||||
* that have not been registered with the class map.
|
* that have not been registered with the class map.
|
||||||
*
|
*
|
||||||
* @param bool $classMapAuthoritative
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
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.
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
*
|
*
|
||||||
* @param string|null $apcuPrefix
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setApcuPrefix($apcuPrefix)
|
public function setApcuPrefix($apcuPrefix)
|
||||||
{
|
{
|
||||||
|
@ -296,25 +383,44 @@ class ClassLoader
|
||||||
* Registers this instance as an autoloader.
|
* Registers this instance as an autoloader.
|
||||||
*
|
*
|
||||||
* @param bool $prepend Whether to prepend the autoloader or not
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register($prepend = false)
|
public function register($prepend = false)
|
||||||
{
|
{
|
||||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
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.
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function unregister()
|
public function unregister()
|
||||||
{
|
{
|
||||||
spl_autoload_unregister(array($this, 'loadClass'));
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the given class or interface.
|
* Loads the given class or interface.
|
||||||
*
|
*
|
||||||
* @param string $class The name of the class
|
* @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)
|
public function loadClass($class)
|
||||||
{
|
{
|
||||||
|
@ -323,6 +429,8 @@ class ClassLoader
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -367,6 +475,21 @@ class ClassLoader
|
||||||
return $file;
|
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)
|
private function findFileWithExtension($class, $ext)
|
||||||
{
|
{
|
||||||
// PSR-4 lookup
|
// PSR-4 lookup
|
||||||
|
@ -438,6 +561,10 @@ class ClassLoader
|
||||||
* Scope isolated include.
|
* Scope isolated include.
|
||||||
*
|
*
|
||||||
* Prevents access to $this/self from included files.
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function includeFile($file)
|
function includeFile($file)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,228 +1,350 @@
|
||||||
<?php
|
<?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;
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
use Composer\Semver\VersionParser;
|
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
|
class InstalledVersions
|
||||||
{
|
{
|
||||||
private static $installed = array (
|
/**
|
||||||
'root' =>
|
* @var mixed[]|null
|
||||||
array (
|
* @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
|
||||||
'pretty_version' => 'dev-develop',
|
*/
|
||||||
'version' => 'dev-develop',
|
private static $installed;
|
||||||
'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 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()
|
||||||
|
{
|
||||||
|
$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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
public static function getInstalledPackages()
|
foreach (self::getInstalled() as $installed) {
|
||||||
{
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
return array_keys(self::$installed['versions']);
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
}
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
public static function isInstalled($packageName)
|
*
|
||||||
{
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
return isset(self::$installed['versions'][$packageName]);
|
*
|
||||||
}
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
/**
|
||||||
{
|
* Checks whether the given package satisfies a version constraint
|
||||||
$constraint = $parser->parseConstraints($constraint);
|
*
|
||||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
return $provided->matches($constraint);
|
* 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);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
public static function getVersionRanges($packageName)
|
return $provided->matches($constraint);
|
||||||
{
|
}
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
/**
|
||||||
}
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
$ranges = array();
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
|
*
|
||||||
}
|
* @param string $packageName
|
||||||
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
|
* @return string Version constraint usable with composer/semver
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
|
*/
|
||||||
}
|
public static function getVersionRanges($packageName)
|
||||||
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
|
{
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
|
foreach (self::getInstalled() as $installed) {
|
||||||
}
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
|
continue;
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
|
}
|
||||||
}
|
|
||||||
|
$ranges = array();
|
||||||
return implode(' || ', $ranges);
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
}
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
public static function getVersion($packageName)
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
{
|
}
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$installed['versions'][$packageName]['version'])) {
|
return implode(' || ', $ranges);
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
return self::$installed['versions'][$packageName]['version'];
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
public static function getPrettyVersion($packageName)
|
{
|
||||||
{
|
foreach (self::getInstalled() as $installed) {
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$installed['versions'][$packageName]['pretty_version'];
|
return $installed['versions'][$packageName]['version'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static function getReference($packageName)
|
* @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
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
*/
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
public static function getPrettyVersion($packageName)
|
||||||
}
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
return null;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$installed['versions'][$packageName]['reference'];
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
public static function getRootPackage()
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
{
|
}
|
||||||
return self::$installed['root'];
|
|
||||||
}
|
/**
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
public static function getRawData()
|
continue;
|
||||||
{
|
}
|
||||||
return self::$installed;
|
|
||||||
}
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
public static function reload($data)
|
|
||||||
{
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
self::$installed = $data;
|
}
|
||||||
}
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
$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';
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
spl_autoload_register(array('ComposerAutoloaderInitd9f2f96e3ad6fd86ce688af0527a1d7b', 'loadClassLoader'), true, true);
|
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'));
|
spl_autoload_unregister(array('ComposerAutoloaderInitd9f2f96e3ad6fd86ce688af0527a1d7b', 'loadClassLoader'));
|
||||||
|
|
||||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
$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"
|
"install-path": "../google/recaptcha"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dev": false,
|
"dev": true,
|
||||||
"dev-package-names": []
|
"dev-package-names": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,32 @@
|
||||||
<?php return array (
|
<?php return array(
|
||||||
'root' =>
|
'root' => array(
|
||||||
array (
|
'pretty_version' => 'dev-develop',
|
||||||
'pretty_version' => 'dev-develop',
|
'version' => 'dev-develop',
|
||||||
'version' => 'dev-develop',
|
'type' => 'grav-plugin',
|
||||||
'aliases' =>
|
'install_path' => __DIR__ . '/../../',
|
||||||
array (
|
'aliases' => array(),
|
||||||
|
'reference' => '2e6d16dbc801d605f56d2d2942cd99a8bf63550c',
|
||||||
|
'name' => 'getgrav/grav-plugin-form',
|
||||||
|
'dev' => true,
|
||||||
),
|
),
|
||||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
'versions' => array(
|
||||||
'name' => 'getgrav/grav-plugin-form',
|
'getgrav/grav-plugin-form' => array(
|
||||||
),
|
'pretty_version' => 'dev-develop',
|
||||||
'versions' =>
|
'version' => 'dev-develop',
|
||||||
array (
|
'type' => 'grav-plugin',
|
||||||
'getgrav/grav-plugin-form' =>
|
'install_path' => __DIR__ . '/../../',
|
||||||
array (
|
'aliases' => array(),
|
||||||
'pretty_version' => 'dev-develop',
|
'reference' => '2e6d16dbc801d605f56d2d2942cd99a8bf63550c',
|
||||||
'version' => 'dev-develop',
|
'dev_requirement' => false,
|
||||||
'aliases' =>
|
),
|
||||||
array (
|
'google/recaptcha' => array(
|
||||||
),
|
'pretty_version' => '1.2.4',
|
||||||
'reference' => 'd53d3124481c8a72f223c49a03e6fd9b1f5bd7ee',
|
'version' => '1.2.4.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/recaptcha',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '614f25a9038be4f3f2da7cbfd778dc5b357d2419',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
'google/recaptcha' =>
|
|
||||||
array (
|
|
||||||
'pretty_version' => '1.2.4',
|
|
||||||
'version' => '1.2.4.0',
|
|
||||||
'aliases' =>
|
|
||||||
array (
|
|
||||||
),
|
|
||||||
'reference' => '614f25a9038be4f3f2da7cbfd778dc5b357d2419',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
# v3.6.2
|
||||||
## 01/12/2022
|
## 01/12/2022
|
||||||
|
|
||||||
|
@ -10,7 +46,7 @@
|
||||||
|
|
||||||
1. [](#bugfix)
|
1. [](#bugfix)
|
||||||
* Fixed issue with forgot password error message translation [#285](https://github.com/getgrav/grav-plugin-login/pull/285)
|
* Fixed issue with forgot password error message translation [#285](https://github.com/getgrav/grav-plugin-login/pull/285)
|
||||||
*
|
|
||||||
# v3.6.0
|
# v3.6.0
|
||||||
## 10/26/2021
|
## 10/26/2021
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Login
|
name: Login
|
||||||
slug: login
|
slug: login
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 3.6.2
|
version: 3.7.3
|
||||||
testing: false
|
testing: false
|
||||||
description: Enables user authentication and login screen.
|
description: Enables user authentication and login screen.
|
||||||
icon: sign-in
|
icon: sign-in
|
||||||
|
@ -15,9 +15,9 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues
|
||||||
license: MIT
|
license: MIT
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- { name: grav, version: '>=1.7.27' }
|
- { name: grav, version: '>=1.7.38' }
|
||||||
- { name: form, version: '>=5.1.0' }
|
- { name: form, version: '>=6.0.0' }
|
||||||
- { name: email, version: '>=3.1.0' }
|
- { name: email, version: '>=3.1.6' }
|
||||||
|
|
||||||
form:
|
form:
|
||||||
validation: loose
|
validation: loose
|
||||||
|
|
|
@ -12,12 +12,12 @@ namespace Grav\Plugin\Login;
|
||||||
use Grav\Common\Config\Config;
|
use Grav\Common\Config\Config;
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
use Grav\Common\Language\Language;
|
use Grav\Common\Language\Language;
|
||||||
|
use Grav\Common\Page\Pages;
|
||||||
use Grav\Common\Uri;
|
use Grav\Common\Uri;
|
||||||
use Grav\Common\User\Interfaces\UserCollectionInterface;
|
use Grav\Common\User\Interfaces\UserCollectionInterface;
|
||||||
use Grav\Common\User\Interfaces\UserInterface;
|
use Grav\Common\User\Interfaces\UserInterface;
|
||||||
use Grav\Common\Utils;
|
use Grav\Common\Utils;
|
||||||
use Grav\Plugin\Email\Utils as EmailUtils;
|
use Grav\Plugin\Email\Utils as EmailUtils;
|
||||||
use Grav\Plugin\Form\Form;
|
|
||||||
use Grav\Plugin\Form\Forms;
|
use Grav\Plugin\Form\Forms;
|
||||||
use Grav\Plugin\Login\Events\UserLoginEvent;
|
use Grav\Plugin\Login\Events\UserLoginEvent;
|
||||||
use Grav\Plugin\Login\Invitations\Invitation;
|
use Grav\Plugin\Login\Invitations\Invitation;
|
||||||
|
@ -343,7 +343,8 @@ class Controller
|
||||||
*/
|
*/
|
||||||
protected function taskForgot()
|
protected function taskForgot()
|
||||||
{
|
{
|
||||||
$param_sep = $this->grav['config']->get('system.param_sep', ':');
|
/** @var Config $config */
|
||||||
|
$config = $this->grav['config'];
|
||||||
$data = $this->post;
|
$data = $this->post;
|
||||||
|
|
||||||
/** @var UserCollectionInterface $users */
|
/** @var UserCollectionInterface $users */
|
||||||
|
@ -386,7 +387,7 @@ class Controller
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$from = $this->grav['config']->get('plugins.email.from');
|
$from = $config->get('plugins.email.from');
|
||||||
|
|
||||||
if (empty($from)) {
|
if (empty($from)) {
|
||||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||||
|
@ -406,37 +407,18 @@ class Controller
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = md5(uniqid(mt_rand(), true));
|
$token = md5(uniqid((string)mt_rand(), true));
|
||||||
$expire = time() + 604800; // next week
|
$expire = time() + 604800; // next week
|
||||||
|
|
||||||
$user->reset = $token . '::' . $expire;
|
$user->reset = $token . '::' . $expire;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
$author = $this->grav['config']->get('site.author.name', '');
|
try {
|
||||||
$fullname = $user->fullname ?: $user->username;
|
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');
|
$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') ?? '/');
|
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @package Grav\Plugin\Login
|
* @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.
|
* @license MIT License; see LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ use RocketTheme\Toolbox\Event\Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserLoginEvent
|
* Class UserLoginEvent
|
||||||
* @package Grav\Common\User\Events
|
* @package Grav\Plugin\Login\Events
|
||||||
*
|
*
|
||||||
* @property int $status
|
* @property int $status
|
||||||
* @property array $credentials
|
* @property array $credentials
|
||||||
|
|
|
@ -24,7 +24,7 @@ use Grav\Common\User\Interfaces\UserCollectionInterface;
|
||||||
use Grav\Common\User\Interfaces\UserInterface;
|
use Grav\Common\User\Interfaces\UserInterface;
|
||||||
use Grav\Common\Uri;
|
use Grav\Common\Uri;
|
||||||
use Grav\Common\Utils;
|
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\Events\UserLoginEvent;
|
||||||
use Grav\Plugin\Login\Invitations\Invitation;
|
use Grav\Plugin\Login\Invitations\Invitation;
|
||||||
use Grav\Plugin\Login\RememberMe\RememberMe;
|
use Grav\Plugin\Login\RememberMe\RememberMe;
|
||||||
|
@ -445,25 +445,9 @@ class Login
|
||||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.USER_NEEDS_EMAIL_FIELD'));
|
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.USER_NEEDS_EMAIL_FIELD'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$site_name = $this->config->get('site.title', 'Website');
|
try {
|
||||||
|
Email::sendNotificationEmail($user);
|
||||||
$subject = $this->language->translate(['PLUGIN_LOGIN.NOTIFICATION_EMAIL_SUBJECT', $site_name]);
|
} catch (\Exception $e) {
|
||||||
$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) {
|
|
||||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
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'));
|
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.USER_NEEDS_EMAIL_FIELD'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$site_name = $this->config->get('site.title', 'Website');
|
try {
|
||||||
$author = $this->grav['config']->get('site.author.name', '');
|
Email::sendWelcomeEmail($user);
|
||||||
$fullname = $user->fullname ?: $user->username;
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
$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) {
|
|
||||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,25 +496,9 @@ class Login
|
||||||
$user->activation_token = $token . '::' . $expire;
|
$user->activation_token = $token . '::' . $expire;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
$param_sep = $this->config->get('system.param_sep', ':');
|
try {
|
||||||
$activationRoute = $this->getRoute('activate');
|
Email::sendActivationEmail($user);
|
||||||
$activation_link = $this->grav['base_url_absolute'] . $activationRoute . '/token' . $param_sep . $token . '/username' . $param_sep . $user->username;
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
$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) {
|
|
||||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
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)
|
public function sendInviteEmail(Invitation $invitation, string $message = null, UserInterface $user = null)
|
||||||
{
|
{
|
||||||
/** @var UserInterface $user */
|
try {
|
||||||
$user = $user ?? $this->grav['user'];
|
Email::sendInvitationEmail($invitation, $message, $user);
|
||||||
|
} catch (\Exception $e) {
|
||||||
$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) {
|
|
||||||
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
throw new \RuntimeException($this->language->translate('PLUGIN_LOGIN.EMAIL_SENDING_FAILURE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,27 +726,15 @@ class Login
|
||||||
* @param Data|null $config
|
* @param Data|null $config
|
||||||
* @return bool
|
* @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();
|
/** @var PageAuthorizeEvent $event */
|
||||||
$rules = (array)($header->access ?? []);
|
$event = $this->grav->dispatchEvent(new PageAuthorizeEvent($page, $user, $config));
|
||||||
|
if (!$event->hasProtectedAccess()) {
|
||||||
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) {
|
|
||||||
return true;
|
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();
|
$cacheControl = $page->cacheControl();
|
||||||
if (!$cacheControl) {
|
if (!$cacheControl) {
|
||||||
$cacheControl = 'private, no-cache, must-revalidate';
|
$cacheControl = 'private, no-cache, must-revalidate';
|
||||||
|
@ -831,28 +756,12 @@ class Login
|
||||||
$page->cacheControl($cacheControl);
|
$page->cacheControl($cacheControl);
|
||||||
|
|
||||||
// Deny access if user has not completed 2FA challenge.
|
// Deny access if user has not completed 2FA challenge.
|
||||||
|
$user = $event->user;
|
||||||
if ($user->authenticated && !$user->authorized) {
|
if ($user->authenticated && !$user->authorized) {
|
||||||
return false;
|
$event->deny();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue to the page if user is authorized to access the page.
|
return $event->isAllowed();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
"docs": "https://github.com/getgrav/grav-plugin-login/blob/master/README.md"
|
"docs": "https://github.com/getgrav/grav-plugin-login/blob/master/README.md"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1.3",
|
"php": ">=7.3.6",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"birke/rememberme": "1.*",
|
"birke/rememberme": "^1.0",
|
||||||
"robthree/twofactorauth": "^1.6",
|
"robthree/twofactorauth": "^1.8",
|
||||||
"bacon/bacon-qr-code": "^1.0"
|
"bacon/bacon-qr-code": "^1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"platform": {
|
"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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "bbcc2f78d1043e3e053994cf79736169",
|
"content-hash": "a76edd1409f49153b8c55e0f6013ae17",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
|
@ -160,16 +160,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "robthree/twofactorauth",
|
"name": "robthree/twofactorauth",
|
||||||
"version": "1.8.0",
|
"version": "1.8.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
||||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
|
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/65681de5a324eae05140ac58b08648a60212afc0",
|
||||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
"reference": "65681de5a324eae05140ac58b08648a60212afc0",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -226,7 +226,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-03-09T18:24:05+00:00"
|
"time": "2022-03-22T16:11:07+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
@ -236,12 +236,12 @@
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=7.1.3",
|
"php": ">=7.3.6",
|
||||||
"ext-json": "*"
|
"ext-json": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.1.3"
|
"php": "7.3.6"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.0.0"
|
"plugin-api-version": "2.2.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,4 +158,5 @@ PLUGIN_LOGIN:
|
||||||
INVITATION_EMAIL_BODY: "<h1>Account Invitation</h1><p>Hi, </p><p>You have been invited to join <b>%1$s</b>.</p><p>%2$s</p><p><br/><a href=\"%3$s\" class=\"btn-primary\">Create Your Account Now</a><br/><br/></p><p>Alternatively, copy the following URL into your browser's address bar:</p><p class=\"word-break\"><a href=\"%3$s\">%3$s</a></p><p><br/>Kind regards,<br/><br/>%4$s</p>"
|
INVITATION_EMAIL_BODY: "<h1>Account Invitation</h1><p>Hi, </p><p>You have been invited to join <b>%1$s</b>.</p><p>%2$s</p><p><br/><a href=\"%3$s\" class=\"btn-primary\">Create Your Account Now</a><br/><br/></p><p>Alternatively, copy the following URL into your browser's address bar:</p><p class=\"word-break\"><a href=\"%3$s\">%3$s</a></p><p><br/>Kind regards,<br/><br/>%4$s</p>"
|
||||||
INVITATION_EMAIL_MESSAGE: "We welcome you to register an account to on site."
|
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_INVITE_EMAILS: "<strong>Error:</strong> An invalid list of emails was provided"
|
||||||
INVALID_FORM: "<strong>Error:</strong> Invalid form"
|
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\User\Interfaces\UserInterface;
|
||||||
use Grav\Common\Utils;
|
use Grav\Common\Utils;
|
||||||
use Grav\Common\Uri;
|
use Grav\Common\Uri;
|
||||||
|
use Grav\Events\BeforeSessionStartEvent;
|
||||||
use Grav\Events\PluginsLoadedEvent;
|
use Grav\Events\PluginsLoadedEvent;
|
||||||
use Grav\Events\SessionStartEvent;
|
use Grav\Events\SessionStartEvent;
|
||||||
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
|
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
|
||||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||||
use Grav\Framework\Form\Interfaces\FormInterface;
|
use Grav\Framework\Form\Interfaces\FormInterface;
|
||||||
|
use Grav\Framework\Psr7\Response;
|
||||||
use Grav\Framework\Session\SessionInterface;
|
use Grav\Framework\Session\SessionInterface;
|
||||||
use Grav\Plugin\Form\Form;
|
use Grav\Plugin\Form\Form;
|
||||||
|
use Grav\Plugin\Login\Events\PageAuthorizeEvent;
|
||||||
use Grav\Plugin\Login\Events\UserLoginEvent;
|
use Grav\Plugin\Login\Events\UserLoginEvent;
|
||||||
use Grav\Plugin\Login\Invitations\Invitation;
|
use Grav\Plugin\Login\Invitations\Invitation;
|
||||||
use Grav\Plugin\Login\Invitations\Invitations;
|
use Grav\Plugin\Login\Invitations\Invitations;
|
||||||
|
@ -38,6 +41,7 @@ use Grav\Plugin\Login\Controller;
|
||||||
use Grav\Plugin\Login\RememberMe\RememberMe;
|
use Grav\Plugin\Login\RememberMe\RememberMe;
|
||||||
use RocketTheme\Toolbox\Event\Event;
|
use RocketTheme\Toolbox\Event\Event;
|
||||||
use RocketTheme\Toolbox\Session\Message;
|
use RocketTheme\Toolbox\Session\Message;
|
||||||
|
use function is_array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LoginPlugin
|
* Class LoginPlugin
|
||||||
|
@ -59,6 +63,9 @@ class LoginPlugin extends Plugin
|
||||||
/** @var Invitation|null */
|
/** @var Invitation|null */
|
||||||
protected $invitation;
|
protected $invitation;
|
||||||
|
|
||||||
|
protected $temp_redirect;
|
||||||
|
protected $temp_messages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -67,6 +74,8 @@ class LoginPlugin extends Plugin
|
||||||
return [
|
return [
|
||||||
PluginsLoadedEvent::class => [['onPluginsLoaded', 10]],
|
PluginsLoadedEvent::class => [['onPluginsLoaded', 10]],
|
||||||
SessionStartEvent::class => ['onSessionStart', 0],
|
SessionStartEvent::class => ['onSessionStart', 0],
|
||||||
|
BeforeSessionStartEvent::class => ['onBeforeSessionStart', 0],
|
||||||
|
PageAuthorizeEvent::class => ['onPageAuthorizeEvent', -10000],
|
||||||
'onPluginsInitialized' => [['initializeSession', 10000], ['initializeLogin', 1000]],
|
'onPluginsInitialized' => [['initializeSession', 10000], ['initializeLogin', 1000]],
|
||||||
'onTask.login.login' => ['loginController', 0],
|
'onTask.login.login' => ['loginController', 0],
|
||||||
'onTask.login.twofa' => ['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
|
public function onSessionStart(SessionStartEvent $event): void
|
||||||
{
|
{
|
||||||
$session = $event->session;
|
$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;
|
$user = $session->user ?? null;
|
||||||
if ($user && $user->exists() && ($this->config()['session_user_sync'] ?? false)) {
|
if ($user && $user->exists() && ($this->config()['session_user_sync'] ?? false)) {
|
||||||
// User is stored into the filesystem.
|
// User is stored into the filesystem.
|
||||||
|
@ -303,7 +337,7 @@ class LoginPlugin extends Plugin
|
||||||
if ($page) {
|
if ($page) {
|
||||||
$header = $page->header();
|
$header = $page->header();
|
||||||
|
|
||||||
$allowed = ($header->login_redirect_here ?? true) === false;
|
$allowed = ($header->login_redirect_here ?? true) === true;
|
||||||
if ($allowed && $page->routable()) {
|
if ($allowed && $page->routable()) {
|
||||||
$redirect = $page->route();
|
$redirect = $page->route();
|
||||||
foreach ($uri->params(null, true) as $key => $value) {
|
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
|
* [onPageInitialized] Authorize Page
|
||||||
*/
|
*/
|
||||||
|
@ -590,7 +685,7 @@ class LoginPlugin extends Plugin
|
||||||
$user = $this->grav['user'];
|
$user = $this->grav['user'];
|
||||||
|
|
||||||
$page = $this->grav['page'] ?? null;
|
$page = $this->grav['page'] ?? null;
|
||||||
if (!$page instanceof PageInterface) {
|
if (!$page instanceof PageInterface || $page->isModule()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,8 +698,9 @@ class LoginPlugin extends Plugin
|
||||||
$uri_extension = $this->grav['uri']->extension('html');
|
$uri_extension = $this->grav['uri']->extension('html');
|
||||||
$supported_types = $this->config->get('media.types');
|
$supported_types = $this->config->get('media.types');
|
||||||
if ($uri_extension !== 'html' && array_key_exists($uri_extension, $supported_types)) {
|
if ($uri_extension !== 'html' && array_key_exists($uri_extension, $supported_types)) {
|
||||||
header('HTTP/1.0 403 Forbidden');
|
$response = new Response(403);
|
||||||
exit;
|
|
||||||
|
$this->grav->close($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// User is not logged in; redirect to login page.
|
// User is not logged in; redirect to login page.
|
||||||
|
@ -783,7 +879,7 @@ class LoginPlugin extends Plugin
|
||||||
foreach ($default_values as $key => $param) {
|
foreach ($default_values as $key => $param) {
|
||||||
|
|
||||||
if ($key === $field) {
|
if ($key === $field) {
|
||||||
if (\is_array($param)) {
|
if (is_array($param)) {
|
||||||
$values = explode(',', $param);
|
$values = explode(',', $param);
|
||||||
} else {
|
} else {
|
||||||
$values = $param;
|
$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
|
class ClassLoader
|
||||||
{
|
{
|
||||||
|
/** @var ?string */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
// PSR-4
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
private $prefixLengthsPsr4 = array();
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<int, string>>
|
||||||
|
*/
|
||||||
private $prefixDirsPsr4 = array();
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $fallbackDirsPsr4 = array();
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
// PSR-0
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, string[]>>
|
||||||
|
*/
|
||||||
private $prefixesPsr0 = array();
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $fallbackDirsPsr0 = array();
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $useIncludePath = false;
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
private $classMap = array();
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $classMapAuthoritative = false;
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool[]
|
||||||
|
* @psalm-var array<string, bool>
|
||||||
|
*/
|
||||||
private $missingClasses = array();
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
private $apcuPrefix;
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var self[]
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ?string $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
public function getPrefixes()
|
public function getPrefixes()
|
||||||
{
|
{
|
||||||
if (!empty($this->prefixesPsr0)) {
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
@ -66,28 +120,47 @@ class ClassLoader
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
public function getPrefixesPsr4()
|
public function getPrefixesPsr4()
|
||||||
{
|
{
|
||||||
return $this->prefixDirsPsr4;
|
return $this->prefixDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getFallbackDirs()
|
public function getFallbackDirs()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr0;
|
return $this->fallbackDirsPsr0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getFallbackDirsPsr4()
|
public function getFallbackDirsPsr4()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr4;
|
return $this->fallbackDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] Array of classname => path
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
public function getClassMap()
|
public function getClassMap()
|
||||||
{
|
{
|
||||||
return $this->classMap;
|
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)
|
public function addClassMap(array $classMap)
|
||||||
{
|
{
|
||||||
|
@ -102,9 +175,11 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix, either
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
* appending or prepending to the ones previously set for this prefix.
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The 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
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($prefix, $paths, $prepend = false)
|
public function add($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
@ -147,11 +222,13 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace, either
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
* appending or prepending to the ones previously set for this namespace.
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @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
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addPsr4($prefix, $paths, $prepend = false)
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
@ -195,8 +272,10 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix,
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
* replacing any others previously set for this prefix.
|
* replacing any others previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The 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)
|
public function set($prefix, $paths)
|
||||||
{
|
{
|
||||||
|
@ -211,10 +290,12 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace,
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
* replacing any others previously set for this namespace.
|
* replacing any others previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @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
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPsr4($prefix, $paths)
|
public function setPsr4($prefix, $paths)
|
||||||
{
|
{
|
||||||
|
@ -234,6 +315,8 @@ class ClassLoader
|
||||||
* Turns on searching the include path for class files.
|
* Turns on searching the include path for class files.
|
||||||
*
|
*
|
||||||
* @param bool $useIncludePath
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setUseIncludePath($useIncludePath)
|
public function setUseIncludePath($useIncludePath)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +339,8 @@ class ClassLoader
|
||||||
* that have not been registered with the class map.
|
* that have not been registered with the class map.
|
||||||
*
|
*
|
||||||
* @param bool $classMapAuthoritative
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
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.
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
*
|
*
|
||||||
* @param string|null $apcuPrefix
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setApcuPrefix($apcuPrefix)
|
public function setApcuPrefix($apcuPrefix)
|
||||||
{
|
{
|
||||||
|
@ -296,25 +383,44 @@ class ClassLoader
|
||||||
* Registers this instance as an autoloader.
|
* Registers this instance as an autoloader.
|
||||||
*
|
*
|
||||||
* @param bool $prepend Whether to prepend the autoloader or not
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register($prepend = false)
|
public function register($prepend = false)
|
||||||
{
|
{
|
||||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
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.
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function unregister()
|
public function unregister()
|
||||||
{
|
{
|
||||||
spl_autoload_unregister(array($this, 'loadClass'));
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the given class or interface.
|
* Loads the given class or interface.
|
||||||
*
|
*
|
||||||
* @param string $class The name of the class
|
* @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)
|
public function loadClass($class)
|
||||||
{
|
{
|
||||||
|
@ -323,6 +429,8 @@ class ClassLoader
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -367,6 +475,21 @@ class ClassLoader
|
||||||
return $file;
|
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)
|
private function findFileWithExtension($class, $ext)
|
||||||
{
|
{
|
||||||
// PSR-4 lookup
|
// PSR-4 lookup
|
||||||
|
@ -438,6 +561,10 @@ class ClassLoader
|
||||||
* Scope isolated include.
|
* Scope isolated include.
|
||||||
*
|
*
|
||||||
* Prevents access to $this/self from included files.
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function includeFile($file)
|
function includeFile($file)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,255 +1,350 @@
|
||||||
<?php
|
<?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;
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
use Composer\Semver\VersionParser;
|
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
|
class InstalledVersions
|
||||||
{
|
{
|
||||||
private static $installed = array (
|
/**
|
||||||
'root' =>
|
* @var mixed[]|null
|
||||||
array (
|
* @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
|
||||||
'pretty_version' => 'dev-develop',
|
*/
|
||||||
'version' => 'dev-develop',
|
private static $installed;
|
||||||
'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 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()
|
||||||
|
{
|
||||||
|
$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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
public static function getInstalledPackages()
|
foreach (self::getInstalled() as $installed) {
|
||||||
{
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
return array_keys(self::$installed['versions']);
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
}
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
public static function isInstalled($packageName)
|
*
|
||||||
{
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
return isset(self::$installed['versions'][$packageName]);
|
*
|
||||||
}
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
/**
|
||||||
{
|
* Checks whether the given package satisfies a version constraint
|
||||||
$constraint = $parser->parseConstraints($constraint);
|
*
|
||||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
return $provided->matches($constraint);
|
* 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);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
public static function getVersionRanges($packageName)
|
return $provided->matches($constraint);
|
||||||
{
|
}
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
/**
|
||||||
}
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
$ranges = array();
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
|
*
|
||||||
}
|
* @param string $packageName
|
||||||
if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
|
* @return string Version constraint usable with composer/semver
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
|
*/
|
||||||
}
|
public static function getVersionRanges($packageName)
|
||||||
if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
|
{
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
|
foreach (self::getInstalled() as $installed) {
|
||||||
}
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
|
continue;
|
||||||
$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
|
}
|
||||||
}
|
|
||||||
|
$ranges = array();
|
||||||
return implode(' || ', $ranges);
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
}
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
public static function getVersion($packageName)
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
{
|
}
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$installed['versions'][$packageName]['version'])) {
|
return implode(' || ', $ranges);
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
return self::$installed['versions'][$packageName]['version'];
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
public static function getPrettyVersion($packageName)
|
{
|
||||||
{
|
foreach (self::getInstalled() as $installed) {
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$installed['versions'][$packageName]['pretty_version'];
|
return $installed['versions'][$packageName]['version'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static function getReference($packageName)
|
* @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
|
||||||
if (!isset(self::$installed['versions'][$packageName])) {
|
*/
|
||||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
public static function getPrettyVersion($packageName)
|
||||||
}
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
if (!isset(self::$installed['versions'][$packageName]['reference'])) {
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
return null;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$installed['versions'][$packageName]['reference'];
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
public static function getRootPackage()
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
{
|
}
|
||||||
return self::$installed['root'];
|
|
||||||
}
|
/**
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
public static function getRawData()
|
continue;
|
||||||
{
|
}
|
||||||
return self::$installed;
|
|
||||||
}
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
public static function reload($data)
|
|
||||||
{
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
self::$installed = $data;
|
}
|
||||||
}
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
$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';
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
spl_autoload_register(array('ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366', 'loadClassLoader'), true, true);
|
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'));
|
spl_autoload_unregister(array('ComposerAutoloaderIniteed5e5cf0aa1e2139f2db7445511e366', 'loadClassLoader'));
|
||||||
|
|
||||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
$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)
|
function composerRequireeed5e5cf0aa1e2139f2db7445511e366($fileIdentifier, $file)
|
||||||
{
|
{
|
||||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
require $file;
|
|
||||||
|
|
||||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
|
||||||
|
require $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,17 +150,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "robthree/twofactorauth",
|
"name": "robthree/twofactorauth",
|
||||||
"version": "1.8.0",
|
"version": "1.8.2",
|
||||||
"version_normalized": "1.8.0.0",
|
"version_normalized": "1.8.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
"url": "https://github.com/RobThree/TwoFactorAuth.git",
|
||||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
|
"reference": "65681de5a324eae05140ac58b08648a60212afc0"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
"url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/65681de5a324eae05140ac58b08648a60212afc0",
|
||||||
"reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
|
"reference": "65681de5a324eae05140ac58b08648a60212afc0",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -174,7 +174,7 @@
|
||||||
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
|
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
|
||||||
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
|
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
|
||||||
},
|
},
|
||||||
"time": "2021-03-09T18:24:05+00:00",
|
"time": "2022-03-22T16:11:07+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
|
@ -1,60 +1,59 @@
|
||||||
<?php return array (
|
<?php return array(
|
||||||
'root' =>
|
'root' => array(
|
||||||
array (
|
'pretty_version' => 'dev-develop',
|
||||||
'pretty_version' => 'dev-develop',
|
'version' => 'dev-develop',
|
||||||
'version' => 'dev-develop',
|
'type' => 'library',
|
||||||
'aliases' =>
|
'install_path' => __DIR__ . '/../../',
|
||||||
array (
|
'aliases' => array(),
|
||||||
|
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
|
||||||
|
'name' => 'getgrav/grav-plugin-login',
|
||||||
|
'dev' => false,
|
||||||
),
|
),
|
||||||
'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517',
|
'versions' => array(
|
||||||
'name' => 'getgrav/grav-plugin-login',
|
'bacon/bacon-qr-code' => array(
|
||||||
),
|
'pretty_version' => '1.0.3',
|
||||||
'versions' =>
|
'version' => '1.0.3.0',
|
||||||
array (
|
'type' => 'library',
|
||||||
'bacon/bacon-qr-code' =>
|
'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
|
||||||
array (
|
'aliases' => array(),
|
||||||
'pretty_version' => '1.0.3',
|
'reference' => '5a91b62b9d37cee635bbf8d553f4546057250bee',
|
||||||
'version' => '1.0.3.0',
|
'dev_requirement' => false,
|
||||||
'aliases' =>
|
),
|
||||||
array (
|
'birke/rememberme' => array(
|
||||||
),
|
'pretty_version' => '1.0.5',
|
||||||
'reference' => '5a91b62b9d37cee635bbf8d553f4546057250bee',
|
'version' => '1.0.5.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../birke/rememberme',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '810473852eb4823098e47e23376a19b77ba0c165',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'getgrav/grav-plugin-login' => array(
|
||||||
|
'pretty_version' => 'dev-develop',
|
||||||
|
'version' => 'dev-develop',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'b873dd50c66d15151e44fde56a79cfc16ba38bd3',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'paragonie/random_compat' => array(
|
||||||
|
'pretty_version' => 'v1.4.3',
|
||||||
|
'version' => '1.4.3.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '9b3899e3c3ddde89016f576edb8c489708ad64cd',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'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,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
'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',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
$issues = array();
|
$issues = array();
|
||||||
|
|
||||||
if (!(PHP_VERSION_ID >= 70103)) {
|
if (!(PHP_VERSION_ID >= 70306)) {
|
||||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.3". You are running ' . PHP_VERSION . '.';
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". You are running ' . PHP_VERSION . '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($issues) {
|
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:
|
strategy:
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -20,6 +20,7 @@ jobs:
|
||||||
php-version: ${{ matrix.php-version }}
|
php-version: ${{ matrix.php-version }}
|
||||||
tools: composer
|
tools: composer
|
||||||
coverage: xdebug
|
coverage: xdebug
|
||||||
|
ini-values: error_reporting=E_ALL
|
||||||
|
|
||||||
- uses: ramsey/composer-install@v1
|
- 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