init
This commit is contained in:
commit
6b687feee2
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Webman INIT
|
||||
|
||||
Webman的启动模板:
|
||||
|
||||
```
|
||||
wget https://git.laysense.com/enoch/webmaninit/archive/main.tar.gz
|
||||
tar -zxvf ./main.tar.gz
|
||||
rm -rf ./main.tar.gz
|
||||
mv webmaninit/* ./
|
||||
```
|
80
app/controller/Account.php
Normal file
80
app/controller/Account.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use yzh52521\EasyHttp\Response;
|
||||
use yzh52521\EasyHttp\RequestException;
|
||||
use yzh52521\EasyHttp\Http;
|
||||
use support\Db;
|
||||
use Webman\Captcha\CaptchaBuilder;
|
||||
|
||||
class Account
|
||||
{
|
||||
public function login(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$user=$session->get('user',null);
|
||||
if($user!=null){
|
||||
return redirect('/my');
|
||||
}
|
||||
return view('login');
|
||||
}
|
||||
public function logout(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$session->delete('user');
|
||||
$session->delete('realname');
|
||||
return redirect('/');
|
||||
}
|
||||
public function my(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$user=$session->get('user',null);
|
||||
$realname=$session->get('realname',null);
|
||||
if($user==null||$realname==null){
|
||||
return redirect('/');
|
||||
}
|
||||
$record=Db::table('links')->where('user', "$user")->get();
|
||||
print_r($record);
|
||||
return view('my', ['user' => $user,'realname' => $realname,'record' => $record]);
|
||||
}
|
||||
public function captcha(Request $request)
|
||||
{
|
||||
// 初始化验证码类
|
||||
$builder = new CaptchaBuilder;
|
||||
// 生成验证码
|
||||
$builder->build();
|
||||
// 将验证码的值存储到session中
|
||||
$request->session()->set('captcha', strtolower($builder->getPhrase()));
|
||||
// 获得验证码图片二进制数据
|
||||
$img_content = $builder->get();
|
||||
// 输出验证码二进制数据
|
||||
return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
|
||||
}
|
||||
public function loginapi(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$username = $request->input('username');
|
||||
$password = $request->input('password');
|
||||
$captcha = $request->input('captcha');
|
||||
$captcha_session = $request->session()->get('captcha');
|
||||
if(strtolower($captcha) != $captcha_session){
|
||||
return json(['code' => 400, 'msg' => '验证码错误']);
|
||||
}
|
||||
if($username == null || $password == null){
|
||||
return json(['code' => 400, 'msg' => '用户名或密码不能为空']);
|
||||
}
|
||||
if(strlen($username)>=36){
|
||||
return json(['code' => 400, 'msg' => '用户名格式错误']);
|
||||
}
|
||||
$username=Db::table('users')->where('username', "$username")->where('password',"$password")->value('username');
|
||||
if($username==null){
|
||||
return json(['code' => 400, 'msg' => '用户名或密码错误']);
|
||||
}else{
|
||||
$session->set('user', $username);
|
||||
$session->set('realname', Db::table('users')->where('username', "$username")->value('realname'));
|
||||
return json(['code' => 200, 'msg' => '登陆成功']);
|
||||
}
|
||||
}
|
||||
}
|
32
app/controller/IndexController.php
Normal file
32
app/controller/IndexController.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
|
||||
class IndexController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$user=$session->get('user',null);
|
||||
$realname=$session->get('realname',null);
|
||||
if($user==null||$realname==null){
|
||||
$display='none';
|
||||
}else{
|
||||
$display='block';
|
||||
}
|
||||
return view('index', ['user' => $user,'realname' => $realname,'display' => $display]);
|
||||
}
|
||||
|
||||
public function view(Request $request)
|
||||
{
|
||||
return view('index/view', ['name' => 'webman']);
|
||||
}
|
||||
|
||||
public function json(Request $request)
|
||||
{
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
}
|
107
app/controller/Server.php
Normal file
107
app/controller/Server.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use yzh52521\EasyHttp\Response;
|
||||
use yzh52521\EasyHttp\RequestException;
|
||||
use yzh52521\EasyHttp\Http;
|
||||
use support\Db;
|
||||
|
||||
class Server
|
||||
{
|
||||
public function short(Request $request)
|
||||
{
|
||||
$session = $request->session();
|
||||
$url = $request->input('url',null);
|
||||
$link = $request->input('link',null);
|
||||
$type = $request->input('type','false');
|
||||
if($link==null && Db::table('links')->where('source', "$url")->where('type',0)->exists() ){
|
||||
$link=Db::table('links')->where('source', "$url")->where('type',0)->value('link');
|
||||
return json(['code' => 200, 'msg' => 'success','link'=>'https://SPQR.top/'.$link]);
|
||||
}
|
||||
$user=$session->get('user',null);
|
||||
if($user==null&&($type!='false'||$link!=null)){
|
||||
return json(['code' => 505, 'msg' => '302直链和自定义链接后缀需要登陆后才可使用']);
|
||||
}
|
||||
$realname=$session->get('realname',null);
|
||||
|
||||
#$domain=parse_url($url)['host'];
|
||||
$domain=$url;
|
||||
$response = Http::post('https://api.uutool.cn/beian/icp/', ['site' => "$domain"])->json();
|
||||
if(isset($response->data->is_icp)){
|
||||
if($response->data->is_icp==1){
|
||||
$icp=$response->data;
|
||||
$owner=$icp->icp_org;
|
||||
$webid=$icp->icp_no;
|
||||
}else{
|
||||
$icp=null;
|
||||
if($user==null){
|
||||
$owner='anonymous';
|
||||
}else{
|
||||
$owner=$realname;
|
||||
}
|
||||
$webid=null;
|
||||
}
|
||||
}else{
|
||||
return json(['code' => 405, 'msg' => '备案查询接口响应异常,请稍后重试']);
|
||||
}
|
||||
if($icp==null&&($user==null||$type!='false')){
|
||||
return json(['code' => 502, 'msg' => '该域名未备案,需要登陆后才可缩短,且不支持302直链']);
|
||||
}
|
||||
|
||||
if($link==null){
|
||||
for($i=4;$i>0;$i++){
|
||||
$link=substr(md5($url).rand(0,pow(10,$i)),0,$i);
|
||||
if(Db::table('links')->where('link', "$link")->exists()){
|
||||
continue;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(Db::table('links')->where('link', "$link")->exists()){
|
||||
return json(['code' => 408, 'msg' => '自定义链接已存在']);
|
||||
}
|
||||
}
|
||||
if($user==null){
|
||||
$user='anonymous';
|
||||
}
|
||||
if($type=='false'){
|
||||
$type=0;
|
||||
}elseif($type=='true'){
|
||||
$type=1;
|
||||
}
|
||||
$data=[
|
||||
'link'=>$link,
|
||||
'source'=>$url,
|
||||
'owner'=>$owner,
|
||||
'webid'=>$webid,
|
||||
'user'=>$user,
|
||||
'type'=>$type,
|
||||
'time'=>time()
|
||||
];
|
||||
Db::table('links')->insert($data);
|
||||
return json(['code' => 200, 'msg' => 'success','link'=>'https://SPQR.top/'.$link]);
|
||||
}
|
||||
public function view(Request $request,$link)
|
||||
{
|
||||
$source=Db::table('links')->where('link', "$link")->first();
|
||||
if($source==null){
|
||||
return redirect('/');
|
||||
}
|
||||
if($source->type==0){
|
||||
if($source->webid==null){
|
||||
$ba='block';
|
||||
}else{
|
||||
$ba='none';
|
||||
}
|
||||
return view('jump', ['source' => $source,'ba'=>$ba]);
|
||||
}elseif($source->type==1){
|
||||
return redirect($source->source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
4
app/functions.php
Normal file
4
app/functions.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Here is your custom functions.
|
||||
*/
|
42
app/middleware/StaticFile.php
Normal file
42
app/middleware/StaticFile.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* Class StaticFile
|
||||
* @package app\middleware
|
||||
*/
|
||||
class StaticFile implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $next): Response
|
||||
{
|
||||
// Access to files beginning with. Is prohibited
|
||||
if (strpos($request->path(), '/.') !== false) {
|
||||
return response('<h1>403 forbidden</h1>', 403);
|
||||
}
|
||||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
// Add cross domain HTTP header
|
||||
/*$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
]);*/
|
||||
return $response;
|
||||
}
|
||||
}
|
29
app/model/Test.php
Normal file
29
app/model/Test.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Test extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
}
|
232
app/view/index.html
Normal file
232
app/view/index.html
Normal file
@ -0,0 +1,232 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href='normalize.css' rel='stylesheet' type='text/css'>
|
||||
<link href="https://fonts.laysense.com/css/5000/zh-cn/harmonyossans/harmonyossans.css" rel="preload" as="style" onload="this.rel='stylesheet'">
|
||||
<link id="theme_css" rel="stylesheet" href="sakura.css">
|
||||
<style>
|
||||
.pmnet { font-family: DOUYUFont;}
|
||||
html {font-family: HarmonyOSSans;}
|
||||
.animbox {
|
||||
margin: 50px auto;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
}
|
||||
/*设置各竖条的共有样式*/
|
||||
.animbox > div {
|
||||
background-color: #279fcf;
|
||||
width: 4px;
|
||||
height: 35px;
|
||||
border-radius: 2px;
|
||||
margin: 2px;
|
||||
animation-fill-mode: both;
|
||||
display: inline-block;
|
||||
animation: anim 0.9s 0s infinite cubic-bezier(.11, .49, .38, .78);
|
||||
}
|
||||
/*设置动画延迟*/
|
||||
.animbox > :nth-child(2), .animbox > :nth-child(4) {
|
||||
animation-delay: 0.25s !important;
|
||||
}
|
||||
|
||||
.animbox > :nth-child(1), .animbox > :nth-child(5) {
|
||||
animation-delay: 0.5s !important;
|
||||
}
|
||||
/*定义动画*/
|
||||
@keyframes anim {
|
||||
0% { transform: scaley(1); }
|
||||
80% { transform: scaley(0.3); }
|
||||
90% { transform: scaley(1); }
|
||||
}
|
||||
|
||||
/* 开关 - 滑块周围的框 */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
/* 隐藏默认 HTML 复选框 */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* 滑块 */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #2fbc47;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
/* 圆形滑块 */
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
<title>SPQR短链接服务-罗马元老院与罗马人民SPQR.TOP</title>
|
||||
<meta name="keywords" content="短链接,短网址,链接缩短,网址缩短,SPQR,罗马元老院,元老院">
|
||||
<meta name="description" content="SPQR.top提供免费的短链接、网址缩短服务,SPQR是罗马元老院与罗马人民的缩写">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
//切换深色模式
|
||||
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
|
||||
document.getElementById('theme_css').href = 'sakura-dark.css';
|
||||
}
|
||||
|
||||
</script>
|
||||
<main>
|
||||
<h1>SPQR.top 免费短链接服务 </h1><hr />
|
||||
<p>可以将很长的网址链接缩短成以SPQR.top开头弘扬罗马元老院与人民精神的短链接。</p>
|
||||
<a href="//laysense.cn" target="_blank_laysense">由[<span class="pmnet">来笙</span>]维护</a>
|
||||
|
||||
<blockquote>
|
||||
SPQR.top 代表 SPQR(罗马元老院与人民) 宇宙第一
|
||||
<br />
|
||||
SPQR是拉丁语Senatus Populusque Romanus(罗马元老院与罗马人民)的缩写
|
||||
<br />
|
||||
<img src="https://wallpapercave.com/wp/wp2471066.jpg" alt="SPQR" style=" max-height: 200px;">
|
||||
<br />
|
||||
<span style="color: coral;">严禁将本服务用于违法目的。</span>
|
||||
</blockquote>
|
||||
|
||||
<blockquote>
|
||||
登陆后,您可以使用自定义短链接后缀,以及302直链功能。<br />
|
||||
未备案的域名必须登陆后才能缩短,且不支持302直链<br />
|
||||
<?php if($user==null){
|
||||
echo '<span><a href="/!/login" target="_blank_login">[登陆]</a></span>';
|
||||
}else{
|
||||
echo '<span>你好,'.$realname.'。<a href="/!/my" target="_blank_login">[查看我缩短的域名]</a><a href="/!/logout">[登出]</a></span>';
|
||||
}
|
||||
?>
|
||||
|
||||
</blockquote>
|
||||
<section>
|
||||
|
||||
<h4>缩短一个网址</h4>
|
||||
<hr />
|
||||
<form action="new_apply.php" method="POST">
|
||||
<p style="display: <?=htmlspecialchars($display)?>;">JS跳转 <label class="switch">
|
||||
<input id="type" type="checkbox" name="type">
|
||||
<span class="slider round"></span>
|
||||
</label> 302直链[需登录]
|
||||
</p>
|
||||
<p>
|
||||
<label for="name">需要缩短的网址链接</label>
|
||||
<input required="required" name="url" id="url" placeholder="https://baidu.cn/" type="url" style="width:80%">
|
||||
</p>
|
||||
<p style="display: <?=htmlspecialchars($display)?>;">
|
||||
<label for="password">自定义短链接后缀[需登录,留空则由系统生成]</label>
|
||||
https://SPQR.top/<input name="link" id="link" type="text" style="width:30%">
|
||||
</p>
|
||||
<div id="load" class="animbox" style="display: none;">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p style="color: blueviolet;" id="notice"></p>
|
||||
<p style="color: skyblue;" id="notice2"></p>
|
||||
|
||||
</form>
|
||||
<p>
|
||||
<button onclick="short()" value="缩短网址" style="width:50%">缩短网址</button>
|
||||
<br />
|
||||
点击缩短代表您同意并接受<a href="https://www.pmnet.gq/PMNETTOS" target="_blank_tos">TOS</a>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
<footer>
|
||||
<hr/>
|
||||
©<a href="https://laysense.cn">laysense.cn</a> 2024 Made with <a href="https://oxal.org/projects/sakura">sakura.css</a>
|
||||
</footer>
|
||||
<script src="jquery-3.6.3.min.js"></script>
|
||||
<script>
|
||||
function short(){
|
||||
var url = $("#url").val();
|
||||
var link = $("#link").val();
|
||||
var type = $("#type").prop('checked');
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: '/!/short',
|
||||
data: {'url':url,'link':link,'type':type},
|
||||
async: true,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
beforeSend: function () {
|
||||
$('#notice2').html('');
|
||||
$('#notice').html('正在进行缩短');
|
||||
$('#load').show();
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.code == 200) {
|
||||
$('#notice').html(`短链接为<a href="javascript:copyToClipboard('`+data.link+`')">`+data.link+'</a>,点击复制');
|
||||
} else {
|
||||
$('#notice').html(data.msg);
|
||||
}
|
||||
$('#load').hide();
|
||||
},
|
||||
clearForm: true,
|
||||
resetForm: false
|
||||
});
|
||||
}
|
||||
async function copyToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
$('#notice2').html('复制成功');
|
||||
} catch (err) {
|
||||
$('#notice2').html('复制失败', err);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
93
app/view/jump.html
Normal file
93
app/view/jump.html
Normal file
@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>正在跳转|SPQR.top 短网址跳转服务</title>
|
||||
<!-- 引入Bootstrap CDN -->
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
/* 内联CSS样式 */
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
/**background: linear-gradient(270deg, #ff9a9e, #fad0c4);**/
|
||||
background-image: url('https://cdn-dynmedia-1.microsoft.com/is/image/microsoftcorp/305616-skucards-backgroundfullbleed-1600x1132?resMode=sharp2&op_usm=1.5,0.65,15,0&wid=2000&hei=1415&qlt=100&fmt=png-alpha&fit=constrain');
|
||||
background-size: 400% 400%;
|
||||
animation: gradient 15s ease infinite;
|
||||
}
|
||||
@keyframes gradient {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
.card {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
border: none;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.btn-error {
|
||||
background-color: #ff3700;
|
||||
border: none;
|
||||
}
|
||||
.btn-error:hover {
|
||||
background-color: #b70404;
|
||||
}
|
||||
.loader {
|
||||
border: 4px solid #f3f3f3;
|
||||
border-radius: 50%;
|
||||
border-top: 4px solid #3498db;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
animation: spin 2s linear infinite;
|
||||
margin: 0 auto 15px auto;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<img src="https://wallpapercave.com/wp/wp2471066.jpg" style="max-width: 168px;"/>
|
||||
<h2 class="card-title" id="title">正在前往目标站点</h2>
|
||||
<p class="card-text">由 <a href="//spqr.top" target="_blank">SPQR.top</a> 提供网址链接缩短服务。</p>
|
||||
<p class="card-text">目标网站由 <span><?php echo($source->owner); ?></span> 提供 <br />
|
||||
我们不对其内容的真实性和合法性负责。
|
||||
</p>
|
||||
<p class="card-text" style="display: <?php echo($ba);?>;">⚠️该网站未备案,可能存在违规内容,请谨慎访问!⚠️</p>
|
||||
<div id="loader" class="loader"></div>
|
||||
<a id="msg" class="btn "></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.7.1.js" ></script>
|
||||
<script type="text/javascript">
|
||||
let min = 2000;
|
||||
let max = 6000;
|
||||
let randomIntInRange = Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
|
||||
setTimeout(function(){
|
||||
var goto='<?php echo $source->source; ?>';
|
||||
$("#msg").attr("href", goto);
|
||||
$("#msg").html('若您的浏览器没有反应,请点击此处');
|
||||
$("#msg").addClass("btn-primary");
|
||||
$("#msg").show();
|
||||
window.location.href=goto;
|
||||
}, randomIntInRange);
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
71
app/view/login.html
Normal file
71
app/view/login.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>登录 SPQR.top</title>
|
||||
<link href='normalize.css' rel='stylesheet' type='text/css'>
|
||||
<link href="https://fonts.laysense.com/css/5000/zh-cn/harmonyossans/harmonyossans.css" rel="preload" as="style" onload="this.rel='stylesheet'">
|
||||
<link id="theme_css" rel="stylesheet" href="/sakura.css"></head>
|
||||
<body>
|
||||
<script>
|
||||
//切换深色模式
|
||||
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
|
||||
document.getElementById('theme_css').href = '/sakura-dark.css';
|
||||
}
|
||||
|
||||
</script>
|
||||
<div class="login-container">
|
||||
<h2>登录 SPQR.top</h2>
|
||||
<form action="/login" method="post">
|
||||
<label for="username">用户名:</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
|
||||
<label for="password">密码:</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
|
||||
<label for="captcha">验证码:</label>
|
||||
<img src="/!/captcha" alt="Captcha Image" id="captcha-image" onclick="change()"><br />
|
||||
<input type="text" id="captcha" name="captcha" required>
|
||||
<br />
|
||||
<button type="submit">登入</button>
|
||||
</form>
|
||||
<hr />
|
||||
<a href="/">[返回首页]</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<script src="/jquery-3.6.3.min.js"></script>
|
||||
<script>
|
||||
function change() {
|
||||
document.getElementById('captcha-image').src = '/!/captcha?' + Math.random();
|
||||
}
|
||||
$(document).ready(function() {
|
||||
$('form').on('submit', function(event) {
|
||||
event.preventDefault();
|
||||
var formData = {
|
||||
username: $('#username').val(),
|
||||
password: $('#password').val(),
|
||||
captcha: $('#captcha').val()
|
||||
};
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/!/loginapi',
|
||||
data: JSON.stringify(formData),
|
||||
contentType: 'application/json',
|
||||
success: function(response) {
|
||||
if(response.code == 200) {
|
||||
window.location.href = '/my';
|
||||
} else {
|
||||
alert('登陆失败:'+response.msg);
|
||||
change();
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
alert('登陆失败:接口错误');
|
||||
change();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
66
app/view/my.html
Normal file
66
app/view/my.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Short Links</title>
|
||||
<link id="theme_css" rel="stylesheet" href="/sakura.css"></head>
|
||||
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/datatables/1.10.21/css/jquery.dataTables.css" rel="stylesheet">
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
//切换深色模式
|
||||
if(window.matchMedia('(prefers-color-scheme: dark)').matches){
|
||||
document.getElementById('theme_css').href = '/sakura-dark.css';
|
||||
}
|
||||
|
||||
</script>
|
||||
<h1>当前的短链接</h1>
|
||||
<p>用户名:<?=htmlspecialchars($user)?> , <?=htmlspecialchars($realname)?> 。<a href="/logout">[登出]</a> <a href="/">[回到首页]</a></p>
|
||||
<hr />
|
||||
<table id="shortLinksTable" class="display" style="width: 100%; table-layout: fixed; word-break: break-all;color:black">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>短链接</th>
|
||||
<th>原始域名</th>
|
||||
<th>备案号/负责人</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<style>
|
||||
.sourcelink {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
foreach($record as $rec){
|
||||
echo '<tr>';
|
||||
echo '<td>SPQR.top/'.$rec->link.'</td>';
|
||||
echo '<td class="sourcelink">'.$rec->source .'</td>';
|
||||
if($rec->webid == null) {
|
||||
echo '<td>未备案</td>';
|
||||
} else {
|
||||
echo '<td>' . $rec->webid . '<br />'.$rec->owner.'</td>';
|
||||
}
|
||||
echo '<td><a style="color: red;" href="/!/delete/'. $rec->link . '">[删除]</a></td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#shortLinksTable').DataTable();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
71
composer.json
Normal file
71
composer.json
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"name": "workerman/webman",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"high performance",
|
||||
"http service"
|
||||
],
|
||||
"homepage": "https://www.workerman.net",
|
||||
"license": "MIT",
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "walkor@workerman.net",
|
||||
"issues": "https://github.com/walkor/webman/issues",
|
||||
"forum": "https://wenda.workerman.net/",
|
||||
"wiki": "https://workerman.net/doc/webman",
|
||||
"source": "https://github.com/walkor/webman"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.5.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"illuminate/database": "^9.52",
|
||||
"illuminate/pagination": "^9.52",
|
||||
"illuminate/events": "^9.52",
|
||||
"symfony/var-dumper": "^6.0",
|
||||
"jasongrimes/paginator": "~1.0",
|
||||
"robmorgan/phinx": "^0.14.0",
|
||||
"illuminate/redis": "^9.52",
|
||||
"symfony/cache": "^6.0",
|
||||
"workerman/validation": "^3.1",
|
||||
"symfony/translation": "^6.0",
|
||||
"webman/captcha": "^1.0",
|
||||
"webman/event": "^1.0",
|
||||
"vlucas/phpdotenv": "^5.6",
|
||||
"workerman/crontab": "^1.0",
|
||||
"yzh52521/easyhttp": "^1.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"app\\": "./app",
|
||||
"App\\": "./app",
|
||||
"app\\View\\Components\\": "./app/view/components"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
4863
composer.lock
generated
Normal file
4863
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
config/app.php
Normal file
26
config/app.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Request;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
'error_reporting' => E_ALL,
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
];
|
21
config/autoload.php
Normal file
21
config/autoload.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/support/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
18
config/bootstrap.php
Normal file
18
config/bootstrap.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Session::class,
|
||||
support\bootstrap\LaravelDb::class,
|
||||
];
|
15
config/container.php
Normal file
15
config/container.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return new Webman\Container;
|
36
config/database.php
Normal file
36
config/database.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
// 默认数据库
|
||||
'default' => 'mysql',
|
||||
|
||||
// 各种数据库配置
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'host' => 'laysense.mysql.database.azure.com',
|
||||
'port' => 3306,
|
||||
'database' => 'SPQR',
|
||||
'username' => 'laysense',
|
||||
'password' => 'qi2005112',
|
||||
'unix_socket' => '',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'strict' => true,
|
||||
'engine' => null
|
||||
],
|
||||
],
|
||||
];
|
15
config/dependence.php
Normal file
15
config/dependence.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
5
config/event.php
Normal file
5
config/event.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
];
|
17
config/exception.php
Normal file
17
config/exception.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
];
|
32
config/log.php
Normal file
32
config/log.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
15
config/middleware.php
Normal file
15
config/middleware.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
4
config/plugin/webman/event/app.php
Normal file
4
config/plugin/webman/event/app.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
return [
|
||||
'enable' => true,
|
||||
];
|
17
config/plugin/webman/event/bootstrap.php
Normal file
17
config/plugin/webman/event/bootstrap.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
Webman\Event\BootStrap::class,
|
||||
];
|
7
config/plugin/webman/event/command.php
Normal file
7
config/plugin/webman/event/command.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Webman\Event\EventListCommand;
|
||||
|
||||
return [
|
||||
EventListCommand::class
|
||||
];
|
42
config/process.php
Normal file
42
config/process.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
global $argv;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// Monitor these directories
|
||||
'monitorDir' => array_merge([
|
||||
app_path(),
|
||||
config_path(),
|
||||
base_path() . '/process',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
|
||||
// Files with these suffixes will be monitored
|
||||
'monitorExtensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
'options' => [
|
||||
'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
22
config/redis.php
Normal file
22
config/redis.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
];
|
31
config/route.php
Normal file
31
config/route.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
Route::any('/', [app\controller\IndexController::class, 'index']);
|
||||
Route::any('/!/short', [app\controller\Server::class, 'short']);
|
||||
Route::any('/!/login', [app\controller\Account::class, 'login']);
|
||||
Route::any('/!/loginapi', [app\controller\Account::class, 'loginapi']);
|
||||
Route::any('/!/my', [app\controller\Account::class, 'my']);
|
||||
Route::any('/!/logout', [app\controller\Account::class, 'logout']);
|
||||
Route::any('/!/captcha', [app\controller\Account::class, 'captcha']);
|
||||
Route::any('/{link}', [app\controller\Server::class, 'view']);
|
||||
Route::fallback(function(){
|
||||
return redirect('/');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
31
config/server.php
Normal file
31
config/server.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'listen' => 'http://0.0.0.0:8780',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'webman',
|
||||
'count' => cpu_count() * 4,
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'reusePort' => false,
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'log_file' => runtime_path() . '/logs/workerman.log',
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
65
config/session.php
Normal file
65
config/session.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Session\FileSessionHandler;
|
||||
use Webman\Session\RedisSessionHandler;
|
||||
use Webman\Session\RedisClusterSessionHandler;
|
||||
|
||||
return [
|
||||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
'save_path' => runtime_path() . '/sessions',
|
||||
],
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'auth' => '',
|
||||
'timeout' => 2,
|
||||
'database' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
],
|
||||
'redis_cluster' => [
|
||||
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
|
||||
'timeout' => 2,
|
||||
'auth' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
]
|
||||
],
|
||||
|
||||
'session_name' => 'PHPSID',
|
||||
|
||||
'auto_update_timestamp' => false,
|
||||
|
||||
'lifetime' => 7*24*60*60,
|
||||
|
||||
'cookie_lifetime' => 365*24*60*60,
|
||||
|
||||
'cookie_path' => '/',
|
||||
|
||||
'domain' => '',
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
'secure' => false,
|
||||
|
||||
'same_site' => '',
|
||||
|
||||
'gc_probability' => [1, 1000],
|
||||
|
||||
];
|
23
config/static.php
Normal file
23
config/static.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static file settings
|
||||
*/
|
||||
return [
|
||||
'enable' => true,
|
||||
'middleware' => [ // Static file Middleware
|
||||
//app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
25
config/translation.php
Normal file
25
config/translation.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multilingual configuration
|
||||
*/
|
||||
return [
|
||||
// Default language
|
||||
'locale' => 'zh_CN',
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => base_path() . '/resource/translations',
|
||||
];
|
22
config/view.php
Normal file
22
config/view.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\view\Raw;
|
||||
use support\view\Twig;
|
||||
use support\view\Blade;
|
||||
use support\view\ThinkPHP;
|
||||
|
||||
return [
|
||||
'handler' => Raw::class
|
||||
];
|
243
process/Monitor.php
Normal file
243
process/Monitor.php
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SplFileInfo;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public static $lockFile = __DIR__ . '/../runtime/monitor.lock';
|
||||
|
||||
/**
|
||||
* Pause monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pause()
|
||||
{
|
||||
file_put_contents(static::$lockFile, time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resume(): void
|
||||
{
|
||||
clearstatcache();
|
||||
if (is_file(static::$lockFile)) {
|
||||
unlink(static::$lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether monitor is paused
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPaused(): bool
|
||||
{
|
||||
clearstatcache();
|
||||
return file_exists(static::$lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitorDir
|
||||
* @param $monitorExtensions
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($monitorDir, $monitorExtensions, array $options = [])
|
||||
{
|
||||
static::resume();
|
||||
$this->paths = (array)$monitorDir;
|
||||
$this->extensions = $monitorExtensions;
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disableFunctions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disableFunctions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if ($options['enable_file_monitor'] ?? true) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
|
||||
if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitorDir
|
||||
* @return bool
|
||||
*/
|
||||
public function checkFilesChange($monitorDir): bool
|
||||
{
|
||||
static $lastMtime, $tooManyFilesCheck;
|
||||
if (!$lastMtime) {
|
||||
$lastMtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitorDir)) {
|
||||
if (!is_file($monitorDir)) {
|
||||
return false;
|
||||
}
|
||||
$iterator = [new SplFileInfo($monitorDir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file->getRealPath())) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
$lastMtime = $file->getMTime();
|
||||
if ($var) {
|
||||
continue;
|
||||
}
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tooManyFilesCheck && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
|
||||
$tooManyFilesCheck = 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange(): bool
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memoryLimit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memoryLimit)
|
||||
{
|
||||
if (static::isPaused() || $memoryLimit <= 0) {
|
||||
return;
|
||||
}
|
||||
$ppid = posix_getppid();
|
||||
$childrenFile = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$statusFile = "/proc/$pid/status";
|
||||
if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memoryLimit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memoryLimit)
|
||||
{
|
||||
if ($memoryLimit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$usePhpIni = false;
|
||||
if (!$memoryLimit) {
|
||||
$memoryLimit = ini_get('memory_limit');
|
||||
$usePhpIni = true;
|
||||
}
|
||||
|
||||
if ($memoryLimit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
|
||||
if ($unit === 'g') {
|
||||
$memoryLimit = 1024 * (int)$memoryLimit;
|
||||
} else if ($unit === 'm') {
|
||||
$memoryLimit = (int)$memoryLimit;
|
||||
} else if ($unit === 'k') {
|
||||
$memoryLimit = ((int)$memoryLimit / 1024);
|
||||
} else {
|
||||
$memoryLimit = ((int)$memoryLimit / (1024 * 1024));
|
||||
}
|
||||
if ($memoryLimit < 30) {
|
||||
$memoryLimit = 30;
|
||||
}
|
||||
if ($usePhpIni) {
|
||||
$memoryLimit = (int)(0.8 * $memoryLimit);
|
||||
}
|
||||
return $memoryLimit;
|
||||
}
|
||||
}
|
12
public/404.html
Normal file
12
public/404.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>404 Not Found - webman</title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>404 Not Found</h1>
|
||||
</center>
|
||||
<hr>
|
||||
<center>webman</center>
|
||||
</body>
|
||||
</html>
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
2
public/jquery-3.6.3.min.js
vendored
Normal file
2
public/jquery-3.6.3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
349
public/normalize.css
vendored
Normal file
349
public/normalize.css
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
223
public/sakura-dark.css
Normal file
223
public/sakura-dark.css
Normal file
@ -0,0 +1,223 @@
|
||||
/* $color-text: #dedce5; */
|
||||
/* Sakura.css v1.4.1
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
/* Body */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #c9c9c9;
|
||||
background-color: #222222;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small, sub, sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
a:visited {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
a:hover {
|
||||
color: #c9c9c9;
|
||||
border-bottom: 2px solid #c9c9c9;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #ffffff;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #4a4a4a;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img, video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
pre {
|
||||
background-color: #4a4a4a;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code, kbd, samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #4a4a4a;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #4a4a4a;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
input, textarea {
|
||||
border: 1px solid #c9c9c9;
|
||||
}
|
||||
input:focus, textarea:focus {
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button, button, input[type=submit], input[type=reset], input[type=button] {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #ffffff;
|
||||
color: #222222;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #ffffff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled], button[disabled], input[type=submit][disabled], input[type=reset][disabled], input[type=button][disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:focus:enabled, .button:hover:enabled, button:focus:enabled, button:hover:enabled, input[type=submit]:focus:enabled, input[type=submit]:hover:enabled, input[type=reset]:focus:enabled, input[type=reset]:hover:enabled, input[type=button]:focus:enabled, input[type=button]:hover:enabled {
|
||||
background-color: #c9c9c9;
|
||||
border-color: #c9c9c9;
|
||||
color: #222222;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
textarea, select, input {
|
||||
color: #c9c9c9;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: #4a4a4a;
|
||||
border: 1px solid #4a4a4a;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus, select:focus, input:focus {
|
||||
border: 1px solid #ffffff;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type=checkbox]:focus {
|
||||
outline: 1px dotted #ffffff;
|
||||
}
|
||||
|
||||
label, legend, fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
222
public/sakura.css
Normal file
222
public/sakura.css
Normal file
@ -0,0 +1,222 @@
|
||||
/* Sakura.css v1.4.1
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
/* Body */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #4a4a4a;
|
||||
background-color: #f9f9f9;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small, sub, sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #1d7484;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1d7484;
|
||||
}
|
||||
a:visited {
|
||||
color: #144f5a;
|
||||
}
|
||||
a:hover {
|
||||
color: #982c61;
|
||||
border-bottom: 2px solid #4a4a4a;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #1d7484;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img, video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
pre {
|
||||
background-color: #f1f1f1;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code, kbd, samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #f1f1f1;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
input, textarea {
|
||||
border: 1px solid #4a4a4a;
|
||||
}
|
||||
input:focus, textarea:focus {
|
||||
border: 1px solid #1d7484;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button, button, input[type=submit], input[type=reset], input[type=button] {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #1d7484;
|
||||
color: #f9f9f9;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #1d7484;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled], button[disabled], input[type=submit][disabled], input[type=reset][disabled], input[type=button][disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:focus:enabled, .button:hover:enabled, button:focus:enabled, button:hover:enabled, input[type=submit]:focus:enabled, input[type=submit]:hover:enabled, input[type=reset]:focus:enabled, input[type=reset]:hover:enabled, input[type=button]:focus:enabled, input[type=button]:hover:enabled {
|
||||
background-color: #982c61;
|
||||
border-color: #982c61;
|
||||
color: #f9f9f9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
textarea, select, input {
|
||||
color: #4a4a4a;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus, select:focus, input:focus {
|
||||
border: 1px solid #1d7484;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type=checkbox]:focus {
|
||||
outline: 1px dotted #1d7484;
|
||||
}
|
||||
|
||||
label, legend, fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
374
runtime/logs/webman-2024-11-04.log
Normal file
374
runtime/logs/webman-2024-11-04.log
Normal file
@ -0,0 +1,374 @@
|
||||
[2024-11-04 19:39:05] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: could not find driver in /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php:70
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(70): PDO->__construct()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(46): Illuminate\Database\Connectors\Connector->createPdoConnection()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connectors/MySqlConnector.php(24): Illuminate\Database\Connectors\Connector->createConnection()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connectors/ConnectionFactory.php(184): Illuminate\Database\Connectors\MySqlConnector->connect()
|
||||
#4 [internal function]: Illuminate\Database\Connectors\ConnectionFactory->Illuminate\Database\Connectors\{closure}()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Connection.php(1181): call_user_func()
|
||||
#6 /www/SPQRjump/vendor/illuminate/database/Connection.php(1217): Illuminate\Database\Connection->getPdo()
|
||||
#7 /www/SPQRjump/vendor/illuminate/database/Connection.php(486): Illuminate\Database\Connection->getReadPdo()
|
||||
#8 /www/SPQRjump/vendor/illuminate/database/Connection.php(414): Illuminate\Database\Connection->getPdoForSelect()
|
||||
#9 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#10 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#11 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#12 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#13 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#15 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#18 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#19 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#20 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#21 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#22 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#23 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#24 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#25 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#26 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#27 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#28 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: could not find driver (SQL: select exists(select * from `links` where `link` = 6271) as `exists`) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#3 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#17 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#18 {main} [] []
|
||||
[2024-11-04 19:42:51] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: could not find driver in /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php:70
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(70): PDO->__construct()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(46): Illuminate\Database\Connectors\Connector->createPdoConnection()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connectors/MySqlConnector.php(24): Illuminate\Database\Connectors\Connector->createConnection()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connectors/ConnectionFactory.php(184): Illuminate\Database\Connectors\MySqlConnector->connect()
|
||||
#4 [internal function]: Illuminate\Database\Connectors\ConnectionFactory->Illuminate\Database\Connectors\{closure}()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Connection.php(1181): call_user_func()
|
||||
#6 /www/SPQRjump/vendor/illuminate/database/Connection.php(1217): Illuminate\Database\Connection->getPdo()
|
||||
#7 /www/SPQRjump/vendor/illuminate/database/Connection.php(486): Illuminate\Database\Connection->getReadPdo()
|
||||
#8 /www/SPQRjump/vendor/illuminate/database/Connection.php(414): Illuminate\Database\Connection->getPdoForSelect()
|
||||
#9 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#10 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#11 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#12 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#13 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#15 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#18 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#19 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#20 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#21 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#22 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#23 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#24 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#25 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#26 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: could not find driver (SQL: select exists(select * from `links` where `link` = 6271) as `exists`) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#3 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#15 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#16 {main} [] []
|
||||
[2024-11-04 19:46:31] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: SQLSTATE[HY000] [3159] Connections using insecure transport are prohibited while --require_secure_transport=ON. in /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php:70
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(70): PDO->__construct()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connectors/Connector.php(46): Illuminate\Database\Connectors\Connector->createPdoConnection()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connectors/MySqlConnector.php(24): Illuminate\Database\Connectors\Connector->createConnection()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connectors/ConnectionFactory.php(184): Illuminate\Database\Connectors\MySqlConnector->connect()
|
||||
#4 [internal function]: Illuminate\Database\Connectors\ConnectionFactory->Illuminate\Database\Connectors\{closure}()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Connection.php(1181): call_user_func()
|
||||
#6 /www/SPQRjump/vendor/illuminate/database/Connection.php(1217): Illuminate\Database\Connection->getPdo()
|
||||
#7 /www/SPQRjump/vendor/illuminate/database/Connection.php(486): Illuminate\Database\Connection->getReadPdo()
|
||||
#8 /www/SPQRjump/vendor/illuminate/database/Connection.php(414): Illuminate\Database\Connection->getPdoForSelect()
|
||||
#9 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#10 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#11 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#12 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#13 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#15 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#18 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#19 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#20 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#21 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#22 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#23 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#24 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#25 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#26 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: SQLSTATE[HY000] [3159] Connections using insecure transport are prohibited while --require_secure_transport=ON. (SQL: select exists(select * from `links` where `link` = 6271) as `exists`) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3030): Illuminate\Database\Connection->select()
|
||||
#3 /www/SPQRjump/app/controller/Server.php(49): Illuminate\Database\Query\Builder->exists()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#15 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#16 {main} [] []
|
||||
[2024-11-04 19:53:15] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user' cannot be null in /www/SPQRjump/vendor/illuminate/database/Connection.php:545
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(545): PDOStatement->execute()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#4 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#6 /www/SPQRjump/app/controller/Server.php(69): Illuminate\Database\Query\Builder->insert()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#8 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#9 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#11 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#18 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#19 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user' cannot be null (SQL: insert into `links` (`link`, `source`, `owner`, `webid`, `user`, `type`, `time`) values (6271, https://www.cnki.net/, 《中国学术期刊(光盘版)》电子杂志社有限公司, 京ICP备11019815号-4, ?, false, 1730721195)) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#4 /www/SPQRjump/app/controller/Server.php(69): Illuminate\Database\Query\Builder->insert()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#9 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#15 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#16 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#17 {main} [] []
|
||||
[2024-11-04 19:54:20] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'false' for column 'type' at row 1 in /www/SPQRjump/vendor/illuminate/database/Connection.php:545
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(545): PDOStatement->execute()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#4 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#6 /www/SPQRjump/app/controller/Server.php(72): Illuminate\Database\Query\Builder->insert()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#8 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#9 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#11 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#18 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#19 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#20 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#21 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'false' for column 'type' at row 1 (SQL: insert into `links` (`link`, `source`, `owner`, `webid`, `user`, `type`, `time`) values (6271, https://www.cnki.net/, 《中国学术期刊(光盘版)》电子杂志社有限公司, 京ICP备11019815号-4, anonymous, false, 1730721260)) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#4 /www/SPQRjump/app/controller/Server.php(72): Illuminate\Database\Query\Builder->insert()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#9 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#18 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#19 {main} [] []
|
||||
[2024-11-04 19:54:58] default.ERROR: 127.0.0.1 POST localhost:8780/!/short
|
||||
PDOException: SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '1730721298' for column 'time' at row 1 in /www/SPQRjump/vendor/illuminate/database/Connection.php:545
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(545): PDOStatement->execute()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#4 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#6 /www/SPQRjump/app/controller/Server.php(77): Illuminate\Database\Query\Builder->insert()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#8 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#9 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#11 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#18 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#19 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#20 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#21 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '1730721298' for column 'time' at row 1 (SQL: insert into `links` (`link`, `source`, `owner`, `webid`, `user`, `type`, `time`) values (6271, https://www.cnki.net/, 《中国学术期刊(光盘版)》电子杂志社有限公司, 京ICP备11019815号-4, anonymous, 0, 1730721298)) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(546): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(498): Illuminate\Database\Connection->statement()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3274): Illuminate\Database\Connection->insert()
|
||||
#4 /www/SPQRjump/app/controller/Server.php(77): Illuminate\Database\Query\Builder->insert()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->short()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#9 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#18 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#19 {main} [] []
|
||||
[2024-11-04 23:14:35] default.ERROR: 127.0.0.1 GET localhost:8780/ed62
|
||||
ErrorException: Undefined variable $code in /www/SPQRjump/app/controller/Server.php:86
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/controller/Server.php(86): support\App::{closure}()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->view()
|
||||
#2 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(369): Webman\App::Webman\{closure}()
|
||||
#3 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#5 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#6 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#15 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#16 {main} [] []
|
||||
[2024-11-04 23:14:53] default.ERROR: 127.0.0.1 GET localhost:8780/ed62
|
||||
ErrorException: Undefined variable $ba in /www/SPQRjump/app/controller/Server.php:94
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/controller/Server.php(94): support\App::{closure}()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Server->view()
|
||||
#2 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(369): Webman\App::Webman\{closure}()
|
||||
#3 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#5 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#6 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#15 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#16 {main} [] []
|
||||
[2024-11-04 23:57:53] default.ERROR: 127.0.0.1 POST localhost:8780/!/loginapi
|
||||
TypeError: count(): Argument #1 ($value) must be of type Countable|array, string given in /www/SPQRjump/app/controller/Account.php:55
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/controller/Account.php(55): count()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->loginapi()
|
||||
#2 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(141): Webman\App::Webman\{closure}()
|
||||
#3 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#4 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#5 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#6 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#12 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#13 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#14 {main} [] []
|
||||
[2024-11-04 23:59:50] default.ERROR: 127.0.0.1 GET localhost:8780
|
||||
ErrorException: Undefined variable $realname in /www/SPQRjump/app/view/index.html:142
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/view/index.html(142): support\App::{closure}()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/support/view/Raw.php(70): include('...')
|
||||
#2 /www/SPQRjump/support/helpers.php(201): support\view\Raw::render()
|
||||
#3 /www/SPQRjump/app/controller/IndexController.php(14): view()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\IndexController->index()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#17 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#18 {main} [] []
|
114
runtime/logs/webman-2024-11-05.log
Normal file
114
runtime/logs/webman-2024-11-05.log
Normal file
@ -0,0 +1,114 @@
|
||||
[2024-11-05 00:23:54] default.ERROR: 127.0.0.1 GET localhost:8780/!/my
|
||||
ParseError: Unclosed '{' on line 36 in /www/SPQRjump/app/view/my.html:58
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/support/helpers.php(201): support\view\Raw::render()
|
||||
#1 /www/SPQRjump/app/controller/Account.php(39): view()
|
||||
#2 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->my()
|
||||
#3 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#5 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#6 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#8 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(560): Workerman\Worker::forkWorkers()
|
||||
#12 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#13 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#14 {main} [] []
|
||||
[2024-11-05 00:25:15] default.ERROR: 127.0.0.1 GET localhost:8780/!/my
|
||||
ErrorException: Undefined property: Illuminate\Database\MySqlConnection::$link in /www/SPQRjump/app/view/my.html:38
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/view/my.html(38): support\App::{closure}()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/support/view/Raw.php(70): include('...')
|
||||
#2 /www/SPQRjump/support/helpers.php(201): support\view\Raw::render()
|
||||
#3 /www/SPQRjump/app/controller/Account.php(39): view()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->my()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#17 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#18 {main} [] []
|
||||
[2024-11-05 00:26:24] default.ERROR: 127.0.0.1 GET localhost:8780/!/my
|
||||
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'enoch' in 'field list' in /www/SPQRjump/vendor/illuminate/database/Connection.php:414
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(414): PDO->prepare()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(753): Illuminate\Database\Connection->Illuminate\Database\{closure}()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#4 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2706): Illuminate\Database\Connection->select()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2694): Illuminate\Database\Query\Builder->runSelect()
|
||||
#6 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3230): Illuminate\Database\Query\Builder->Illuminate\Database\Query\{closure}()
|
||||
#7 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2695): Illuminate\Database\Query\Builder->onceWithColumns()
|
||||
#8 /www/SPQRjump/app/controller/Account.php(38): Illuminate\Database\Query\Builder->get()
|
||||
#9 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->my()
|
||||
#10 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#11 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#13 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#18 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#19 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#20 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#21 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#22 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#23 {main}
|
||||
|
||||
Next Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'enoch' in 'field list' (SQL: select `owner`, `enoch` from `links`) in /www/SPQRjump/vendor/illuminate/database/Connection.php:760
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/vendor/illuminate/database/Connection.php(720): Illuminate\Database\Connection->runQueryCallback()
|
||||
#1 /www/SPQRjump/vendor/illuminate/database/Connection.php(422): Illuminate\Database\Connection->run()
|
||||
#2 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2706): Illuminate\Database\Connection->select()
|
||||
#3 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2694): Illuminate\Database\Query\Builder->runSelect()
|
||||
#4 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(3230): Illuminate\Database\Query\Builder->Illuminate\Database\Query\{closure}()
|
||||
#5 /www/SPQRjump/vendor/illuminate/database/Query/Builder.php(2695): Illuminate\Database\Query\Builder->onceWithColumns()
|
||||
#6 /www/SPQRjump/app/controller/Account.php(38): Illuminate\Database\Query\Builder->get()
|
||||
#7 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->my()
|
||||
#8 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#9 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#11 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#16 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#17 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#18 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#19 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#20 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#21 {main} [] []
|
||||
[2024-11-05 00:27:11] default.ERROR: 127.0.0.1 GET localhost:8780/!/my
|
||||
ErrorException: Undefined property: Illuminate\Database\MySqlConnection::$link in /www/SPQRjump/app/view/my.html:38
|
||||
Stack trace:
|
||||
#0 /www/SPQRjump/app/view/my.html(38): support\App::{closure}()
|
||||
#1 /www/SPQRjump/vendor/workerman/webman-framework/src/support/view/Raw.php(70): include('...')
|
||||
#2 /www/SPQRjump/support/helpers.php(201): support\view\Raw::render()
|
||||
#3 /www/SPQRjump/app/controller/Account.php(40): view()
|
||||
#4 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(319): app\controller\Account->my()
|
||||
#5 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(560): Webman\App::Webman\{closure}()
|
||||
#6 /www/SPQRjump/vendor/workerman/webman-framework/src/App.php(148): Webman\App::findRoute()
|
||||
#7 /www/SPQRjump/vendor/workerman/workerman/Connection/TcpConnection.php(646): Webman\App->onMessage()
|
||||
#8 [internal function]: Workerman\Connection\TcpConnection->baseRead()
|
||||
#9 /www/SPQRjump/vendor/workerman/workerman/Events/Event.php(193): EventBase->loop()
|
||||
#10 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1638): Workerman\Events\Event->loop()
|
||||
#11 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1429): Workerman\Worker::forkOneWorkerForLinux()
|
||||
#12 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1403): Workerman\Worker::forkWorkersForLinux()
|
||||
#13 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1788): Workerman\Worker::forkWorkers()
|
||||
#14 /www/SPQRjump/vendor/workerman/workerman/Worker.php(1724): Workerman\Worker::monitorWorkersForLinux()
|
||||
#15 /www/SPQRjump/vendor/workerman/workerman/Worker.php(562): Workerman\Worker::monitorWorkers()
|
||||
#16 /www/SPQRjump/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
|
||||
#17 /www/SPQRjump/start.php(4): support\App::run()
|
||||
#18 {main} [] []
|
135
runtime/logs/workerman.log
Normal file
135
runtime/logs/workerman.log
Normal file
@ -0,0 +1,135 @@
|
||||
2024-11-04 15:41:56 pid:5686 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 15:43:21 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 15:44:33 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 15:49:31 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:05:12 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:05:20 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:05:40 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:08:02 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:10:14 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:10:52 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:11:04 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:15:29 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:19:19 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:27:52 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 16:33:06 pid:5686 Workerman[start.php] reloading
|
||||
2024-11-04 19:11:11 pid:5686 Workerman[start.php] stopping ...
|
||||
2024-11-04 19:11:12 pid:5686 Workerman[start.php] has been stopped
|
||||
2024-11-04 19:35:58 pid:23658 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 19:37:16 pid:23658 Workerman[start.php] reloading
|
||||
2024-11-04 19:37:17 pid:23658 Workerman[start.php] stopping ...
|
||||
2024-11-04 19:37:18 pid:23658 Workerman[start.php] has been stopped
|
||||
2024-11-04 19:37:24 pid:24988 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 19:38:10 pid:24988 Workerman[start.php] reloading
|
||||
2024-11-04 19:38:39 pid:24988 Workerman[start.php] reloading
|
||||
2024-11-04 19:39:42 pid:24988 Workerman[start.php] stopping ...
|
||||
2024-11-04 19:39:42 pid:24988 Workerman[start.php] has been stopped
|
||||
2024-11-04 19:42:45 pid:28498 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 19:44:44 pid:28498 Workerman[start.php] stopping ...
|
||||
2024-11-04 19:44:44 pid:28498 Workerman[start.php] has been stopped
|
||||
2024-11-04 19:46:27 pid:30000 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 19:54:16 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 19:54:51 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:44:39 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:46:14 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:46:44 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:48:16 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:52:23 pid:30000 Workerman[start.php] reloading
|
||||
2024-11-04 22:53:42 pid:30000 Workerman[start.php] stopping ...
|
||||
2024-11-04 22:53:42 pid:30000 Workerman[start.php] has been stopped
|
||||
2024-11-04 22:55:54 pid:2219 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 23:00:07 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:06:02 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:09:06 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:09:28 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:09:35 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:10:02 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:10:08 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:10:14 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:04 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:13 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:19 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:25 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:33 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:48 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:13:54 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:14:22 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:14:50 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:15:13 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:17:01 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:17:18 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:18:00 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:25:18 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:28:01 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:31:04 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:35:22 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:35:39 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:35:50 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:36:09 pid:2219 Workerman[start.php] reloading
|
||||
2024-11-04 23:36:11 pid:2219 Workerman[start.php] stopping ...
|
||||
2024-11-04 23:36:11 pid:2219 Workerman[start.php] has been stopped
|
||||
2024-11-04 23:36:33 pid:14722 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 23:37:12 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:38:47 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:38:55 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:42:23 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:42:54 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:43:52 pid:14722 Workerman[start.php] reloading
|
||||
2024-11-04 23:44:23 pid:14722 Workerman[start.php] stopping ...
|
||||
2024-11-04 23:44:23 pid:14722 Workerman[start.php] has been stopped
|
||||
2024-11-04 23:45:28 pid:17683 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-04 23:45:37 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:47:16 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:47:32 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:48:05 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:49:42 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:50:09 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:50:33 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:50:49 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:52:45 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:57:35 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:58:10 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:58:55 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:58:58 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:59:35 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:59:48 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:59:56 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-04 23:59:57 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:01:10 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:01:18 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:03:28 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:04:52 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:05:54 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:06:19 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:08:00 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:11:41 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:14:04 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:14:07 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:14:35 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:14:56 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:16:47 pid:17683 Workerman[start.php] reloading
|
||||
2024-11-05 00:23:50 pid:17683 Workerman[start.php] stopping ...
|
||||
2024-11-05 00:23:50 pid:17683 Workerman[start.php] has been stopped
|
||||
2024-11-05 00:23:51 pid:30205 Workerman[start.php] start in DEBUG mode
|
||||
2024-11-05 00:24:43 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:24:55 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:25:08 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:26:21 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:26:53 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:27:09 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:27:33 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:28:04 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:29:59 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:30:15 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:31:08 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:32:10 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:37:46 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:38:29 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:38:41 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:39:30 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:39:43 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:40:44 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:41:08 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:41:47 pid:30205 Workerman[start.php] reloading
|
||||
2024-11-05 00:43:44 pid:30205 Workerman[start.php] stopping ...
|
||||
2024-11-05 00:43:44 pid:30205 Workerman[start.php] has been stopped
|
@ -0,0 +1 @@
|
||||
a:2:{s:7:"captcha";s:5:"tcqyy";s:4:"user";s:5:"enoch";}
|
@ -0,0 +1 @@
|
||||
a:3:{s:7:"captcha";s:5:"sq8y4";s:4:"user";s:5:"enoch";s:8:"realname";s:9:"以诺书";}
|
4
start.php
Executable file
4
start.php
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
support\App::run();
|
24
support/Request.php
Normal file
24
support/Request.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package support
|
||||
*/
|
||||
class Request extends \Webman\Http\Request
|
||||
{
|
||||
|
||||
}
|
24
support/Response.php
Normal file
24
support/Response.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package support
|
||||
*/
|
||||
class Response extends \Webman\Http\Response
|
||||
{
|
||||
|
||||
}
|
133
support/bootstrap.php
Normal file
133
support/bootstrap.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use support\Log;
|
||||
use Webman\Bootstrap;
|
||||
use Webman\Config;
|
||||
use Webman\Middleware;
|
||||
use Webman\Route;
|
||||
use Webman\Util;
|
||||
|
||||
$worker = $worker ?? null;
|
||||
|
||||
set_error_handler(function ($level, $message, $file = '', $line = 0) {
|
||||
if (error_reporting() & $level) {
|
||||
throw new ErrorException($message, 0, $level, $file, $line);
|
||||
}
|
||||
});
|
||||
|
||||
if ($worker) {
|
||||
register_shutdown_function(function ($startTime) {
|
||||
if (time() - $startTime <= 0.1) {
|
||||
sleep(1);
|
||||
}
|
||||
}, time());
|
||||
}
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
|
||||
Dotenv::createUnsafeMutable(base_path(false))->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path(false))->load();
|
||||
}
|
||||
}
|
||||
|
||||
Config::clear();
|
||||
support\App::loadAllConfig(['route']);
|
||||
if ($timezone = config('app.default_timezone')) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
foreach (config('autoload.files', []) as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
foreach ($projects['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
Middleware::load(config('middleware', []));
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project) || $name === 'static') {
|
||||
continue;
|
||||
}
|
||||
Middleware::load($project['middleware'] ?? []);
|
||||
}
|
||||
Middleware::load($projects['middleware'] ?? [], $firm);
|
||||
if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
|
||||
Middleware::load(['__static__' => $staticMiddlewares], $firm);
|
||||
}
|
||||
}
|
||||
Middleware::load(['__static__' => config('static.middleware', [])]);
|
||||
|
||||
foreach (config('bootstrap', []) as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['bootstrap'] ?? [] as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
foreach ($projects['bootstrap'] ?? [] as $className) {
|
||||
/** @var string $className */
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
|
||||
$directory = base_path() . '/plugin';
|
||||
$paths = [config_path()];
|
||||
foreach (Util::scanDir($directory) as $path) {
|
||||
if (is_dir($path = "$path/config")) {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
Route::load($paths);
|
||||
|
528
support/helpers.php
Normal file
528
support/helpers.php
Normal file
@ -0,0 +1,528 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Container;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\Translation;
|
||||
use support\view\Blade;
|
||||
use support\view\Raw;
|
||||
use support\view\ThinkPHP;
|
||||
use support\view\Twig;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Webman\App;
|
||||
use Webman\Config;
|
||||
use Webman\Route;
|
||||
use Workerman\Protocols\Http\Session;
|
||||
use Workerman\Worker;
|
||||
|
||||
// Project base path
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* return the program execute directory
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function run_path(string $path = ''): string
|
||||
{
|
||||
static $runPath = '';
|
||||
if (!$runPath) {
|
||||
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
|
||||
}
|
||||
return path_combine($runPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the param $path equal false,will return this program current execute directory
|
||||
* @param string|false $path
|
||||
* @return string
|
||||
*/
|
||||
function base_path($path = ''): string
|
||||
{
|
||||
if (false === $path) {
|
||||
return run_path();
|
||||
}
|
||||
return path_combine(BASE_PATH, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* App path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function app_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function public_path(string $path = ''): string
|
||||
{
|
||||
static $publicPath = '';
|
||||
if (!$publicPath) {
|
||||
$publicPath = \config('app.public_path') ?: run_path('public');
|
||||
}
|
||||
return path_combine($publicPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Config path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function config_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function runtime_path(string $path = ''): string
|
||||
{
|
||||
static $runtimePath = '';
|
||||
if (!$runtimePath) {
|
||||
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
|
||||
}
|
||||
return path_combine($runtimePath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate paths based on given information
|
||||
* @param string $front
|
||||
* @param string $back
|
||||
* @return string
|
||||
*/
|
||||
function path_combine(string $front, string $back): string
|
||||
{
|
||||
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
|
||||
}
|
||||
|
||||
/**
|
||||
* Response
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param string $body
|
||||
* @return Response
|
||||
*/
|
||||
function response(string $body = '', int $status = 200, array $headers = []): Response
|
||||
{
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Json response
|
||||
* @param $data
|
||||
* @param int $options
|
||||
* @return Response
|
||||
*/
|
||||
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
|
||||
{
|
||||
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml response
|
||||
* @param $xml
|
||||
* @return Response
|
||||
*/
|
||||
function xml($xml): Response
|
||||
{
|
||||
if ($xml instanceof SimpleXMLElement) {
|
||||
$xml = $xml->asXML();
|
||||
}
|
||||
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jsonp response
|
||||
* @param $data
|
||||
* @param string $callbackName
|
||||
* @return Response
|
||||
*/
|
||||
function jsonp($data, string $callbackName = 'callback'): Response
|
||||
{
|
||||
if (!is_scalar($data) && null !== $data) {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
return new Response(200, [], "$callbackName($data)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect response
|
||||
* @param string $location
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return Response
|
||||
*/
|
||||
function redirect(string $location, int $status = 302, array $headers = []): Response
|
||||
{
|
||||
$response = new Response($status, ['Location' => $location]);
|
||||
if (!empty($headers)) {
|
||||
$response->withHeaders($headers);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* View response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return Response
|
||||
*/
|
||||
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
function raw_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Raw::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blade view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function blade_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Blade::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Think view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function think_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws LoaderError
|
||||
* @throws RuntimeError
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
function twig_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Twig::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request
|
||||
* @return \Webman\Http\Request|Request|null
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return App::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config
|
||||
* @param string|null $key
|
||||
* @param $default
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
function config(string $key = null, $default = null)
|
||||
{
|
||||
return Config::get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create url
|
||||
* @param string $name
|
||||
* @param ...$parameters
|
||||
* @return string
|
||||
*/
|
||||
function route(string $name, ...$parameters): string
|
||||
{
|
||||
$route = Route::getByName($name);
|
||||
if (!$route) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$parameters) {
|
||||
return $route->url();
|
||||
}
|
||||
|
||||
if (is_array(current($parameters))) {
|
||||
$parameters = current($parameters);
|
||||
}
|
||||
|
||||
return $route->url($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed|bool|Session
|
||||
*/
|
||||
function session($key = null, $default = null)
|
||||
{
|
||||
$session = \request()->session();
|
||||
if (null === $key) {
|
||||
return $session;
|
||||
}
|
||||
if (is_array($key)) {
|
||||
$session->put($key);
|
||||
return null;
|
||||
}
|
||||
if (strpos($key, '.')) {
|
||||
$keyArray = explode('.', $key);
|
||||
$value = $session->all();
|
||||
foreach ($keyArray as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
return $session->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation
|
||||
* @param string $id
|
||||
* @param array $parameters
|
||||
* @param string|null $domain
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
|
||||
{
|
||||
$res = Translation::trans($id, $parameters, $domain, $locale);
|
||||
return $res === '' ? $id : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function locale(string $locale = null): string
|
||||
{
|
||||
if (!$locale) {
|
||||
return Translation::getLocale();
|
||||
}
|
||||
Translation::setLocale($locale);
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 not found
|
||||
* @return Response
|
||||
*/
|
||||
function not_found(): Response
|
||||
{
|
||||
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy dir
|
||||
* @param string $source
|
||||
* @param string $dest
|
||||
* @param bool $overwrite
|
||||
* @return void
|
||||
*/
|
||||
function copy_dir(string $source, string $dest, bool $overwrite = false)
|
||||
{
|
||||
if (is_dir($source)) {
|
||||
if (!is_dir($dest)) {
|
||||
mkdir($dest);
|
||||
}
|
||||
$files = scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if ($file !== "." && $file !== "..") {
|
||||
copy_dir("$source/$file", "$dest/$file", $overwrite);
|
||||
}
|
||||
}
|
||||
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
|
||||
copy($source, $dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dir
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
*/
|
||||
function remove_dir(string $dir): bool
|
||||
{
|
||||
if (is_link($dir) || is_file($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
$files = array_diff(scandir($dir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind worker
|
||||
* @param $worker
|
||||
* @param $class
|
||||
*/
|
||||
function worker_bind($worker, $class)
|
||||
{
|
||||
$callbackMap = [
|
||||
'onConnect',
|
||||
'onMessage',
|
||||
'onClose',
|
||||
'onError',
|
||||
'onBufferFull',
|
||||
'onBufferDrain',
|
||||
'onWorkerStop',
|
||||
'onWebSocketConnect',
|
||||
'onWorkerReload'
|
||||
];
|
||||
foreach ($callbackMap as $name) {
|
||||
if (method_exists($class, $name)) {
|
||||
$worker->$name = [$class, $name];
|
||||
}
|
||||
}
|
||||
if (method_exists($class, 'onWorkerStart')) {
|
||||
call_user_func([$class, 'onWorkerStart'], $worker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start worker
|
||||
* @param $processName
|
||||
* @param $config
|
||||
* @return void
|
||||
*/
|
||||
function worker_start($processName, $config)
|
||||
{
|
||||
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
|
||||
$propertyMap = [
|
||||
'count',
|
||||
'user',
|
||||
'group',
|
||||
'reloadable',
|
||||
'reusePort',
|
||||
'transport',
|
||||
'protocol',
|
||||
];
|
||||
$worker->name = $processName;
|
||||
foreach ($propertyMap as $property) {
|
||||
if (isset($config[$property])) {
|
||||
$worker->$property = $config[$property];
|
||||
}
|
||||
}
|
||||
|
||||
$worker->onWorkerStart = function ($worker) use ($config) {
|
||||
require_once base_path('/support/bootstrap.php');
|
||||
if (isset($config['handler'])) {
|
||||
if (!class_exists($config['handler'])) {
|
||||
echo "process error: class {$config['handler']} not exists\r\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
|
||||
worker_bind($worker, $instance);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get realpath
|
||||
* @param string $filePath
|
||||
* @return string
|
||||
*/
|
||||
function get_realpath(string $filePath): string
|
||||
{
|
||||
if (strpos($filePath, 'phar://') === 0) {
|
||||
return $filePath;
|
||||
} else {
|
||||
return realpath($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is phar
|
||||
* @return bool
|
||||
*/
|
||||
function is_phar(): bool
|
||||
{
|
||||
return class_exists(Phar::class, false) && Phar::running();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cpu count
|
||||
* @return int
|
||||
*/
|
||||
function cpu_count(): int
|
||||
{
|
||||
// Windows does not support the number of processes setting.
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return 1;
|
||||
}
|
||||
$count = 4;
|
||||
if (is_callable('shell_exec')) {
|
||||
if (strtolower(PHP_OS) === 'darwin') {
|
||||
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
|
||||
} else {
|
||||
$count = (int)shell_exec('nproc');
|
||||
}
|
||||
}
|
||||
return $count > 0 ? $count : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request parameters, if no parameter name is passed, an array of all values is returned, default values is supported
|
||||
* @param string|null $param param's name
|
||||
* @param mixed|null $default default value
|
||||
* @return mixed|null
|
||||
*/
|
||||
function input(string $param = null, $default = null)
|
||||
{
|
||||
return is_null($param) ? request()->all() : request()->input($param, $default);
|
||||
}
|
25
vendor/autoload.php
vendored
Normal file
25
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7604022b3ed72e518bc17cb475d0aba8::getLoader();
|
120
vendor/bin/carbon
vendored
Executable file
120
vendor/bin/carbon
vendored
Executable file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../nesbot/carbon/bin/carbon)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/nesbot/carbon/bin/carbon');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/nesbot/carbon/bin/carbon';
|
5
vendor/bin/carbon.bat
vendored
Executable file
5
vendor/bin/carbon.bat
vendored
Executable file
@ -0,0 +1,5 @@
|
||||
@ECHO OFF
|
||||
setlocal DISABLEDELAYEDEXPANSION
|
||||
SET BIN_TARGET=%~dp0/carbon
|
||||
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
|
||||
php "%BIN_TARGET%" %*
|
120
vendor/bin/phinx
vendored
Executable file
120
vendor/bin/phinx
vendored
Executable file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../robmorgan/phinx/bin/phinx)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/robmorgan/phinx/bin/phinx');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/robmorgan/phinx/bin/phinx';
|
5
vendor/bin/phinx.bat
vendored
Executable file
5
vendor/bin/phinx.bat
vendored
Executable file
@ -0,0 +1,5 @@
|
||||
@ECHO OFF
|
||||
setlocal DISABLEDELAYEDEXPANSION
|
||||
SET BIN_TARGET=%~dp0/phinx
|
||||
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
|
||||
php "%BIN_TARGET%" %*
|
120
vendor/bin/var-dump-server
vendored
Executable file
120
vendor/bin/var-dump-server
vendored
Executable file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../symfony/var-dumper/Resources/bin/var-dump-server)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';
|
5
vendor/bin/var-dump-server.bat
vendored
Executable file
5
vendor/bin/var-dump-server.bat
vendored
Executable file
@ -0,0 +1,5 @@
|
||||
@ECHO OFF
|
||||
setlocal DISABLEDELAYEDEXPANSION
|
||||
SET BIN_TARGET=%~dp0/var-dump-server
|
||||
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
|
||||
php "%BIN_TARGET%" %*
|
445
vendor/brick/math/CHANGELOG.md
vendored
Normal file
445
vendor/brick/math/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.11.0](https://github.com/brick/math/releases/tag/0.11.0) - 2023-01-16
|
||||
|
||||
💥 **Breaking changes**
|
||||
|
||||
- Minimum PHP version is now 8.0
|
||||
- Methods accepting a union of types are now strongly typed<sup>*</sup>
|
||||
- `MathException` now extends `Exception` instead of `RuntimeException`
|
||||
|
||||
<sup>* You may now run into type errors if you were passing `Stringable` objects to `of()` or any of the methods
|
||||
internally calling `of()`, with `strict_types` enabled. You can fix this by casting `Stringable` objects to `string`
|
||||
first.</sup>
|
||||
|
||||
## [0.10.2](https://github.com/brick/math/releases/tag/0.10.2) - 2022-08-11
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- `BigRational::toFloat()` now simplifies the fraction before performing division (#73) thanks to @olsavmic
|
||||
|
||||
## [0.10.1](https://github.com/brick/math/releases/tag/0.10.1) - 2022-08-02
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::gcdMultiple()` returns the GCD of multiple `BigInteger` numbers
|
||||
|
||||
## [0.10.0](https://github.com/brick/math/releases/tag/0.10.0) - 2022-06-18
|
||||
|
||||
💥 **Breaking changes**
|
||||
|
||||
- Minimum PHP version is now 7.4
|
||||
|
||||
## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15
|
||||
|
||||
🚀 **Compatibility with PHP 8.1**
|
||||
|
||||
- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (#60) thanks @TRowbotham
|
||||
|
||||
## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20
|
||||
|
||||
🐛 **Bug fix**
|
||||
|
||||
- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55).
|
||||
|
||||
## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::not()` returns the bitwise `NOT` value
|
||||
|
||||
🐛 **Bug fixes**
|
||||
|
||||
- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
|
||||
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
|
||||
|
||||
## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal`
|
||||
|
||||
💥 **Breaking changes**
|
||||
|
||||
- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead
|
||||
- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead
|
||||
|
||||
## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19
|
||||
|
||||
🐛 **Bug fix**
|
||||
|
||||
- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
|
||||
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
|
||||
|
||||
## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18
|
||||
|
||||
🚑 **Critical fix**
|
||||
|
||||
- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle.
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::modInverse()` calculates a modular multiplicative inverse
|
||||
- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string
|
||||
- `BigInteger::toBytes()` converts a `BigInteger` to a byte string
|
||||
- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length
|
||||
- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds
|
||||
|
||||
💩 **Deprecations**
|
||||
|
||||
- `BigInteger::powerMod()` is now deprecated in favour of `modPow()`
|
||||
|
||||
## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15
|
||||
|
||||
🐛 **Fixes**
|
||||
|
||||
- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable`
|
||||
|
||||
⚡️ **Optimizations**
|
||||
|
||||
- additional optimization in `BigInteger::remainder()`
|
||||
|
||||
## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit
|
||||
|
||||
## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::isEven()` tests whether the number is even
|
||||
- `BigInteger::isOdd()` tests whether the number is odd
|
||||
- `BigInteger::testBit()` tests if a bit is set
|
||||
- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number
|
||||
|
||||
## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03
|
||||
|
||||
🛠️ **Maintenance release**
|
||||
|
||||
Classes are now annotated for better static analysis with [psalm](https://psalm.dev/).
|
||||
|
||||
This is a maintenance release: no bug fixes, no new features, no breaking changes.
|
||||
|
||||
## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23
|
||||
|
||||
✨ **New feature**
|
||||
|
||||
`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto.
|
||||
|
||||
## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21
|
||||
|
||||
✨ **New feature**
|
||||
|
||||
`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different.
|
||||
|
||||
## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08
|
||||
|
||||
⚡️ **Performance improvements**
|
||||
|
||||
A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24.
|
||||
|
||||
## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25
|
||||
|
||||
🐛 **Bug fixes**
|
||||
|
||||
- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected)
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet
|
||||
- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number
|
||||
|
||||
These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation.
|
||||
|
||||
💩 **Deprecations**
|
||||
|
||||
- `BigInteger::parse()` is now deprecated in favour of `fromBase()`
|
||||
|
||||
`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences:
|
||||
|
||||
- the `$base` parameter is required, it does not default to `10`
|
||||
- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed
|
||||
|
||||
## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Safer conversion from `float` when using custom locales
|
||||
- **Much faster** `NativeCalculator` implementation 🚀
|
||||
|
||||
You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before.
|
||||
|
||||
## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11
|
||||
|
||||
**New method**
|
||||
|
||||
`BigNumber::sum()` returns the sum of one or more numbers.
|
||||
|
||||
## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12
|
||||
|
||||
**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20).
|
||||
|
||||
Thanks @manowark 👍
|
||||
|
||||
## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07
|
||||
|
||||
**New method**
|
||||
|
||||
`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale.
|
||||
|
||||
## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06
|
||||
|
||||
**New method**
|
||||
|
||||
`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k).
|
||||
|
||||
**New exception**
|
||||
|
||||
`NegativeNumberException` is thrown when calling `sqrt()` on a negative number.
|
||||
|
||||
## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08
|
||||
|
||||
**Performance update**
|
||||
|
||||
- Further improvement of `toInt()` performance
|
||||
- `NativeCalculator` can now perform some multiplications more efficiently
|
||||
|
||||
## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07
|
||||
|
||||
Performance optimization of `toInt()` methods.
|
||||
|
||||
## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13
|
||||
|
||||
**Breaking changes**
|
||||
|
||||
The following deprecated methods have been removed. Use the new method name instead:
|
||||
|
||||
| Method removed | Replacement method |
|
||||
| --- | --- |
|
||||
| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` |
|
||||
| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` |
|
||||
|
||||
---
|
||||
|
||||
**New features**
|
||||
|
||||
`BigInteger` has been augmented with 5 new methods for bitwise operations:
|
||||
|
||||
| New method | Description |
|
||||
| --- | --- |
|
||||
| `and()` | performs a bitwise `AND` operation on two numbers |
|
||||
| `or()` | performs a bitwise `OR` operation on two numbers |
|
||||
| `xor()` | performs a bitwise `XOR` operation on two numbers |
|
||||
| `shiftedLeft()` | returns the number shifted left by a number of bits |
|
||||
| `shiftedRight()` | returns the number shifted right by a number of bits |
|
||||
|
||||
Thanks to @DASPRiD 👍
|
||||
|
||||
## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20
|
||||
|
||||
**New method:** `BigDecimal::hasNonZeroFractionalPart()`
|
||||
|
||||
**Renamed/deprecated methods:**
|
||||
|
||||
- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated
|
||||
- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated
|
||||
|
||||
## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21
|
||||
|
||||
**Performance update**
|
||||
|
||||
`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available.
|
||||
|
||||
## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01
|
||||
|
||||
This is a maintenance release, no code has been changed.
|
||||
|
||||
- When installed with `--no-dev`, the autoloader does not autoload tests anymore
|
||||
- Tests and other files unnecessary for production are excluded from the dist package
|
||||
|
||||
This will help make installations more compact.
|
||||
|
||||
## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02
|
||||
|
||||
Methods renamed:
|
||||
|
||||
- `BigNumber:sign()` has been renamed to `getSign()`
|
||||
- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()`
|
||||
- `BigDecimal::scale()` has been renamed to `getScale()`
|
||||
- `BigDecimal::integral()` has been renamed to `getIntegral()`
|
||||
- `BigDecimal::fraction()` has been renamed to `getFraction()`
|
||||
- `BigRational::numerator()` has been renamed to `getNumerator()`
|
||||
- `BigRational::denominator()` has been renamed to `getDenominator()`
|
||||
|
||||
Classes renamed:
|
||||
|
||||
- `ArithmeticException` has been renamed to `MathException`
|
||||
|
||||
## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02
|
||||
|
||||
The base class for all exceptions is now `MathException`.
|
||||
`ArithmeticException` has been deprecated, and will be removed in 0.7.0.
|
||||
|
||||
## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02
|
||||
|
||||
A number of methods have been renamed:
|
||||
|
||||
- `BigNumber:sign()` is deprecated; use `getSign()` instead
|
||||
- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead
|
||||
- `BigDecimal::scale()` is deprecated; use `getScale()` instead
|
||||
- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead
|
||||
- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead
|
||||
- `BigRational::numerator()` is deprecated; use `getNumerator()` instead
|
||||
- `BigRational::denominator()` is deprecated; use `getDenominator()` instead
|
||||
|
||||
The old methods will be removed in version 0.7.0.
|
||||
|
||||
## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25
|
||||
|
||||
- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5`
|
||||
- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead
|
||||
- Method `BigNumber::toInteger()` has been renamed to `toInt()`
|
||||
|
||||
## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17
|
||||
|
||||
`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php).
|
||||
The JSON output is always a string.
|
||||
|
||||
## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31
|
||||
|
||||
This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
|
||||
|
||||
## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06
|
||||
|
||||
The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again.
|
||||
|
||||
## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05
|
||||
|
||||
**New method: `BigNumber::toScale()`**
|
||||
|
||||
This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary.
|
||||
|
||||
## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04
|
||||
|
||||
**New features**
|
||||
- Common `BigNumber` interface for all classes, with the following methods:
|
||||
- `sign()` and derived methods (`isZero()`, `isPositive()`, ...)
|
||||
- `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types
|
||||
- `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods
|
||||
- `toInteger()` and `toFloat()` conversion methods to native types
|
||||
- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type
|
||||
- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits
|
||||
- New methods: `BigRational::quotient()` and `remainder()`
|
||||
- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException`
|
||||
- Factory methods `zero()`, `one()` and `ten()` available in all classes
|
||||
- Rounding mode reintroduced in `BigInteger::dividedBy()`
|
||||
|
||||
This release also comes with many performance improvements.
|
||||
|
||||
---
|
||||
|
||||
**Breaking changes**
|
||||
- `BigInteger`:
|
||||
- `getSign()` is renamed to `sign()`
|
||||
- `toString()` is renamed to `toBase()`
|
||||
- `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour
|
||||
- `BigDecimal`:
|
||||
- `getSign()` is renamed to `sign()`
|
||||
- `getUnscaledValue()` is renamed to `unscaledValue()`
|
||||
- `getScale()` is renamed to `scale()`
|
||||
- `getIntegral()` is renamed to `integral()`
|
||||
- `getFraction()` is renamed to `fraction()`
|
||||
- `divideAndRemainder()` is renamed to `quotientAndRemainder()`
|
||||
- `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode
|
||||
- `toBigInteger()` does not accept a `$roundingMode` parameter anymore
|
||||
- `toBigRational()` does not simplify the fraction anymore; explicitly add `->simplified()` to get the previous behaviour
|
||||
- `BigRational`:
|
||||
- `getSign()` is renamed to `sign()`
|
||||
- `getNumerator()` is renamed to `numerator()`
|
||||
- `getDenominator()` is renamed to `denominator()`
|
||||
- `of()` is renamed to `nd()`, while `parse()` is renamed to `of()`
|
||||
- Miscellaneous:
|
||||
- `ArithmeticException` is moved to an `Exception\` sub-namespace
|
||||
- `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException`
|
||||
|
||||
## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31
|
||||
|
||||
Backport of two bug fixes from the 0.5 branch:
|
||||
- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
|
||||
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
|
||||
|
||||
## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16
|
||||
|
||||
New method: `BigDecimal::stripTrailingZeros()`
|
||||
|
||||
## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12
|
||||
|
||||
Introducing a `BigRational` class, to perform calculations on fractions of any size.
|
||||
|
||||
## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12
|
||||
|
||||
Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`.
|
||||
|
||||
`BigInteger::dividedBy()` now always returns the quotient of the division.
|
||||
|
||||
## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31
|
||||
|
||||
Backport of two bug fixes from the 0.5 branch:
|
||||
|
||||
- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
|
||||
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
|
||||
|
||||
## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11
|
||||
|
||||
New methods:
|
||||
- `BigInteger::remainder()` returns the remainder of a division only
|
||||
- `BigInteger::gcd()` returns the greatest common divisor of two numbers
|
||||
|
||||
## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07
|
||||
|
||||
Fix `toString()` not handling negative numbers.
|
||||
|
||||
## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07
|
||||
|
||||
`BigInteger` and `BigDecimal` now have a `getSign()` method that returns:
|
||||
- `-1` if the number is negative
|
||||
- `0` if the number is zero
|
||||
- `1` if the number is positive
|
||||
|
||||
## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05
|
||||
|
||||
Minor performance improvements
|
||||
|
||||
## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04
|
||||
|
||||
The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`.
|
||||
|
||||
## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04
|
||||
|
||||
Stronger immutability guarantee for `BigInteger` and `BigDecimal`.
|
||||
|
||||
So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that.
|
||||
|
||||
## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02
|
||||
|
||||
Added `BigDecimal::divideAndRemainder()`
|
||||
|
||||
## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22
|
||||
|
||||
- `min()` and `max()` do not accept an `array` anymore, but a variable number of parameters
|
||||
- **minimum PHP version is now 5.6**
|
||||
- continuous integration with PHP 7
|
||||
|
||||
## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01
|
||||
|
||||
- Added `BigInteger::power()`
|
||||
- Added HHVM support
|
||||
|
||||
## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31
|
||||
|
||||
First beta release.
|
||||
|
20
vendor/brick/math/LICENSE
vendored
Normal file
20
vendor/brick/math/LICENSE
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-present Benjamin Morel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
34
vendor/brick/math/composer.json
vendored
Normal file
34
vendor/brick/math/composer.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "brick/math",
|
||||
"description": "Arbitrary-precision arithmetic library",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"Brick",
|
||||
"Math",
|
||||
"Arbitrary-precision",
|
||||
"Arithmetic",
|
||||
"BigInteger",
|
||||
"BigDecimal",
|
||||
"BigRational",
|
||||
"Bignum"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"vimeo/psalm": "5.0.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\Tests\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
786
vendor/brick/math/src/BigDecimal.php
vendored
Normal file
786
vendor/brick/math/src/BigDecimal.php
vendored
Normal file
@ -0,0 +1,786 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NegativeNumberException;
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Immutable, arbitrary-precision signed decimal numbers.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class BigDecimal extends BigNumber
|
||||
{
|
||||
/**
|
||||
* The unscaled value of this decimal number.
|
||||
*
|
||||
* This is a string of digits with an optional leading minus sign.
|
||||
* No leading zero must be present.
|
||||
* No leading minus sign must be present if the value is 0.
|
||||
*/
|
||||
private string $value;
|
||||
|
||||
/**
|
||||
* The scale (number of digits after the decimal point) of this decimal number.
|
||||
*
|
||||
* This must be zero or more.
|
||||
*/
|
||||
private int $scale;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
*
|
||||
* @param string $value The unscaled value, validated.
|
||||
* @param int $scale The scale, validated.
|
||||
*/
|
||||
protected function __construct(string $value, int $scale = 0)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->scale = $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal of the given value.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigDecimal
|
||||
{
|
||||
return parent::of($value)->toBigDecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal from an unscaled value and a scale.
|
||||
*
|
||||
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
|
||||
* @param int $scale The scale of the number, positive or zero.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
|
||||
{
|
||||
if ($scale < 0) {
|
||||
throw new \InvalidArgumentException('The scale cannot be negative.');
|
||||
}
|
||||
|
||||
return new BigDecimal((string) BigInteger::of($value), $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing zero, with a scale of zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigDecimal
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigDecimal|null $zero
|
||||
*/
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigDecimal('0');
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing one, with a scale of zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigDecimal
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigDecimal|null $one
|
||||
*/
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigDecimal('1');
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing ten, with a scale of zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigDecimal
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigDecimal|null $ten
|
||||
*/
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigDecimal('10');
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function plus(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0' && $that->scale <= $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '0' && $this->scale <= $that->scale) {
|
||||
return $that;
|
||||
}
|
||||
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = Calculator::get()->add($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function minus(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0' && $that->scale <= $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = Calculator::get()->sub($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `$this->scale + $that->scale`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '1' && $that->scale === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '1' && $this->scale === 0) {
|
||||
return $that;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->mul($this->value, $that->value);
|
||||
$scale = $this->scale + $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one, at the given scale.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
* @param int|null $scale The desired scale, or null to use the scale of this number.
|
||||
* @param int $roundingMode An optional rounding mode.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
|
||||
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
if ($scale === null) {
|
||||
$scale = $this->scale;
|
||||
} elseif ($scale < 0) {
|
||||
throw new \InvalidArgumentException('Scale cannot be negative.');
|
||||
}
|
||||
|
||||
if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale + $scale);
|
||||
$q = $that->valueWithMinScale($this->scale - $scale);
|
||||
|
||||
$result = Calculator::get()->divRound($p, $q, $roundingMode);
|
||||
|
||||
return new BigDecimal($result, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exact result of the division of this number by the given one.
|
||||
*
|
||||
* The scale of the result is automatically calculated to fit all the fraction digits.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
|
||||
* or the result yields an infinite number of digits.
|
||||
*/
|
||||
public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
[, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$d = \rtrim($b, '0');
|
||||
$scale = \strlen($b) - \strlen($d);
|
||||
|
||||
$calculator = Calculator::get();
|
||||
|
||||
foreach ([5, 2] as $prime) {
|
||||
for (;;) {
|
||||
$lastDigit = (int) $d[-1];
|
||||
|
||||
if ($lastDigit % $prime !== 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$d = $calculator->divQ($d, (string) $prime);
|
||||
$scale++;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dividedBy($that, $scale)->stripTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
* The result has a scale of `$this->scale * $exponent`.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||
*/
|
||||
public function power(int $exponent) : BigDecimal
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
return BigDecimal::one();
|
||||
}
|
||||
|
||||
if ($exponent === 1) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($exponent < 0 || $exponent > Calculator::MAX_POWER) {
|
||||
throw new \InvalidArgumentException(\sprintf(
|
||||
'The exponent %d is not in the range 0 to %d.',
|
||||
$exponent,
|
||||
Calculator::MAX_POWER
|
||||
));
|
||||
}
|
||||
|
||||
return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of this number by this given one.
|
||||
*
|
||||
* The quotient has a scale of `0`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotient(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
$quotient = Calculator::get()->divQ($p, $q);
|
||||
|
||||
return new BigDecimal($quotient, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of this number by this given one.
|
||||
*
|
||||
* The remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function remainder(BigNumber|int|float|string $that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
$remainder = Calculator::get()->divR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($remainder, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of this number by the given one.
|
||||
*
|
||||
* The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal[] An array containing the quotient and the remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
[$quotient, $remainder] = Calculator::get()->divQR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
$quotient = new BigDecimal($quotient, 0);
|
||||
$remainder = new BigDecimal($remainder, $scale);
|
||||
|
||||
return [$quotient, $remainder];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of this number, rounded down to the given number of decimals.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
*/
|
||||
public function sqrt(int $scale) : BigDecimal
|
||||
{
|
||||
if ($scale < 0) {
|
||||
throw new \InvalidArgumentException('Scale cannot be negative.');
|
||||
}
|
||||
|
||||
if ($this->value === '0') {
|
||||
return new BigDecimal('0', $scale);
|
||||
}
|
||||
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||
}
|
||||
|
||||
$value = $this->value;
|
||||
$addDigits = 2 * $scale - $this->scale;
|
||||
|
||||
if ($addDigits > 0) {
|
||||
// add zeros
|
||||
$value .= \str_repeat('0', $addDigits);
|
||||
} elseif ($addDigits < 0) {
|
||||
// trim digits
|
||||
if (-$addDigits >= \strlen($this->value)) {
|
||||
// requesting a scale too low, will always yield a zero result
|
||||
return new BigDecimal('0', $scale);
|
||||
}
|
||||
|
||||
$value = \substr($value, 0, $addDigits);
|
||||
}
|
||||
|
||||
$value = Calculator::get()->sqrt($value);
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
|
||||
*/
|
||||
public function withPointMovedLeft(int $n) : BigDecimal
|
||||
{
|
||||
if ($n === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($n < 0) {
|
||||
return $this->withPointMovedRight(-$n);
|
||||
}
|
||||
|
||||
return new BigDecimal($this->value, $this->scale + $n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
|
||||
*/
|
||||
public function withPointMovedRight(int $n) : BigDecimal
|
||||
{
|
||||
if ($n === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($n < 0) {
|
||||
return $this->withPointMovedLeft(-$n);
|
||||
}
|
||||
|
||||
$value = $this->value;
|
||||
$scale = $this->scale - $n;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($value !== '0') {
|
||||
$value .= \str_repeat('0', -$scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
||||
*/
|
||||
public function stripTrailingZeros() : BigDecimal
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$trimmedValue = \rtrim($this->value, '0');
|
||||
|
||||
if ($trimmedValue === '') {
|
||||
return BigDecimal::zero();
|
||||
}
|
||||
|
||||
$trimmableZeros = \strlen($this->value) - \strlen($trimmedValue);
|
||||
|
||||
if ($trimmableZeros === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($trimmableZeros > $this->scale) {
|
||||
$trimmableZeros = $this->scale;
|
||||
}
|
||||
|
||||
$value = \substr($this->value, 0, -$trimmableZeros);
|
||||
$scale = $this->scale - $trimmableZeros;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
*/
|
||||
public function abs() : BigDecimal
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*/
|
||||
public function negated() : BigDecimal
|
||||
{
|
||||
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
|
||||
}
|
||||
|
||||
public function compareTo(BigNumber|int|float|string $that) : int
|
||||
{
|
||||
$that = BigNumber::of($that);
|
||||
|
||||
if ($that instanceof BigInteger) {
|
||||
$that = $that->toBigDecimal();
|
||||
}
|
||||
|
||||
if ($that instanceof BigDecimal) {
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
return Calculator::get()->cmp($a, $b);
|
||||
}
|
||||
|
||||
return - $that->compareTo($this);
|
||||
}
|
||||
|
||||
public function getSign() : int
|
||||
{
|
||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||
}
|
||||
|
||||
public function getUnscaledValue() : BigInteger
|
||||
{
|
||||
return self::newBigInteger($this->value);
|
||||
}
|
||||
|
||||
public function getScale() : int
|
||||
{
|
||||
return $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the integral part of this decimal number.
|
||||
*
|
||||
* Example: `-123.456` => `-123`.
|
||||
*/
|
||||
public function getIntegralPart() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, 0, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the fractional part of this decimal number.
|
||||
*
|
||||
* If the scale is zero, an empty string is returned.
|
||||
*
|
||||
* Examples: `-123.456` => '456', `123` => ''.
|
||||
*/
|
||||
public function getFractionalPart() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this decimal number has a non-zero fractional part.
|
||||
*/
|
||||
public function hasNonZeroFractionalPart() : bool
|
||||
{
|
||||
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
||||
}
|
||||
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
|
||||
|
||||
return self::newBigInteger($zeroScaleDecimal->value);
|
||||
}
|
||||
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
$numerator = self::newBigInteger($this->value);
|
||||
$denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
|
||||
|
||||
return self::newBigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
||||
}
|
||||
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
public function toFloat() : float
|
||||
{
|
||||
return (float) (string) $this;
|
||||
}
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required for serializing the object and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return array{value: string, scale: int}
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return ['value' => $this->value, 'scale' => $this->scale];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @param array{value: string, scale: int} $data
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
if (isset($this->value)) {
|
||||
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
$this->value = $data['value'];
|
||||
$this->scale = $data['scale'];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value . ':' . $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->value)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$value, $scale] = \explode(':', $value);
|
||||
|
||||
$this->value = $value;
|
||||
$this->scale = (int) $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the internal values of the given decimal numbers on the same scale.
|
||||
*
|
||||
* @return array{string, string} The scaled integer values of $x and $y.
|
||||
*/
|
||||
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
|
||||
{
|
||||
$a = $x->value;
|
||||
$b = $y->value;
|
||||
|
||||
if ($b !== '0' && $x->scale > $y->scale) {
|
||||
$b .= \str_repeat('0', $x->scale - $y->scale);
|
||||
} elseif ($a !== '0' && $x->scale < $y->scale) {
|
||||
$a .= \str_repeat('0', $y->scale - $x->scale);
|
||||
}
|
||||
|
||||
return [$a, $b];
|
||||
}
|
||||
|
||||
private function valueWithMinScale(int $scale) : string
|
||||
{
|
||||
$value = $this->value;
|
||||
|
||||
if ($this->value !== '0' && $scale > $this->scale) {
|
||||
$value .= \str_repeat('0', $scale - $this->scale);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
|
||||
*/
|
||||
private function getUnscaledValueWithLeadingZeros() : string
|
||||
{
|
||||
$value = $this->value;
|
||||
$targetLength = $this->scale + 1;
|
||||
$negative = ($value[0] === '-');
|
||||
$length = \strlen($value);
|
||||
|
||||
if ($negative) {
|
||||
$length--;
|
||||
}
|
||||
|
||||
if ($length >= $targetLength) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
if ($negative) {
|
||||
$value = \substr($value, 1);
|
||||
}
|
||||
|
||||
$value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT);
|
||||
|
||||
if ($negative) {
|
||||
$value = '-' . $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
1079
vendor/brick/math/src/BigInteger.php
vendored
Normal file
1079
vendor/brick/math/src/BigInteger.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
512
vendor/brick/math/src/BigNumber.php
vendored
Normal file
512
vendor/brick/math/src/BigNumber.php
vendored
Normal file
@ -0,0 +1,512 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
|
||||
/**
|
||||
* Common interface for arbitrary-precision rational numbers.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* The regular expression used to parse integer, decimal and rational numbers.
|
||||
*/
|
||||
private const PARSE_REGEXP =
|
||||
'/^' .
|
||||
'(?<sign>[\-\+])?' .
|
||||
'(?:' .
|
||||
'(?:' .
|
||||
'(?<integral>[0-9]+)?' .
|
||||
'(?<point>\.)?' .
|
||||
'(?<fractional>[0-9]+)?' .
|
||||
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
||||
')|(?:' .
|
||||
'(?<numerator>[0-9]+)' .
|
||||
'\/?' .
|
||||
'(?<denominator>[0-9]+)' .
|
||||
')' .
|
||||
')' .
|
||||
'$/';
|
||||
|
||||
/**
|
||||
* Creates a BigNumber of the given value.
|
||||
*
|
||||
* The concrete return type is dependent on the given value, with the following rules:
|
||||
*
|
||||
* - BigNumber instances are returned as is
|
||||
* - integer numbers are returned as BigInteger
|
||||
* - floating point numbers are converted to a string then parsed as such
|
||||
* - strings containing a `/` character are returned as BigRational
|
||||
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
|
||||
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
|
||||
*
|
||||
* @throws NumberFormatException If the format of the number is not valid.
|
||||
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_int($value)) {
|
||||
return new BigInteger((string) $value);
|
||||
}
|
||||
|
||||
$value = \is_float($value) ? self::floatToString($value) : $value;
|
||||
|
||||
$throw = static function() use ($value) : void {
|
||||
throw new NumberFormatException(\sprintf(
|
||||
'The given value "%s" does not represent a valid number.',
|
||||
$value
|
||||
));
|
||||
};
|
||||
|
||||
if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
|
||||
$throw();
|
||||
}
|
||||
|
||||
$getMatch = static fn(string $value): ?string => (($matches[$value] ?? '') !== '') ? $matches[$value] : null;
|
||||
|
||||
$sign = $getMatch('sign');
|
||||
$numerator = $getMatch('numerator');
|
||||
$denominator = $getMatch('denominator');
|
||||
|
||||
if ($numerator !== null) {
|
||||
assert($denominator !== null);
|
||||
|
||||
if ($sign !== null) {
|
||||
$numerator = $sign . $numerator;
|
||||
}
|
||||
|
||||
$numerator = self::cleanUp($numerator);
|
||||
$denominator = self::cleanUp($denominator);
|
||||
|
||||
if ($denominator === '0') {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
}
|
||||
|
||||
return new BigRational(
|
||||
new BigInteger($numerator),
|
||||
new BigInteger($denominator),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$point = $getMatch('point');
|
||||
$integral = $getMatch('integral');
|
||||
$fractional = $getMatch('fractional');
|
||||
$exponent = $getMatch('exponent');
|
||||
|
||||
if ($integral === null && $fractional === null) {
|
||||
$throw();
|
||||
}
|
||||
|
||||
if ($integral === null) {
|
||||
$integral = '0';
|
||||
}
|
||||
|
||||
if ($point !== null || $exponent !== null) {
|
||||
$fractional = ($fractional ?? '');
|
||||
$exponent = ($exponent !== null) ? (int) $exponent : 0;
|
||||
|
||||
if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
|
||||
throw new NumberFormatException('Exponent too large.');
|
||||
}
|
||||
|
||||
$unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', - $scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
}
|
||||
|
||||
$integral = self::cleanUp(($sign ?? '') . $integral);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely converts float to string, avoiding locale-dependent issues.
|
||||
*
|
||||
* @see https://github.com/brick/math/pull/20
|
||||
*
|
||||
* @psalm-pure
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
private static function floatToString(float $float) : string
|
||||
{
|
||||
$currentLocale = \setlocale(LC_NUMERIC, '0');
|
||||
\setlocale(LC_NUMERIC, 'C');
|
||||
|
||||
$result = (string) $float;
|
||||
|
||||
\setlocale(LC_NUMERIC, $currentLocale);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access BigInteger's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigInteger(string $value) : BigInteger
|
||||
{
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access BigDecimal's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
|
||||
{
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access BigRational's protected constructor from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
|
||||
{
|
||||
return new BigRational($numerator, $denominator, $checkDenominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-suppress LessSpecificReturnStatement
|
||||
* @psalm-suppress MoreSpecificReturnType
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function min(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$min = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($min === null || $value->isLessThan($min)) {
|
||||
$min = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($min === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-suppress LessSpecificReturnStatement
|
||||
* @psalm-suppress MoreSpecificReturnType
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function max(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$max = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($max === null || $value->isGreaterThan($max)) {
|
||||
$max = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($max === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
/** @var static|null $sum */
|
||||
$sum = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
$sum = $sum === null ? $value : self::add($sum, $value);
|
||||
}
|
||||
|
||||
if ($sum === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
|
||||
*
|
||||
* @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
|
||||
* concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
|
||||
* depending on their ability to perform the operation. This will also require a version bump because we're
|
||||
* potentially breaking custom BigNumber implementations (if any...)
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function add(BigNumber $a, BigNumber $b) : BigNumber
|
||||
{
|
||||
if ($a instanceof BigRational) {
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
if ($b instanceof BigRational) {
|
||||
return $b->plus($a);
|
||||
}
|
||||
|
||||
if ($a instanceof BigDecimal) {
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
if ($b instanceof BigDecimal) {
|
||||
return $b->plus($a);
|
||||
}
|
||||
|
||||
/** @var BigInteger $a */
|
||||
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes optional leading zeros and + sign from the given number.
|
||||
*
|
||||
* @param string $number The number, validated as a non-empty string of digits with optional leading sign.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function cleanUp(string $number) : string
|
||||
{
|
||||
$firstChar = $number[0];
|
||||
|
||||
if ($firstChar === '+' || $firstChar === '-') {
|
||||
$number = \substr($number, 1);
|
||||
}
|
||||
|
||||
$number = \ltrim($number, '0');
|
||||
|
||||
if ($number === '') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($firstChar === '-') {
|
||||
return '-' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is equal to the given one.
|
||||
*/
|
||||
public function isEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
*/
|
||||
public function isLessThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
*/
|
||||
public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*/
|
||||
public function isGreaterThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*/
|
||||
public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number equals zero.
|
||||
*/
|
||||
public function isZero() : bool
|
||||
{
|
||||
return $this->getSign() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly negative.
|
||||
*/
|
||||
public function isNegative() : bool
|
||||
{
|
||||
return $this->getSign() < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is negative or zero.
|
||||
*/
|
||||
public function isNegativeOrZero() : bool
|
||||
{
|
||||
return $this->getSign() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly positive.
|
||||
*/
|
||||
public function isPositive() : bool
|
||||
{
|
||||
return $this->getSign() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is positive or zero.
|
||||
*/
|
||||
public function isPositiveOrZero() : bool
|
||||
{
|
||||
return $this->getSign() >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sign of this number.
|
||||
*
|
||||
* @return int -1 if the number is negative, 0 if zero, 1 if positive.
|
||||
*/
|
||||
abstract public function getSign() : int;
|
||||
|
||||
/**
|
||||
* Compares this number to the given one.
|
||||
*
|
||||
* @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
abstract public function compareTo(BigNumber|int|float|string $that) : int;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigInteger.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
||||
*/
|
||||
abstract public function toBigInteger() : BigInteger;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
||||
*/
|
||||
abstract public function toBigDecimal() : BigDecimal;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigRational.
|
||||
*/
|
||||
abstract public function toBigRational() : BigRational;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
|
||||
*
|
||||
* @param int $scale The scale of the resulting `BigDecimal`.
|
||||
* @param int $roundingMode A `RoundingMode` constant.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
||||
* This only applies when RoundingMode::UNNECESSARY is used.
|
||||
*/
|
||||
abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
||||
|
||||
/**
|
||||
* Returns the exact value of this number as a native integer.
|
||||
*
|
||||
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
|
||||
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
|
||||
*
|
||||
* @throws MathException If this number cannot be exactly converted to a native integer.
|
||||
*/
|
||||
abstract public function toInt() : int;
|
||||
|
||||
/**
|
||||
* Returns an approximation of this number as a floating-point value.
|
||||
*
|
||||
* Note that this method can discard information as the precision of a floating-point value
|
||||
* is inherently limited.
|
||||
*
|
||||
* If the number is greater than the largest representable floating point number, positive infinity is returned.
|
||||
* If the number is less than the smallest representable floating point number, negative infinity is returned.
|
||||
*/
|
||||
abstract public function toFloat() : float;
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number.
|
||||
*
|
||||
* The output of this method can be parsed by the `of()` factory method;
|
||||
* this will yield an object equal to this one, without any information loss.
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
445
vendor/brick/math/src/BigRational.php
vendored
Normal file
445
vendor/brick/math/src/BigRational.php
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
|
||||
/**
|
||||
* An arbitrarily large rational number.
|
||||
*
|
||||
* This class is immutable.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class BigRational extends BigNumber
|
||||
{
|
||||
/**
|
||||
* The numerator.
|
||||
*/
|
||||
private BigInteger $numerator;
|
||||
|
||||
/**
|
||||
* The denominator. Always strictly positive.
|
||||
*/
|
||||
private BigInteger $denominator;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
*
|
||||
* @param BigInteger $numerator The numerator.
|
||||
* @param BigInteger $denominator The denominator.
|
||||
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
|
||||
*
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*/
|
||||
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
|
||||
{
|
||||
if ($checkDenominator) {
|
||||
if ($denominator->isZero()) {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
}
|
||||
|
||||
if ($denominator->isNegative()) {
|
||||
$numerator = $numerator->negated();
|
||||
$denominator = $denominator->negated();
|
||||
}
|
||||
}
|
||||
|
||||
$this->numerator = $numerator;
|
||||
$this->denominator = $denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational of the given value.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigRational.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigRational
|
||||
{
|
||||
return parent::of($value)->toBigRational();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational out of a numerator and a denominator.
|
||||
*
|
||||
* If the denominator is negative, the signs of both the numerator and the denominator
|
||||
* will be inverted to ensure that the denominator is always positive.
|
||||
*
|
||||
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws NumberFormatException If an argument does not represent a valid number.
|
||||
* @throws RoundingNecessaryException If an argument represents a non-integer number.
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function nd(
|
||||
BigNumber|int|float|string $numerator,
|
||||
BigNumber|int|float|string $denominator,
|
||||
) : BigRational {
|
||||
$numerator = BigInteger::of($numerator);
|
||||
$denominator = BigInteger::of($denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigRational
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigRational|null $zero
|
||||
*/
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing one.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigRational
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigRational|null $one
|
||||
*/
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigRational(BigInteger::one(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing ten.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigRational
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress ImpureStaticVariable
|
||||
* @var BigRational|null $ten
|
||||
*/
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
public function getNumerator() : BigInteger
|
||||
{
|
||||
return $this->numerator;
|
||||
}
|
||||
|
||||
public function getDenominator() : BigInteger
|
||||
{
|
||||
return $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of the numerator by the denominator.
|
||||
*/
|
||||
public function quotient() : BigInteger
|
||||
{
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of the numerator by the denominator.
|
||||
*/
|
||||
public function remainder() : BigInteger
|
||||
{
|
||||
return $this->numerator->remainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger[]
|
||||
*/
|
||||
public function quotientAndRemainder() : array
|
||||
{
|
||||
return $this->numerator->quotientAndRemainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to add.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function plus(BigNumber|int|float|string $that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator));
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to subtract.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function minus(BigNumber|int|float|string $that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator));
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number.
|
||||
*/
|
||||
public function multipliedBy(BigNumber|int|float|string $that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->numerator);
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$denominator = $this->denominator->multipliedBy($that->numerator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||
*/
|
||||
public function power(int $exponent) : BigRational
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
$one = BigInteger::one();
|
||||
|
||||
return new BigRational($one, $one, false);
|
||||
}
|
||||
|
||||
if ($exponent === 1) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new BigRational(
|
||||
$this->numerator->power($exponent),
|
||||
$this->denominator->power($exponent),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reciprocal of this BigRational.
|
||||
*
|
||||
* The reciprocal has the numerator and denominator swapped.
|
||||
*
|
||||
* @throws DivisionByZeroException If the numerator is zero.
|
||||
*/
|
||||
public function reciprocal() : BigRational
|
||||
{
|
||||
return new BigRational($this->denominator, $this->numerator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this BigRational.
|
||||
*/
|
||||
public function abs() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->abs(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this BigRational.
|
||||
*/
|
||||
public function negated() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->negated(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simplified value of this BigRational.
|
||||
*/
|
||||
public function simplified() : BigRational
|
||||
{
|
||||
$gcd = $this->numerator->gcd($this->denominator);
|
||||
|
||||
$numerator = $this->numerator->quotient($gcd);
|
||||
$denominator = $this->denominator->quotient($gcd);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
public function compareTo(BigNumber|int|float|string $that) : int
|
||||
{
|
||||
return $this->minus($that)->getSign();
|
||||
}
|
||||
|
||||
public function getSign() : int
|
||||
{
|
||||
return $this->numerator->getSign();
|
||||
}
|
||||
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
$simplified = $this->simplified();
|
||||
|
||||
if (! $simplified->denominator->isEqualTo(1)) {
|
||||
throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
|
||||
}
|
||||
|
||||
return $simplified->numerator;
|
||||
}
|
||||
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||
}
|
||||
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
public function toFloat() : float
|
||||
{
|
||||
$simplified = $this->simplified();
|
||||
return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
|
||||
}
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
$numerator = (string) $this->numerator;
|
||||
$denominator = (string) $this->denominator;
|
||||
|
||||
if ($denominator === '1') {
|
||||
return $numerator;
|
||||
}
|
||||
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required for serializing the object and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return array{numerator: BigInteger, denominator: BigInteger}
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return ['numerator' => $this->numerator, 'denominator' => $this->denominator];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @param array{numerator: BigInteger, denominator: BigInteger} $data
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
if (isset($this->numerator)) {
|
||||
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
$this->numerator = $data['numerator'];
|
||||
$this->denominator = $data['denominator'];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->numerator)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$numerator, $denominator] = \explode('/', $value);
|
||||
|
||||
$this->numerator = BigInteger::of($numerator);
|
||||
$this->denominator = BigInteger::of($denominator);
|
||||
}
|
||||
}
|
35
vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
35
vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a division by zero occurs.
|
||||
*/
|
||||
class DivisionByZeroException extends MathException
|
||||
{
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function divisionByZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('Division by zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function modulusMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The modulus must not be zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The denominator of a rational number cannot be zero.');
|
||||
}
|
||||
}
|
23
vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
23
vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Exception thrown when an integer overflow occurs.
|
||||
*/
|
||||
class IntegerOverflowException extends MathException
|
||||
{
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
|
||||
{
|
||||
$message = '%s is out of range %d to %d and cannot be represented as an integer.';
|
||||
|
||||
return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX));
|
||||
}
|
||||
}
|
12
vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
12
vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Base class for all math exceptions.
|
||||
*/
|
||||
class MathException extends \Exception
|
||||
{
|
||||
}
|
12
vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
12
vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
|
||||
*/
|
||||
class NegativeNumberException extends MathException
|
||||
{
|
||||
}
|
33
vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
33
vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to create a number from a string with an invalid format.
|
||||
*/
|
||||
class NumberFormatException extends MathException
|
||||
{
|
||||
/**
|
||||
* @param string $char The failing character.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function charNotInAlphabet(string $char) : self
|
||||
{
|
||||
$ord = \ord($char);
|
||||
|
||||
if ($ord < 32 || $ord > 126) {
|
||||
$char = \strtoupper(\dechex($ord));
|
||||
|
||||
if ($ord < 10) {
|
||||
$char = '0' . $char;
|
||||
}
|
||||
} else {
|
||||
$char = '"' . $char . '"';
|
||||
}
|
||||
|
||||
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||
}
|
||||
}
|
19
vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
19
vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a number cannot be represented at the requested scale without rounding.
|
||||
*/
|
||||
class RoundingNecessaryException extends MathException
|
||||
{
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function roundingNecessary() : RoundingNecessaryException
|
||||
{
|
||||
return new self('Rounding is necessary to represent the result of the operation at this scale.');
|
||||
}
|
||||
}
|
676
vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
676
vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
@ -0,0 +1,676 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal;
|
||||
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
use Brick\Math\RoundingMode;
|
||||
|
||||
/**
|
||||
* Performs basic operations on arbitrary size integers.
|
||||
*
|
||||
* Unless otherwise specified, all parameters must be validated as non-empty strings of digits,
|
||||
* without leading zero, and with an optional leading minus sign if the number is not zero.
|
||||
*
|
||||
* Any other parameter format will lead to undefined behaviour.
|
||||
* All methods must return strings respecting this format, unless specified otherwise.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
abstract class Calculator
|
||||
{
|
||||
/**
|
||||
* The maximum exponent value allowed for the pow() method.
|
||||
*/
|
||||
public const MAX_POWER = 1000000;
|
||||
|
||||
/**
|
||||
* The alphabet for converting from and to base 2 to 36, lowercase.
|
||||
*/
|
||||
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
/**
|
||||
* The Calculator instance in use.
|
||||
*/
|
||||
private static ?Calculator $instance = null;
|
||||
|
||||
/**
|
||||
* Sets the Calculator instance to use.
|
||||
*
|
||||
* An instance is typically set only in unit tests: the autodetect is usually the best option.
|
||||
*
|
||||
* @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
|
||||
*/
|
||||
final public static function set(?Calculator $calculator) : void
|
||||
{
|
||||
self::$instance = $calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Calculator instance to use.
|
||||
*
|
||||
* If none has been explicitly set, the fastest available implementation will be returned.
|
||||
*
|
||||
* @psalm-pure
|
||||
* @psalm-suppress ImpureStaticProperty
|
||||
*/
|
||||
final public static function get() : Calculator
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
/** @psalm-suppress ImpureMethodCall */
|
||||
self::$instance = self::detect();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fastest available Calculator implementation.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private static function detect() : Calculator
|
||||
{
|
||||
if (\extension_loaded('gmp')) {
|
||||
return new Calculator\GmpCalculator();
|
||||
}
|
||||
|
||||
if (\extension_loaded('bcmath')) {
|
||||
return new Calculator\BcMathCalculator();
|
||||
}
|
||||
|
||||
return new Calculator\NativeCalculator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the sign & digits of the operands.
|
||||
*
|
||||
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
|
||||
*/
|
||||
final protected function init(string $a, string $b) : array
|
||||
{
|
||||
return [
|
||||
$aNeg = ($a[0] === '-'),
|
||||
$bNeg = ($b[0] === '-'),
|
||||
|
||||
$aNeg ? \substr($a, 1) : $a,
|
||||
$bNeg ? \substr($b, 1) : $b,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of a number.
|
||||
*/
|
||||
final public function abs(string $n) : string
|
||||
{
|
||||
return ($n[0] === '-') ? \substr($n, 1) : $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates a number.
|
||||
*/
|
||||
final public function neg(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($n[0] === '-') {
|
||||
return \substr($n, 1);
|
||||
}
|
||||
|
||||
return '-' . $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
|
||||
*/
|
||||
final public function cmp(string $a, string $b) : int
|
||||
{
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
if ($aNeg && ! $bNeg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ($bNeg && ! $aNeg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$aLen = \strlen($aDig);
|
||||
$bLen = \strlen($bDig);
|
||||
|
||||
if ($aLen < $bLen) {
|
||||
$result = -1;
|
||||
} elseif ($aLen > $bLen) {
|
||||
$result = 1;
|
||||
} else {
|
||||
$result = $aDig <=> $bDig;
|
||||
}
|
||||
|
||||
return $aNeg ? -$result : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two numbers.
|
||||
*/
|
||||
abstract public function add(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Subtracts two numbers.
|
||||
*/
|
||||
abstract public function sub(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Multiplies two numbers.
|
||||
*/
|
||||
abstract public function mul(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return string The quotient.
|
||||
*/
|
||||
abstract public function divQ(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return string The remainder.
|
||||
*/
|
||||
abstract public function divR(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return array{string, string} An array containing the quotient and remainder.
|
||||
*/
|
||||
abstract public function divQR(string $a, string $b) : array;
|
||||
|
||||
/**
|
||||
* Exponentiates a number.
|
||||
*
|
||||
* @param string $a The base number.
|
||||
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
|
||||
*
|
||||
* @return string The power.
|
||||
*/
|
||||
abstract public function pow(string $a, int $e) : string;
|
||||
|
||||
/**
|
||||
* @param string $b The modulus; must not be zero.
|
||||
*/
|
||||
public function mod(string $a, string $b) : string
|
||||
{
|
||||
return $this->divR($this->add($this->divR($a, $b), $b), $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modular multiplicative inverse of $x modulo $m.
|
||||
*
|
||||
* If $x has no multiplicative inverse mod m, this method must return null.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
|
||||
*
|
||||
* @param string $m The modulus; must not be negative or zero.
|
||||
*/
|
||||
public function modInverse(string $x, string $m) : ?string
|
||||
{
|
||||
if ($m === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$modVal = $x;
|
||||
|
||||
if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) {
|
||||
$modVal = $this->mod($x, $m);
|
||||
}
|
||||
|
||||
[$g, $x] = $this->gcdExtended($modVal, $m);
|
||||
|
||||
if ($g !== '1') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->mod($this->add($this->mod($x, $m), $m), $m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a number into power with modulo.
|
||||
*
|
||||
* @param string $base The base number; must be positive or zero.
|
||||
* @param string $exp The exponent; must be positive or zero.
|
||||
* @param string $mod The modulus; must be strictly positive.
|
||||
*/
|
||||
abstract public function modPow(string $base, string $exp, string $mod) : string;
|
||||
|
||||
/**
|
||||
* Returns the greatest common divisor of the two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for GCD calculations.
|
||||
*
|
||||
* @return string The GCD, always positive, or zero if both arguments are zero.
|
||||
*/
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
if ($a === '0') {
|
||||
return $this->abs($b);
|
||||
}
|
||||
|
||||
if ($b === '0') {
|
||||
return $this->abs($a);
|
||||
}
|
||||
|
||||
return $this->gcd($b, $this->divR($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, string, string} GCD, X, Y
|
||||
*/
|
||||
private function gcdExtended(string $a, string $b) : array
|
||||
{
|
||||
if ($a === '0') {
|
||||
return [$b, '0', '1'];
|
||||
}
|
||||
|
||||
[$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
|
||||
|
||||
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
|
||||
$y = $x1;
|
||||
|
||||
return [$gcd, $x, $y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the given number, rounded down.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
* The input MUST NOT be negative.
|
||||
*/
|
||||
abstract public function sqrt(string $n) : string;
|
||||
|
||||
/**
|
||||
* Converts a number from an arbitrary base.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for base conversion.
|
||||
*
|
||||
* @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base.
|
||||
* @param int $base The base of the number, validated from 2 to 36.
|
||||
*
|
||||
* @return string The converted number, following the Calculator conventions.
|
||||
*/
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number to an arbitrary base.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for base conversion.
|
||||
*
|
||||
* @param string $number The number to convert, following the Calculator conventions.
|
||||
* @param int $base The base to convert to, validated from 2 to 36.
|
||||
*
|
||||
* @return string The converted number, lowercase.
|
||||
*/
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
$negative = ($number[0] === '-');
|
||||
|
||||
if ($negative) {
|
||||
$number = \substr($number, 1);
|
||||
}
|
||||
|
||||
$number = $this->toArbitraryBase($number, self::ALPHABET, $base);
|
||||
|
||||
if ($negative) {
|
||||
return '-' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10.
|
||||
*
|
||||
* @param string $number The number to convert, validated as a non-empty string,
|
||||
* containing only chars in the given alphabet/base.
|
||||
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
|
||||
* @param int $base The base of the number, validated from 2 to alphabet length.
|
||||
*
|
||||
* @return string The number in base 10, following the Calculator conventions.
|
||||
*/
|
||||
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||
{
|
||||
// remove leading "zeros"
|
||||
$number = \ltrim($number, $alphabet[0]);
|
||||
|
||||
if ($number === '') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// optimize for "one"
|
||||
if ($number === $alphabet[1]) {
|
||||
return '1';
|
||||
}
|
||||
|
||||
$result = '0';
|
||||
$power = '1';
|
||||
|
||||
$base = (string) $base;
|
||||
|
||||
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
|
||||
$index = \strpos($alphabet, $number[$i]);
|
||||
|
||||
if ($index !== 0) {
|
||||
$result = $this->add($result, ($index === 1)
|
||||
? $power
|
||||
: $this->mul($power, (string) $index)
|
||||
);
|
||||
}
|
||||
|
||||
if ($i !== 0) {
|
||||
$power = $this->mul($power, $base);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a non-negative number to an arbitrary base using a custom alphabet.
|
||||
*
|
||||
* @param string $number The number to convert, positive or zero, following the Calculator conventions.
|
||||
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
|
||||
* @param int $base The base to convert to, validated from 2 to alphabet length.
|
||||
*
|
||||
* @return string The converted number in the given alphabet.
|
||||
*/
|
||||
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||
{
|
||||
if ($number === '0') {
|
||||
return $alphabet[0];
|
||||
}
|
||||
|
||||
$base = (string) $base;
|
||||
$result = '';
|
||||
|
||||
while ($number !== '0') {
|
||||
[$number, $remainder] = $this->divQR($number, $base);
|
||||
$remainder = (int) $remainder;
|
||||
|
||||
$result .= $alphabet[$remainder];
|
||||
}
|
||||
|
||||
return \strrev($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a rounded division.
|
||||
*
|
||||
* Rounding is performed when the remainder of the division is not zero.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
* @param int $roundingMode The rounding mode.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
*
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
final public function divRound(string $a, string $b, int $roundingMode) : string
|
||||
{
|
||||
[$quotient, $remainder] = $this->divQR($a, $b);
|
||||
|
||||
$hasDiscardedFraction = ($remainder !== '0');
|
||||
$isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');
|
||||
|
||||
$discardedFractionSign = function() use ($remainder, $b) : int {
|
||||
$r = $this->abs($this->mul($remainder, '2'));
|
||||
$b = $this->abs($b);
|
||||
|
||||
return $this->cmp($r, $b);
|
||||
};
|
||||
|
||||
$increment = false;
|
||||
|
||||
switch ($roundingMode) {
|
||||
case RoundingMode::UNNECESSARY:
|
||||
if ($hasDiscardedFraction) {
|
||||
throw RoundingNecessaryException::roundingNecessary();
|
||||
}
|
||||
break;
|
||||
|
||||
case RoundingMode::UP:
|
||||
$increment = $hasDiscardedFraction;
|
||||
break;
|
||||
|
||||
case RoundingMode::DOWN:
|
||||
break;
|
||||
|
||||
case RoundingMode::CEILING:
|
||||
$increment = $hasDiscardedFraction && $isPositiveOrZero;
|
||||
break;
|
||||
|
||||
case RoundingMode::FLOOR:
|
||||
$increment = $hasDiscardedFraction && ! $isPositiveOrZero;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_UP:
|
||||
$increment = $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_DOWN:
|
||||
$increment = $discardedFractionSign() > 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_CEILING:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_FLOOR:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_EVEN:
|
||||
$lastDigit = (int) $quotient[-1];
|
||||
$lastDigitIsEven = ($lastDigit % 2 === 0);
|
||||
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid rounding mode.');
|
||||
}
|
||||
|
||||
if ($increment) {
|
||||
return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
|
||||
}
|
||||
|
||||
return $quotient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise AND of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*/
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('and', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise OR of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*/
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('or', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise XOR of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('xor', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a bitwise operation on a decimal number.
|
||||
*
|
||||
* @param 'and'|'or'|'xor' $operator The operator to use.
|
||||
* @param string $a The left operand.
|
||||
* @param string $b The right operand.
|
||||
*/
|
||||
private function bitwise(string $operator, string $a, string $b) : string
|
||||
{
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
$aBin = $this->toBinary($aDig);
|
||||
$bBin = $this->toBinary($bDig);
|
||||
|
||||
$aLen = \strlen($aBin);
|
||||
$bLen = \strlen($bBin);
|
||||
|
||||
if ($aLen > $bLen) {
|
||||
$bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin;
|
||||
} elseif ($bLen > $aLen) {
|
||||
$aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin;
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$aBin = $this->twosComplement($aBin);
|
||||
}
|
||||
if ($bNeg) {
|
||||
$bBin = $this->twosComplement($bBin);
|
||||
}
|
||||
|
||||
switch ($operator) {
|
||||
case 'and':
|
||||
$value = $aBin & $bBin;
|
||||
$negative = ($aNeg and $bNeg);
|
||||
break;
|
||||
|
||||
case 'or':
|
||||
$value = $aBin | $bBin;
|
||||
$negative = ($aNeg or $bNeg);
|
||||
break;
|
||||
|
||||
case 'xor':
|
||||
$value = $aBin ^ $bBin;
|
||||
$negative = ($aNeg xor $bNeg);
|
||||
break;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid bitwise operator.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if ($negative) {
|
||||
$value = $this->twosComplement($value);
|
||||
}
|
||||
|
||||
$result = $this->toDecimal($value);
|
||||
|
||||
return $negative ? $this->neg($result) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number A positive, binary number.
|
||||
*/
|
||||
private function twosComplement(string $number) : string
|
||||
{
|
||||
$xor = \str_repeat("\xff", \strlen($number));
|
||||
|
||||
$number ^= $xor;
|
||||
|
||||
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
|
||||
$byte = \ord($number[$i]);
|
||||
|
||||
if (++$byte !== 256) {
|
||||
$number[$i] = \chr($byte);
|
||||
break;
|
||||
}
|
||||
|
||||
$number[$i] = "\x00";
|
||||
|
||||
if ($i === 0) {
|
||||
$number = "\x01" . $number;
|
||||
}
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a decimal number to a binary string.
|
||||
*
|
||||
* @param string $number The number to convert, positive or zero, only digits.
|
||||
*/
|
||||
private function toBinary(string $number) : string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
while ($number !== '0') {
|
||||
[$number, $remainder] = $this->divQR($number, '256');
|
||||
$result .= \chr((int) $remainder);
|
||||
}
|
||||
|
||||
return \strrev($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the positive decimal representation of a binary number.
|
||||
*
|
||||
* @param string $bytes The bytes representing the number.
|
||||
*/
|
||||
private function toDecimal(string $bytes) : string
|
||||
{
|
||||
$result = '0';
|
||||
$power = '1';
|
||||
|
||||
for ($i = \strlen($bytes) - 1; $i >= 0; $i--) {
|
||||
$index = \ord($bytes[$i]);
|
||||
|
||||
if ($index !== 0) {
|
||||
$result = $this->add($result, ($index === 1)
|
||||
? $power
|
||||
: $this->mul($power, (string) $index)
|
||||
);
|
||||
}
|
||||
|
||||
if ($i !== 0) {
|
||||
$power = $this->mul($power, '256');
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
75
vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
75
vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation built around the bcmath library.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class BcMathCalculator extends Calculator
|
||||
{
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \bcadd($a, $b, 0);
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \bcsub($a, $b, 0);
|
||||
}
|
||||
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \bcmul($a, $b, 0);
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b, 0);
|
||||
}
|
||||
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b, 0);
|
||||
|
||||
assert($r !== null);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \bcpow($a, (string) $e, 0);
|
||||
}
|
||||
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
}
|
||||
}
|
108
vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
108
vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation built around the GMP library.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class GmpCalculator extends Calculator
|
||||
{
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_add($a, $b));
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sub($a, $b));
|
||||
}
|
||||
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_mul($a, $b));
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_q($a, $b));
|
||||
}
|
||||
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_r($a, $b));
|
||||
}
|
||||
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
[$q, $r] = \gmp_div_qr($a, $b);
|
||||
|
||||
return [
|
||||
\gmp_strval($q),
|
||||
\gmp_strval($r)
|
||||
];
|
||||
}
|
||||
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_pow($a, $e));
|
||||
}
|
||||
|
||||
public function modInverse(string $x, string $m) : ?string
|
||||
{
|
||||
$result = \gmp_invert($x, $m);
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \gmp_strval($result);
|
||||
}
|
||||
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
||||
}
|
||||
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_gcd($a, $b));
|
||||
}
|
||||
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_init($number, $base));
|
||||
}
|
||||
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval($number, $base);
|
||||
}
|
||||
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_and($a, $b));
|
||||
}
|
||||
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_or($a, $b));
|
||||
}
|
||||
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_xor($a, $b));
|
||||
}
|
||||
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sqrt($n));
|
||||
}
|
||||
}
|
581
vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
581
vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation using only native PHP code.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class NativeCalculator extends Calculator
|
||||
{
|
||||
/**
|
||||
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
|
||||
* For multiplication, this represents the max sum of the lengths of both operands.
|
||||
*
|
||||
* In addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
|
||||
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
|
||||
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
|
||||
*/
|
||||
private int $maxDigits;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
switch (PHP_INT_SIZE) {
|
||||
case 4:
|
||||
$this->maxDigits = 9;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$this->maxDigits = 18;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
|
||||
}
|
||||
}
|
||||
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
/**
|
||||
* @psalm-var numeric-string $a
|
||||
* @psalm-var numeric-string $b
|
||||
*/
|
||||
$result = $a + $b;
|
||||
|
||||
if (is_int($result)) {
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
if ($a === '0') {
|
||||
return $b;
|
||||
}
|
||||
|
||||
if ($b === '0') {
|
||||
return $a;
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
$result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig);
|
||||
|
||||
if ($aNeg) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return $this->add($a, $this->neg($b));
|
||||
}
|
||||
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
/**
|
||||
* @psalm-var numeric-string $a
|
||||
* @psalm-var numeric-string $b
|
||||
*/
|
||||
$result = $a * $b;
|
||||
|
||||
if (is_int($result)) {
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
if ($a === '0' || $b === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($a === '1') {
|
||||
return $b;
|
||||
}
|
||||
|
||||
if ($b === '1') {
|
||||
return $a;
|
||||
}
|
||||
|
||||
if ($a === '-1') {
|
||||
return $this->neg($b);
|
||||
}
|
||||
|
||||
if ($b === '-1') {
|
||||
return $this->neg($a);
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
$result = $this->doMul($aDig, $bDig);
|
||||
|
||||
if ($aNeg !== $bNeg) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return $this->divQR($a, $b)[0];
|
||||
}
|
||||
|
||||
public function divR(string $a, string $b): string
|
||||
{
|
||||
return $this->divQR($a, $b)[1];
|
||||
}
|
||||
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
if ($a === '0') {
|
||||
return ['0', '0'];
|
||||
}
|
||||
|
||||
if ($a === $b) {
|
||||
return ['1', '0'];
|
||||
}
|
||||
|
||||
if ($b === '1') {
|
||||
return [$a, '0'];
|
||||
}
|
||||
|
||||
if ($b === '-1') {
|
||||
return [$this->neg($a), '0'];
|
||||
}
|
||||
|
||||
/** @psalm-var numeric-string $a */
|
||||
$na = $a * 1; // cast to number
|
||||
|
||||
if (is_int($na)) {
|
||||
/** @psalm-var numeric-string $b */
|
||||
$nb = $b * 1;
|
||||
|
||||
if (is_int($nb)) {
|
||||
// the only division that may overflow is PHP_INT_MIN / -1,
|
||||
// which cannot happen here as we've already handled a divisor of -1 above.
|
||||
$r = $na % $nb;
|
||||
$q = ($na - $r) / $nb;
|
||||
|
||||
assert(is_int($q));
|
||||
|
||||
return [
|
||||
(string) $q,
|
||||
(string) $r
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
[$q, $r] = $this->doDiv($aDig, $bDig);
|
||||
|
||||
if ($aNeg !== $bNeg) {
|
||||
$q = $this->neg($q);
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$r = $this->neg($r);
|
||||
}
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
if ($e === 0) {
|
||||
return '1';
|
||||
}
|
||||
|
||||
if ($e === 1) {
|
||||
return $a;
|
||||
}
|
||||
|
||||
$odd = $e % 2;
|
||||
$e -= $odd;
|
||||
|
||||
$aa = $this->mul($a, $a);
|
||||
|
||||
/** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
|
||||
$result = $this->pow($aa, $e / 2);
|
||||
|
||||
if ($odd === 1) {
|
||||
$result = $this->mul($result, $a);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
|
||||
*/
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($base === '0' && $exp === '0' && $mod === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($exp === '0' && $mod === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$x = $base;
|
||||
|
||||
$res = '1';
|
||||
|
||||
// numbers are positive, so we can use remainder instead of modulo
|
||||
$x = $this->divR($x, $mod);
|
||||
|
||||
while ($exp !== '0') {
|
||||
if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd
|
||||
$res = $this->divR($this->mul($res, $x), $mod);
|
||||
}
|
||||
|
||||
$exp = $this->divQ($exp, '2');
|
||||
$x = $this->divR($this->mul($x, $x), $mod);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// initial approximation
|
||||
$x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1);
|
||||
|
||||
$decreased = false;
|
||||
|
||||
for (;;) {
|
||||
$nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2');
|
||||
|
||||
if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) {
|
||||
break;
|
||||
}
|
||||
|
||||
$decreased = $this->cmp($nx, $x) < 0;
|
||||
$x = $nx;
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the addition of two non-signed large integers.
|
||||
*/
|
||||
private function doAdd(string $a, string $b) : string
|
||||
{
|
||||
[$a, $b, $length] = $this->pad($a, $b);
|
||||
|
||||
$carry = 0;
|
||||
$result = '';
|
||||
|
||||
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
|
||||
$blockLength = $this->maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockLength += $i;
|
||||
/** @psalm-suppress LoopInvalidation */
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
/** @psalm-var numeric-string $blockA */
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
|
||||
/** @psalm-var numeric-string $blockB */
|
||||
$blockB = \substr($b, $i, $blockLength);
|
||||
|
||||
$sum = (string) ($blockA + $blockB + $carry);
|
||||
$sumLength = \strlen($sum);
|
||||
|
||||
if ($sumLength > $blockLength) {
|
||||
$sum = \substr($sum, 1);
|
||||
$carry = 1;
|
||||
} else {
|
||||
if ($sumLength < $blockLength) {
|
||||
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
|
||||
}
|
||||
$carry = 0;
|
||||
}
|
||||
|
||||
$result = $sum . $result;
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($carry === 1) {
|
||||
$result = '1' . $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the subtraction of two non-signed large integers.
|
||||
*/
|
||||
private function doSub(string $a, string $b) : string
|
||||
{
|
||||
if ($a === $b) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// Ensure that we always subtract to a positive result: biggest minus smallest.
|
||||
$cmp = $this->doCmp($a, $b);
|
||||
|
||||
$invert = ($cmp === -1);
|
||||
|
||||
if ($invert) {
|
||||
$c = $a;
|
||||
$a = $b;
|
||||
$b = $c;
|
||||
}
|
||||
|
||||
[$a, $b, $length] = $this->pad($a, $b);
|
||||
|
||||
$carry = 0;
|
||||
$result = '';
|
||||
|
||||
$complement = 10 ** $this->maxDigits;
|
||||
|
||||
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
|
||||
$blockLength = $this->maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockLength += $i;
|
||||
/** @psalm-suppress LoopInvalidation */
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
/** @psalm-var numeric-string $blockA */
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
|
||||
/** @psalm-var numeric-string $blockB */
|
||||
$blockB = \substr($b, $i, $blockLength);
|
||||
|
||||
$sum = $blockA - $blockB - $carry;
|
||||
|
||||
if ($sum < 0) {
|
||||
$sum += $complement;
|
||||
$carry = 1;
|
||||
} else {
|
||||
$carry = 0;
|
||||
}
|
||||
|
||||
$sum = (string) $sum;
|
||||
$sumLength = \strlen($sum);
|
||||
|
||||
if ($sumLength < $blockLength) {
|
||||
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
|
||||
}
|
||||
|
||||
$result = $sum . $result;
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Carry cannot be 1 when the loop ends, as a > b
|
||||
assert($carry === 0);
|
||||
|
||||
$result = \ltrim($result, '0');
|
||||
|
||||
if ($invert) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the multiplication of two non-signed large integers.
|
||||
*/
|
||||
private function doMul(string $a, string $b) : string
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
$maxDigits = \intdiv($this->maxDigits, 2);
|
||||
$complement = 10 ** $maxDigits;
|
||||
|
||||
$result = '0';
|
||||
|
||||
for ($i = $x - $maxDigits;; $i -= $maxDigits) {
|
||||
$blockALength = $maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockALength += $i;
|
||||
/** @psalm-suppress LoopInvalidation */
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = (int) \substr($a, $i, $blockALength);
|
||||
|
||||
$line = '';
|
||||
$carry = 0;
|
||||
|
||||
for ($j = $y - $maxDigits;; $j -= $maxDigits) {
|
||||
$blockBLength = $maxDigits;
|
||||
|
||||
if ($j < 0) {
|
||||
$blockBLength += $j;
|
||||
/** @psalm-suppress LoopInvalidation */
|
||||
$j = 0;
|
||||
}
|
||||
|
||||
$blockB = (int) \substr($b, $j, $blockBLength);
|
||||
|
||||
$mul = $blockA * $blockB + $carry;
|
||||
$value = $mul % $complement;
|
||||
$carry = ($mul - $value) / $complement;
|
||||
|
||||
$value = (string) $value;
|
||||
$value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT);
|
||||
|
||||
$line = $value . $line;
|
||||
|
||||
if ($j === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($carry !== 0) {
|
||||
$line = $carry . $line;
|
||||
}
|
||||
|
||||
$line = \ltrim($line, '0');
|
||||
|
||||
if ($line !== '') {
|
||||
$line .= \str_repeat('0', $x - $blockALength - $i);
|
||||
$result = $this->add($result, $line);
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the division of two non-signed large integers.
|
||||
*
|
||||
* @return string[] The quotient and remainder.
|
||||
*/
|
||||
private function doDiv(string $a, string $b) : array
|
||||
{
|
||||
$cmp = $this->doCmp($a, $b);
|
||||
|
||||
if ($cmp === -1) {
|
||||
return ['0', $a];
|
||||
}
|
||||
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
// we now know that a >= b && x >= y
|
||||
|
||||
$q = '0'; // quotient
|
||||
$r = $a; // remainder
|
||||
$z = $y; // focus length, always $y or $y+1
|
||||
|
||||
for (;;) {
|
||||
$focus = \substr($a, 0, $z);
|
||||
|
||||
$cmp = $this->doCmp($focus, $b);
|
||||
|
||||
if ($cmp === -1) {
|
||||
if ($z === $x) { // remainder < dividend
|
||||
break;
|
||||
}
|
||||
|
||||
$z++;
|
||||
}
|
||||
|
||||
$zeros = \str_repeat('0', $x - $z);
|
||||
|
||||
$q = $this->add($q, '1' . $zeros);
|
||||
$a = $this->sub($a, $b . $zeros);
|
||||
|
||||
$r = $a;
|
||||
|
||||
if ($r === '0') { // remainder == 0
|
||||
break;
|
||||
}
|
||||
|
||||
$x = \strlen($a);
|
||||
|
||||
if ($x < $y) { // remainder < dividend
|
||||
break;
|
||||
}
|
||||
|
||||
$z = $y;
|
||||
}
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two non-signed large numbers.
|
||||
*
|
||||
* @return int [-1, 0, 1]
|
||||
*/
|
||||
private function doCmp(string $a, string $b) : int
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
$cmp = $x <=> $y;
|
||||
|
||||
if ($cmp !== 0) {
|
||||
return $cmp;
|
||||
}
|
||||
|
||||
return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length.
|
||||
*
|
||||
* The numbers must only consist of digits, without leading minus sign.
|
||||
*
|
||||
* @return array{string, string, int}
|
||||
*/
|
||||
private function pad(string $a, string $b) : array
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
if ($x > $y) {
|
||||
$b = \str_repeat('0', $x - $y) . $b;
|
||||
|
||||
return [$a, $b, $x];
|
||||
}
|
||||
|
||||
if ($x < $y) {
|
||||
$a = \str_repeat('0', $y - $x) . $a;
|
||||
|
||||
return [$a, $b, $y];
|
||||
}
|
||||
|
||||
return [$a, $b, $x];
|
||||
}
|
||||
}
|
107
vendor/brick/math/src/RoundingMode.php
vendored
Normal file
107
vendor/brick/math/src/RoundingMode.php
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
/**
|
||||
* Specifies a rounding behavior for numerical operations capable of discarding precision.
|
||||
*
|
||||
* Each rounding mode indicates how the least significant returned digit of a rounded result
|
||||
* is to be calculated. If fewer digits are returned than the digits needed to represent the
|
||||
* exact numerical result, the discarded digits will be referred to as the discarded fraction
|
||||
* regardless the digits' contribution to the value of the number. In other words, considered
|
||||
* as a numerical value, the discarded fraction could have an absolute value greater than one.
|
||||
*/
|
||||
final class RoundingMode
|
||||
{
|
||||
/**
|
||||
* Private constructor. This class is not instantiable.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the requested operation has an exact result, hence no rounding is necessary.
|
||||
*
|
||||
* If this rounding mode is specified on an operation that yields a result that
|
||||
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
|
||||
*/
|
||||
public const UNNECESSARY = 0;
|
||||
|
||||
/**
|
||||
* Rounds away from zero.
|
||||
*
|
||||
* Always increments the digit prior to a nonzero discarded fraction.
|
||||
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
||||
*/
|
||||
public const UP = 1;
|
||||
|
||||
/**
|
||||
* Rounds towards zero.
|
||||
*
|
||||
* Never increments the digit prior to a discarded fraction (i.e., truncates).
|
||||
* Note that this rounding mode never increases the magnitude of the calculated value.
|
||||
*/
|
||||
public const DOWN = 2;
|
||||
|
||||
/**
|
||||
* Rounds towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
|
||||
* Note that this rounding mode never decreases the calculated value.
|
||||
*/
|
||||
public const CEILING = 3;
|
||||
|
||||
/**
|
||||
* Rounds towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
|
||||
* Note that this rounding mode never increases the calculated value.
|
||||
*/
|
||||
public const FLOOR = 4;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
|
||||
* Note that this is the rounding mode commonly taught at school.
|
||||
*/
|
||||
public const HALF_UP = 5;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
|
||||
*/
|
||||
public const HALF_DOWN = 6;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
|
||||
*/
|
||||
public const HALF_CEILING = 7;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
|
||||
*/
|
||||
public const HALF_FLOOR = 8;
|
||||
|
||||
/**
|
||||
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
||||
*
|
||||
* Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
|
||||
* behaves as for HALF_DOWN if it's even.
|
||||
*
|
||||
* Note that this is the rounding mode that statistically minimizes
|
||||
* cumulative error when applied repeatedly over a sequence of calculations.
|
||||
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
|
||||
*/
|
||||
public const HALF_EVEN = 9;
|
||||
}
|
269
vendor/cakephp/core/App.php
vendored
Normal file
269
vendor/cakephp/core/App.php
vendored
Normal file
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 1.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
/**
|
||||
* App is responsible for resource location, and path management.
|
||||
*
|
||||
* ### Adding paths
|
||||
*
|
||||
* Additional paths for Templates and Plugins are configured with Configure now. See config/app.php for an
|
||||
* example. The `App.paths.plugins` and `App.paths.templates` variables are used to configure paths for plugins
|
||||
* and templates respectively. All class based resources should be mapped using your application's autoloader.
|
||||
*
|
||||
* ### Inspecting loaded paths
|
||||
*
|
||||
* You can inspect the currently loaded paths using `App::classPath('Controller')` for example to see loaded
|
||||
* controller paths.
|
||||
*
|
||||
* It is also possible to inspect paths for plugin classes, for instance, to get
|
||||
* the path to a plugin's helpers you would call `App::classPath('View/Helper', 'MyPlugin')`
|
||||
*
|
||||
* ### Locating plugins
|
||||
*
|
||||
* Plugins can be located with App as well. Using Plugin::path('DebugKit') for example, will
|
||||
* give you the full path to the DebugKit plugin.
|
||||
*
|
||||
* @link https://book.cakephp.org/4/en/core-libraries/app.html
|
||||
*/
|
||||
class App
|
||||
{
|
||||
/**
|
||||
* Return the class name namespaced. This method checks if the class is defined on the
|
||||
* application/plugin, otherwise try to load from the CakePHP core
|
||||
*
|
||||
* @param string $class Class name
|
||||
* @param string $type Type of class
|
||||
* @param string $suffix Class name suffix
|
||||
* @return string|null Namespaced class name, null if the class is not found.
|
||||
* @psalm-return class-string|null
|
||||
*/
|
||||
public static function className(string $class, string $type = '', string $suffix = ''): ?string
|
||||
{
|
||||
if (strpos($class, '\\') !== false) {
|
||||
return class_exists($class) ? $class : null;
|
||||
}
|
||||
|
||||
[$plugin, $name] = pluginSplit($class);
|
||||
$fullname = '\\' . str_replace('/', '\\', $type . '\\' . $name) . $suffix;
|
||||
|
||||
$base = $plugin ?: Configure::read('App.namespace');
|
||||
if ($base !== null) {
|
||||
$base = str_replace('/', '\\', rtrim($base, '\\'));
|
||||
|
||||
if (static::_classExistsInBase($fullname, $base)) {
|
||||
/** @var class-string */
|
||||
return $base . $fullname;
|
||||
}
|
||||
}
|
||||
|
||||
if ($plugin || !static::_classExistsInBase($fullname, 'Cake')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var class-string */
|
||||
return 'Cake' . $fullname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin split name of a class
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* App::shortName(
|
||||
* 'SomeVendor\SomePlugin\Controller\Component\TestComponent',
|
||||
* 'Controller/Component',
|
||||
* 'Component'
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* Returns: SomeVendor/SomePlugin.Test
|
||||
*
|
||||
* ```
|
||||
* App::shortName(
|
||||
* 'SomeVendor\SomePlugin\Controller\Component\Subfolder\TestComponent',
|
||||
* 'Controller/Component',
|
||||
* 'Component'
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* Returns: SomeVendor/SomePlugin.Subfolder/Test
|
||||
*
|
||||
* ```
|
||||
* App::shortName(
|
||||
* 'Cake\Controller\Component\AuthComponent',
|
||||
* 'Controller/Component',
|
||||
* 'Component'
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* Returns: Auth
|
||||
*
|
||||
* @param string $class Class name
|
||||
* @param string $type Type of class
|
||||
* @param string $suffix Class name suffix
|
||||
* @return string Plugin split name of class
|
||||
*/
|
||||
public static function shortName(string $class, string $type, string $suffix = ''): string
|
||||
{
|
||||
$class = str_replace('\\', '/', $class);
|
||||
$type = '/' . $type . '/';
|
||||
|
||||
$pos = strrpos($class, $type);
|
||||
if ($pos === false) {
|
||||
return $class;
|
||||
}
|
||||
|
||||
$pluginName = (string)substr($class, 0, $pos);
|
||||
$name = (string)substr($class, $pos + strlen($type));
|
||||
|
||||
if ($suffix) {
|
||||
$name = (string)substr($name, 0, -strlen($suffix));
|
||||
}
|
||||
|
||||
$nonPluginNamespaces = [
|
||||
'Cake',
|
||||
str_replace('\\', '/', (string)Configure::read('App.namespace')),
|
||||
];
|
||||
if (in_array($pluginName, $nonPluginNamespaces, true)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return $pluginName . '.' . $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* _classExistsInBase
|
||||
*
|
||||
* Test isolation wrapper
|
||||
*
|
||||
* @param string $name Class name.
|
||||
* @param string $namespace Namespace.
|
||||
* @return bool
|
||||
*/
|
||||
protected static function _classExistsInBase(string $name, string $namespace): bool
|
||||
{
|
||||
return class_exists($namespace . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to read information stored path.
|
||||
*
|
||||
* The 1st character of $type argument should be lower cased and will return the
|
||||
* value of `App.paths.$type` config.
|
||||
*
|
||||
* Default types:
|
||||
* - plugins
|
||||
* - templates
|
||||
* - locales
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* App::path('plugins');
|
||||
* ```
|
||||
*
|
||||
* Will return the value of `App.paths.plugins` config.
|
||||
*
|
||||
* Deprecated: 4.0 App::path() is deprecated for class path (inside src/ directory).
|
||||
* Use \Cake\Core\App::classPath() instead or directly the method on \Cake\Core\Plugin class.
|
||||
*
|
||||
* @param string $type Type of path
|
||||
* @param string|null $plugin Plugin name
|
||||
* @return array<string>
|
||||
* @link https://book.cakephp.org/4/en/core-libraries/app.html#finding-paths-to-namespaces
|
||||
*/
|
||||
public static function path(string $type, ?string $plugin = null): array
|
||||
{
|
||||
if ($plugin === null && $type[0] === strtolower($type[0])) {
|
||||
return (array)Configure::read('App.paths.' . $type);
|
||||
}
|
||||
|
||||
if ($type === 'templates') {
|
||||
/** @psalm-suppress PossiblyNullArgument */
|
||||
return [Plugin::templatePath($plugin)];
|
||||
}
|
||||
|
||||
if ($type === 'locales') {
|
||||
/** @psalm-suppress PossiblyNullArgument */
|
||||
return [Plugin::path($plugin) . 'resources' . DIRECTORY_SEPARATOR . 'locales' . DIRECTORY_SEPARATOR];
|
||||
}
|
||||
|
||||
deprecationWarning(
|
||||
'App::path() is deprecated for class path.'
|
||||
. ' Use \Cake\Core\App::classPath() or \Cake\Core\Plugin::classPath() instead.'
|
||||
);
|
||||
|
||||
return static::classPath($type, $plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to a class type in the application or a plugin.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* App::classPath('Model/Table');
|
||||
* ```
|
||||
*
|
||||
* Will return the path for tables - e.g. `src/Model/Table/`.
|
||||
*
|
||||
* ```
|
||||
* App::classPath('Model/Table', 'My/Plugin');
|
||||
* ```
|
||||
*
|
||||
* Will return the plugin based path for those.
|
||||
*
|
||||
* @param string $type Package type.
|
||||
* @param string|null $plugin Plugin name.
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function classPath(string $type, ?string $plugin = null): array
|
||||
{
|
||||
if ($plugin !== null) {
|
||||
return [
|
||||
Plugin::classPath($plugin) . $type . DIRECTORY_SEPARATOR,
|
||||
];
|
||||
}
|
||||
|
||||
return [APP . $type . DIRECTORY_SEPARATOR];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path to a package inside the CakePHP core
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```
|
||||
* App::core('Cache/Engine');
|
||||
* ```
|
||||
*
|
||||
* Will return the full path to the cache engines package.
|
||||
*
|
||||
* @param string $type Package type.
|
||||
* @return array<string> Full path to package
|
||||
*/
|
||||
public static function core(string $type): array
|
||||
{
|
||||
if ($type === 'templates') {
|
||||
return [CORE_PATH . 'templates' . DIRECTORY_SEPARATOR];
|
||||
}
|
||||
|
||||
return [CAKE . str_replace('/', DIRECTORY_SEPARATOR, $type) . DIRECTORY_SEPARATOR];
|
||||
}
|
||||
}
|
305
vendor/cakephp/core/BasePlugin.php
vendored
Normal file
305
vendor/cakephp/core/BasePlugin.php
vendored
Normal file
@ -0,0 +1,305 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.6.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Console\CommandCollection;
|
||||
use Cake\Http\MiddlewareQueue;
|
||||
use Cake\Routing\RouteBuilder;
|
||||
use Closure;
|
||||
use InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Base Plugin Class
|
||||
*
|
||||
* Every plugin should extend from this class or implement the interfaces and
|
||||
* include a plugin class in its src root folder.
|
||||
*/
|
||||
class BasePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* Do bootstrapping or not
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $bootstrapEnabled = true;
|
||||
|
||||
/**
|
||||
* Console middleware
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $consoleEnabled = true;
|
||||
|
||||
/**
|
||||
* Enable middleware
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $middlewareEnabled = true;
|
||||
|
||||
/**
|
||||
* Register container services
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $servicesEnabled = true;
|
||||
|
||||
/**
|
||||
* Load routes or not
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $routesEnabled = true;
|
||||
|
||||
/**
|
||||
* The path to this plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* The class path for this plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $classPath;
|
||||
|
||||
/**
|
||||
* The config path for this plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $configPath;
|
||||
|
||||
/**
|
||||
* The templates path for this plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $templatePath;
|
||||
|
||||
/**
|
||||
* The name of this plugin
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array<string, mixed> $options Options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
foreach (static::VALID_HOOKS as $key) {
|
||||
if (isset($options[$key])) {
|
||||
$this->{"{$key}Enabled"} = (bool)$options[$key];
|
||||
}
|
||||
}
|
||||
foreach (['name', 'path', 'classPath', 'configPath', 'templatePath'] as $path) {
|
||||
if (isset($options[$path])) {
|
||||
$this->{$path} = $options[$path];
|
||||
}
|
||||
}
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization hook called from constructor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
if ($this->name) {
|
||||
return $this->name;
|
||||
}
|
||||
$parts = explode('\\', static::class);
|
||||
array_pop($parts);
|
||||
$this->name = implode('/', $parts);
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getPath(): string
|
||||
{
|
||||
if ($this->path) {
|
||||
return $this->path;
|
||||
}
|
||||
$reflection = new ReflectionClass($this);
|
||||
$path = dirname($reflection->getFileName());
|
||||
|
||||
// Trim off src
|
||||
if (substr($path, -3) === 'src') {
|
||||
$path = substr($path, 0, -3);
|
||||
}
|
||||
$this->path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getConfigPath(): string
|
||||
{
|
||||
if ($this->configPath) {
|
||||
return $this->configPath;
|
||||
}
|
||||
$path = $this->getPath();
|
||||
|
||||
return $path . 'config' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getClassPath(): string
|
||||
{
|
||||
if ($this->classPath) {
|
||||
return $this->classPath;
|
||||
}
|
||||
$path = $this->getPath();
|
||||
|
||||
return $path . 'src' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getTemplatePath(): string
|
||||
{
|
||||
if ($this->templatePath) {
|
||||
return $this->templatePath;
|
||||
}
|
||||
$path = $this->getPath();
|
||||
|
||||
return $this->templatePath = $path . 'templates' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enable(string $hook)
|
||||
{
|
||||
$this->checkHook($hook);
|
||||
$this->{"{$hook}Enabled"} = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function disable(string $hook)
|
||||
{
|
||||
$this->checkHook($hook);
|
||||
$this->{"{$hook}Enabled"} = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isEnabled(string $hook): bool
|
||||
{
|
||||
$this->checkHook($hook);
|
||||
|
||||
return $this->{"{$hook}Enabled"} === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a hook name is valid
|
||||
*
|
||||
* @param string $hook The hook name to check
|
||||
* @throws \InvalidArgumentException on invalid hooks
|
||||
* @return void
|
||||
*/
|
||||
protected function checkHook(string $hook): void
|
||||
{
|
||||
if (!in_array($hook, static::VALID_HOOKS, true)) {
|
||||
throw new InvalidArgumentException(
|
||||
"`$hook` is not a valid hook name. Must be one of " . implode(', ', static::VALID_HOOKS)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function routes(RouteBuilder $routes): void
|
||||
{
|
||||
$path = $this->getConfigPath() . 'routes.php';
|
||||
if (is_file($path)) {
|
||||
$return = require $path;
|
||||
if ($return instanceof Closure) {
|
||||
$return($routes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function bootstrap(PluginApplicationInterface $app): void
|
||||
{
|
||||
$bootstrap = $this->getConfigPath() . 'bootstrap.php';
|
||||
if (is_file($bootstrap)) {
|
||||
require $bootstrap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function console(CommandCollection $commands): CommandCollection
|
||||
{
|
||||
return $commands->addMany($commands->discoverPlugin($this->getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
|
||||
{
|
||||
return $middlewareQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register container services for this plugin.
|
||||
*
|
||||
* @param \Cake\Core\ContainerInterface $container The container to add services to.
|
||||
* @return void
|
||||
*/
|
||||
public function services(ContainerInterface $container): void
|
||||
{
|
||||
}
|
||||
}
|
139
vendor/cakephp/core/ClassLoader.php
vendored
Normal file
139
vendor/cakephp/core/ClassLoader.php
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
/**
|
||||
* ClassLoader
|
||||
*
|
||||
* @deprecated 4.0.3 Use composer to generate autoload files instead.
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/**
|
||||
* An associative array where the key is a namespace prefix and the value
|
||||
* is an array of base directories for classes in that namespace.
|
||||
*
|
||||
* @var array<string, array>
|
||||
*/
|
||||
protected $_prefixes = [];
|
||||
|
||||
/**
|
||||
* Register loader with SPL autoloader stack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
/** @var callable $callable */
|
||||
$callable = [$this, 'loadClass'];
|
||||
spl_autoload_register($callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a base directory for a namespace prefix.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $baseDir A base directory for class files in the
|
||||
* namespace.
|
||||
* @param bool $prepend If true, prepend the base directory to the stack
|
||||
* instead of appending it; this causes it to be searched first rather
|
||||
* than last.
|
||||
* @return void
|
||||
*/
|
||||
public function addNamespace(string $prefix, string $baseDir, bool $prepend = false): void
|
||||
{
|
||||
$prefix = trim($prefix, '\\') . '\\';
|
||||
|
||||
$baseDir = rtrim($baseDir, '/') . DIRECTORY_SEPARATOR;
|
||||
$baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
|
||||
|
||||
$this->_prefixes[$prefix] = $this->_prefixes[$prefix] ?? [];
|
||||
|
||||
if ($prepend) {
|
||||
array_unshift($this->_prefixes[$prefix], $baseDir);
|
||||
} else {
|
||||
$this->_prefixes[$prefix][] = $baseDir;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the class file for a given class name.
|
||||
*
|
||||
* @param string $class The fully-qualified class name.
|
||||
* @return string|false The mapped file name on success, or boolean false on
|
||||
* failure.
|
||||
*/
|
||||
public function loadClass(string $class)
|
||||
{
|
||||
$prefix = $class;
|
||||
|
||||
while (($pos = strrpos($prefix, '\\')) !== false) {
|
||||
$prefix = substr($class, 0, $pos + 1);
|
||||
$relativeClass = substr($class, $pos + 1);
|
||||
|
||||
$mappedFile = $this->_loadMappedFile($prefix, $relativeClass);
|
||||
if ($mappedFile) {
|
||||
return $mappedFile;
|
||||
}
|
||||
|
||||
$prefix = rtrim($prefix, '\\');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the mapped file for a namespace prefix and relative class.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $relativeClass The relative class name.
|
||||
* @return string|false Boolean false if no mapped file can be loaded, or the
|
||||
* name of the mapped file that was loaded.
|
||||
*/
|
||||
protected function _loadMappedFile(string $prefix, string $relativeClass)
|
||||
{
|
||||
if (!isset($this->_prefixes[$prefix])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->_prefixes[$prefix] as $baseDir) {
|
||||
$file = $baseDir . str_replace('\\', DIRECTORY_SEPARATOR, $relativeClass) . '.php';
|
||||
|
||||
if ($this->_requireFile($file)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a file exists, require it from the file system.
|
||||
*
|
||||
* @param string $file The file to require.
|
||||
* @return bool True if the file exists, false if not.
|
||||
*/
|
||||
protected function _requireFile(string $file): bool
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
498
vendor/cakephp/core/Configure.php
vendored
Normal file
498
vendor/cakephp/core/Configure.php
vendored
Normal file
@ -0,0 +1,498 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 1.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Cache\Cache;
|
||||
use Cake\Core\Configure\ConfigEngineInterface;
|
||||
use Cake\Core\Configure\Engine\PhpConfig;
|
||||
use Cake\Core\Exception\CakeException;
|
||||
use Cake\Utility\Hash;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Configuration class. Used for managing runtime configuration information.
|
||||
*
|
||||
* Provides features for reading and writing to the runtime configuration, as well
|
||||
* as methods for loading additional configuration files or storing runtime configuration
|
||||
* for future use.
|
||||
*
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html
|
||||
*/
|
||||
class Configure
|
||||
{
|
||||
/**
|
||||
* Array of values currently stored in Configure.
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected static $_values = [
|
||||
'debug' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Configured engine classes, used to load config files from resources
|
||||
*
|
||||
* @see \Cake\Core\Configure::load()
|
||||
* @var array<\Cake\Core\Configure\ConfigEngineInterface>
|
||||
*/
|
||||
protected static $_engines = [];
|
||||
|
||||
/**
|
||||
* Flag to track whether ini_set exists.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
protected static $_hasIniSet;
|
||||
|
||||
/**
|
||||
* Used to store a dynamic variable in Configure.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* Configure::write('One.key1', 'value of the Configure::One[key1]');
|
||||
* Configure::write(['One.key1' => 'value of the Configure::One[key1]']);
|
||||
* Configure::write('One', [
|
||||
* 'key1' => 'value of the Configure::One[key1]',
|
||||
* 'key2' => 'value of the Configure::One[key2]'
|
||||
* ]);
|
||||
*
|
||||
* Configure::write([
|
||||
* 'One.key1' => 'value of the Configure::One[key1]',
|
||||
* 'One.key2' => 'value of the Configure::One[key2]'
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* @param array<string, mixed>|string $config The key to write, can be a dot notation value.
|
||||
* Alternatively can be an array containing key(s) and value(s).
|
||||
* @param mixed $value Value to set for the given key.
|
||||
* @return void
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html#writing-configuration-data
|
||||
*/
|
||||
public static function write($config, $value = null): void
|
||||
{
|
||||
if (!is_array($config)) {
|
||||
$config = [$config => $value];
|
||||
}
|
||||
|
||||
foreach ($config as $name => $valueToInsert) {
|
||||
static::$_values = Hash::insert(static::$_values, $name, $valueToInsert);
|
||||
}
|
||||
|
||||
if (isset($config['debug'])) {
|
||||
if (static::$_hasIniSet === null) {
|
||||
static::$_hasIniSet = function_exists('ini_set');
|
||||
}
|
||||
if (static::$_hasIniSet) {
|
||||
ini_set('display_errors', $config['debug'] ? '1' : '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to read information stored in Configure. It's not
|
||||
* possible to store `null` values in Configure.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* Configure::read('Name'); will return all values for Name
|
||||
* Configure::read('Name.key'); will return only the value of Configure::Name[key]
|
||||
* ```
|
||||
*
|
||||
* @param string|null $var Variable to obtain. Use '.' to access array elements.
|
||||
* @param mixed $default The return value when the configure does not exist
|
||||
* @return mixed Value stored in configure, or null.
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html#reading-configuration-data
|
||||
*/
|
||||
public static function read(?string $var = null, $default = null)
|
||||
{
|
||||
if ($var === null) {
|
||||
return static::$_values;
|
||||
}
|
||||
|
||||
return Hash::get(static::$_values, $var, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if given variable is set in Configure.
|
||||
*
|
||||
* @param string $var Variable name to check for
|
||||
* @return bool True if variable is there
|
||||
*/
|
||||
public static function check(string $var): bool
|
||||
{
|
||||
if (empty($var)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return static::read($var) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get information stored in Configure. It's not
|
||||
* possible to store `null` values in Configure.
|
||||
*
|
||||
* Acts as a wrapper around Configure::read() and Configure::check().
|
||||
* The configure key/value pair fetched via this method is expected to exist.
|
||||
* In case it does not an exception will be thrown.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* Configure::readOrFail('Name'); will return all values for Name
|
||||
* Configure::readOrFail('Name.key'); will return only the value of Configure::Name[key]
|
||||
* ```
|
||||
*
|
||||
* @param string $var Variable to obtain. Use '.' to access array elements.
|
||||
* @return mixed Value stored in configure.
|
||||
* @throws \RuntimeException if the requested configuration is not set.
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html#reading-configuration-data
|
||||
*/
|
||||
public static function readOrFail(string $var)
|
||||
{
|
||||
if (!static::check($var)) {
|
||||
throw new RuntimeException(sprintf('Expected configuration key "%s" not found.', $var));
|
||||
}
|
||||
|
||||
return static::read($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to delete a variable from Configure.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* Configure::delete('Name'); will delete the entire Configure::Name
|
||||
* Configure::delete('Name.key'); will delete only the Configure::Name[key]
|
||||
* ```
|
||||
*
|
||||
* @param string $var the var to be deleted
|
||||
* @return void
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html#deleting-configuration-data
|
||||
*/
|
||||
public static function delete(string $var): void
|
||||
{
|
||||
static::$_values = Hash::remove(static::$_values, $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to consume information stored in Configure. It's not
|
||||
* possible to store `null` values in Configure.
|
||||
*
|
||||
* Acts as a wrapper around Configure::consume() and Configure::check().
|
||||
* The configure key/value pair consumed via this method is expected to exist.
|
||||
* In case it does not an exception will be thrown.
|
||||
*
|
||||
* @param string $var Variable to consume. Use '.' to access array elements.
|
||||
* @return mixed Value stored in configure.
|
||||
* @throws \RuntimeException if the requested configuration is not set.
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public static function consumeOrFail(string $var)
|
||||
{
|
||||
if (!static::check($var)) {
|
||||
throw new RuntimeException(sprintf('Expected configuration key "%s" not found.', $var));
|
||||
}
|
||||
|
||||
return static::consume($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to read and delete a variable from Configure.
|
||||
*
|
||||
* This is primarily used during bootstrapping to move configuration data
|
||||
* out of configure into the various other classes in CakePHP.
|
||||
*
|
||||
* @param string $var The key to read and remove.
|
||||
* @return array|string|null
|
||||
*/
|
||||
public static function consume(string $var)
|
||||
{
|
||||
if (strpos($var, '.') === false) {
|
||||
if (!isset(static::$_values[$var])) {
|
||||
return null;
|
||||
}
|
||||
$value = static::$_values[$var];
|
||||
unset(static::$_values[$var]);
|
||||
|
||||
return $value;
|
||||
}
|
||||
$value = Hash::get(static::$_values, $var);
|
||||
static::delete($var);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new engine to Configure. Engines allow you to read configuration
|
||||
* files in various formats/storage locations. CakePHP comes with two built-in engines
|
||||
* PhpConfig and IniConfig. You can also implement your own engine classes in your application.
|
||||
*
|
||||
* To add a new engine to Configure:
|
||||
*
|
||||
* ```
|
||||
* Configure::config('ini', new IniConfig());
|
||||
* ```
|
||||
*
|
||||
* @param string $name The name of the engine being configured. This alias is used later to
|
||||
* read values from a specific engine.
|
||||
* @param \Cake\Core\Configure\ConfigEngineInterface $engine The engine to append.
|
||||
* @return void
|
||||
*/
|
||||
public static function config(string $name, ConfigEngineInterface $engine): void
|
||||
{
|
||||
static::$_engines[$name] = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Engine objects is configured.
|
||||
*
|
||||
* @param string $name Engine name.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isConfigured(string $name): bool
|
||||
{
|
||||
return isset(static::$_engines[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of the configured Engine objects.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function configured(): array
|
||||
{
|
||||
$engines = array_keys(static::$_engines);
|
||||
|
||||
return array_map(function ($key) {
|
||||
return (string)$key;
|
||||
}, $engines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a configured engine. This will unset the engine
|
||||
* and make any future attempts to use it cause an Exception.
|
||||
*
|
||||
* @param string $name Name of the engine to drop.
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function drop(string $name): bool
|
||||
{
|
||||
if (!isset(static::$_engines[$name])) {
|
||||
return false;
|
||||
}
|
||||
unset(static::$_engines[$name]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads stored configuration information from a resource. You can add
|
||||
* config file resource engines with `Configure::config()`.
|
||||
*
|
||||
* Loaded configuration information will be merged with the current
|
||||
* runtime configuration. You can load configuration files from plugins
|
||||
* by preceding the filename with the plugin name.
|
||||
*
|
||||
* `Configure::load('Users.user', 'default')`
|
||||
*
|
||||
* Would load the 'user' config file using the default config engine. You can load
|
||||
* app config files by giving the name of the resource you want loaded.
|
||||
*
|
||||
* ```
|
||||
* Configure::load('setup', 'default');
|
||||
* ```
|
||||
*
|
||||
* If using `default` config and no engine has been configured for it yet,
|
||||
* one will be automatically created using PhpConfig
|
||||
*
|
||||
* @param string $key name of configuration resource to load.
|
||||
* @param string $config Name of the configured engine to use to read the resource identified by $key.
|
||||
* @param bool $merge if config files should be merged instead of simply overridden
|
||||
* @return bool True if load successful.
|
||||
* @throws \Cake\Core\Exception\CakeException if the $config engine is not found
|
||||
* @link https://book.cakephp.org/4/en/development/configuration.html#reading-and-writing-configuration-files
|
||||
*/
|
||||
public static function load(string $key, string $config = 'default', bool $merge = true): bool
|
||||
{
|
||||
$engine = static::_getEngine($config);
|
||||
if (!$engine) {
|
||||
throw new CakeException(
|
||||
sprintf(
|
||||
'Config %s engine not found when attempting to load %s.',
|
||||
$config,
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$values = $engine->read($key);
|
||||
|
||||
if ($merge) {
|
||||
$values = Hash::merge(static::$_values, $values);
|
||||
}
|
||||
|
||||
static::write($values);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump data currently in Configure into $key. The serialization format
|
||||
* is decided by the config engine attached as $config. For example, if the
|
||||
* 'default' adapter is a PhpConfig, the generated file will be a PHP
|
||||
* configuration file loadable by the PhpConfig.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* Given that the 'default' engine is an instance of PhpConfig.
|
||||
* Save all data in Configure to the file `my_config.php`:
|
||||
*
|
||||
* ```
|
||||
* Configure::dump('my_config', 'default');
|
||||
* ```
|
||||
*
|
||||
* Save only the error handling configuration:
|
||||
*
|
||||
* ```
|
||||
* Configure::dump('error', 'default', ['Error', 'Exception'];
|
||||
* ```
|
||||
*
|
||||
* @param string $key The identifier to create in the config adapter.
|
||||
* This could be a filename or a cache key depending on the adapter being used.
|
||||
* @param string $config The name of the configured adapter to dump data with.
|
||||
* @param array<string> $keys The name of the top-level keys you want to dump.
|
||||
* This allows you save only some data stored in Configure.
|
||||
* @return bool Success
|
||||
* @throws \Cake\Core\Exception\CakeException if the adapter does not implement a `dump` method.
|
||||
*/
|
||||
public static function dump(string $key, string $config = 'default', array $keys = []): bool
|
||||
{
|
||||
$engine = static::_getEngine($config);
|
||||
if (!$engine) {
|
||||
throw new CakeException(sprintf('There is no "%s" config engine.', $config));
|
||||
}
|
||||
$values = static::$_values;
|
||||
if (!empty($keys)) {
|
||||
$values = array_intersect_key($values, array_flip($keys));
|
||||
}
|
||||
|
||||
return $engine->dump($key, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured engine. Internally used by `Configure::load()` and `Configure::dump()`
|
||||
* Will create new PhpConfig for default if not configured yet.
|
||||
*
|
||||
* @param string $config The name of the configured adapter
|
||||
* @return \Cake\Core\Configure\ConfigEngineInterface|null Engine instance or null
|
||||
*/
|
||||
protected static function _getEngine(string $config): ?ConfigEngineInterface
|
||||
{
|
||||
if (!isset(static::$_engines[$config])) {
|
||||
if ($config !== 'default') {
|
||||
return null;
|
||||
}
|
||||
static::config($config, new PhpConfig());
|
||||
}
|
||||
|
||||
return static::$_engines[$config];
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine the current version of CakePHP.
|
||||
*
|
||||
* Usage
|
||||
* ```
|
||||
* Configure::version();
|
||||
* ```
|
||||
*
|
||||
* @return string Current version of CakePHP
|
||||
*/
|
||||
public static function version(): string
|
||||
{
|
||||
$version = static::read('Cake.version');
|
||||
if ($version !== null) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$path = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'config/config.php';
|
||||
if (is_file($path)) {
|
||||
$config = require $path;
|
||||
static::write($config);
|
||||
|
||||
return static::read('Cake.version');
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to write runtime configuration into Cache. Stored runtime configuration can be
|
||||
* restored using `Configure::restore()`. These methods can be used to enable configuration managers
|
||||
* frontends, or other GUI type interfaces for configuration.
|
||||
*
|
||||
* @param string $name The storage name for the saved configuration.
|
||||
* @param string $cacheConfig The cache configuration to save into. Defaults to 'default'
|
||||
* @param array|null $data Either an array of data to store, or leave empty to store all values.
|
||||
* @return bool Success
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function store(string $name, string $cacheConfig = 'default', ?array $data = null): bool
|
||||
{
|
||||
if ($data === null) {
|
||||
$data = static::$_values;
|
||||
}
|
||||
if (!class_exists(Cache::class)) {
|
||||
throw new RuntimeException('You must install cakephp/cache to use Configure::store()');
|
||||
}
|
||||
|
||||
return Cache::write($name, $data, $cacheConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores configuration data stored in the Cache into configure. Restored
|
||||
* values will overwrite existing ones.
|
||||
*
|
||||
* @param string $name Name of the stored config file to load.
|
||||
* @param string $cacheConfig Name of the Cache configuration to read from.
|
||||
* @return bool Success.
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function restore(string $name, string $cacheConfig = 'default'): bool
|
||||
{
|
||||
if (!class_exists(Cache::class)) {
|
||||
throw new RuntimeException('You must install cakephp/cache to use Configure::restore()');
|
||||
}
|
||||
$values = Cache::read($name, $cacheConfig);
|
||||
if ($values) {
|
||||
static::write($values);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all values stored in Configure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear(): void
|
||||
{
|
||||
static::$_values = [];
|
||||
}
|
||||
}
|
44
vendor/cakephp/core/Configure/ConfigEngineInterface.php
vendored
Normal file
44
vendor/cakephp/core/Configure/ConfigEngineInterface.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 1.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Configure;
|
||||
|
||||
/**
|
||||
* An interface for creating objects compatible with Configure::load()
|
||||
*/
|
||||
interface ConfigEngineInterface
|
||||
{
|
||||
/**
|
||||
* Read a configuration file/storage key
|
||||
*
|
||||
* This method is used for reading configuration information from sources.
|
||||
* These sources can either be static resources like files, or dynamic ones like
|
||||
* a database, or other datasource.
|
||||
*
|
||||
* @param string $key Key to read.
|
||||
* @return array An array of data to merge into the runtime configuration
|
||||
*/
|
||||
public function read(string $key): array;
|
||||
|
||||
/**
|
||||
* Dumps the configure data into the storage key/file of the given `$key`.
|
||||
*
|
||||
* @param string $key The identifier to write to.
|
||||
* @param array $data The data to dump.
|
||||
* @return bool True on success or false on failure.
|
||||
*/
|
||||
public function dump(string $key, array $data): bool;
|
||||
}
|
203
vendor/cakephp/core/Configure/Engine/IniConfig.php
vendored
Normal file
203
vendor/cakephp/core/Configure/Engine/IniConfig.php
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 2.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Configure\Engine;
|
||||
|
||||
use Cake\Core\Configure\ConfigEngineInterface;
|
||||
use Cake\Core\Configure\FileConfigTrait;
|
||||
use Cake\Utility\Hash;
|
||||
|
||||
/**
|
||||
* Ini file configuration engine.
|
||||
*
|
||||
* Since IniConfig uses parse_ini_file underneath, you should be aware that this
|
||||
* class shares the same behavior, especially with regards to boolean and null values.
|
||||
*
|
||||
* In addition to the native `parse_ini_file` features, IniConfig also allows you
|
||||
* to create nested array structures through usage of `.` delimited names. This allows
|
||||
* you to create nested arrays structures in an ini config file. For example:
|
||||
*
|
||||
* `db.password = secret` would turn into `['db' => ['password' => 'secret']]`
|
||||
*
|
||||
* You can nest properties as deeply as needed using `.`'s. In addition to using `.` you
|
||||
* can use standard ini section notation to create nested structures:
|
||||
*
|
||||
* ```
|
||||
* [section]
|
||||
* key = value
|
||||
* ```
|
||||
*
|
||||
* Once loaded into Configure, the above would be accessed using:
|
||||
*
|
||||
* `Configure::read('section.key');
|
||||
*
|
||||
* You can also use `.` separated values in section names to create more deeply
|
||||
* nested structures.
|
||||
*
|
||||
* IniConfig also manipulates how the special ini values of
|
||||
* 'yes', 'no', 'on', 'off', 'null' are handled. These values will be
|
||||
* converted to their boolean equivalents.
|
||||
*
|
||||
* @see https://secure.php.net/parse_ini_file
|
||||
*/
|
||||
class IniConfig implements ConfigEngineInterface
|
||||
{
|
||||
use FileConfigTrait;
|
||||
|
||||
/**
|
||||
* File extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_extension = '.ini';
|
||||
|
||||
/**
|
||||
* The section to read, if null all sections will be read.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $_section;
|
||||
|
||||
/**
|
||||
* Build and construct a new ini file parser. The parser can be used to read
|
||||
* ini files that are on the filesystem.
|
||||
*
|
||||
* @param string|null $path Path to load ini config files from. Defaults to CONFIG.
|
||||
* @param string|null $section Only get one section, leave null to parse and fetch
|
||||
* all sections in the ini file.
|
||||
*/
|
||||
public function __construct(?string $path = null, ?string $section = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
$path = CONFIG;
|
||||
}
|
||||
$this->_path = $path;
|
||||
$this->_section = $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an ini file and return the results as an array.
|
||||
*
|
||||
* @param string $key The identifier to read from. If the key has a . it will be treated
|
||||
* as a plugin prefix. The chosen file must be on the engine's path.
|
||||
* @return array Parsed configuration values.
|
||||
* @throws \Cake\Core\Exception\CakeException when files don't exist.
|
||||
* Or when files contain '..' as this could lead to abusive reads.
|
||||
*/
|
||||
public function read(string $key): array
|
||||
{
|
||||
$file = $this->_getFilePath($key, true);
|
||||
|
||||
$contents = parse_ini_file($file, true);
|
||||
if ($this->_section && isset($contents[$this->_section])) {
|
||||
$values = $this->_parseNestedValues($contents[$this->_section]);
|
||||
} else {
|
||||
$values = [];
|
||||
foreach ($contents as $section => $attribs) {
|
||||
if (is_array($attribs)) {
|
||||
$values[$section] = $this->_parseNestedValues($attribs);
|
||||
} else {
|
||||
$parse = $this->_parseNestedValues([$attribs]);
|
||||
$values[$section] = array_shift($parse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses nested values out of keys.
|
||||
*
|
||||
* @param array $values Values to be exploded.
|
||||
* @return array Array of values exploded
|
||||
*/
|
||||
protected function _parseNestedValues(array $values): array
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
if ($value === '1') {
|
||||
$value = true;
|
||||
}
|
||||
if ($value === '') {
|
||||
$value = false;
|
||||
}
|
||||
unset($values[$key]);
|
||||
if (strpos((string)$key, '.') !== false) {
|
||||
$values = Hash::insert($values, $key, $value);
|
||||
} else {
|
||||
$values[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the state of Configure data into an ini formatted string.
|
||||
*
|
||||
* @param string $key The identifier to write to. If the key has a . it will be treated
|
||||
* as a plugin prefix.
|
||||
* @param array $data The data to convert to ini file.
|
||||
* @return bool Success.
|
||||
*/
|
||||
public function dump(string $key, array $data): bool
|
||||
{
|
||||
$result = [];
|
||||
foreach ($data as $k => $value) {
|
||||
$isSection = false;
|
||||
/** @psalm-suppress InvalidArrayAccess */
|
||||
if ($k[0] !== '[') {
|
||||
$result[] = "[$k]";
|
||||
$isSection = true;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$kValues = Hash::flatten($value, '.');
|
||||
foreach ($kValues as $k2 => $v) {
|
||||
$result[] = "$k2 = " . $this->_value($v);
|
||||
}
|
||||
}
|
||||
if ($isSection) {
|
||||
$result[] = '';
|
||||
}
|
||||
}
|
||||
$contents = trim(implode("\n", $result));
|
||||
|
||||
$filename = $this->_getFilePath($key);
|
||||
|
||||
return file_put_contents($filename, $contents) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value into the ini equivalent
|
||||
*
|
||||
* @param mixed $value Value to export.
|
||||
* @return string String value for ini file.
|
||||
*/
|
||||
protected function _value($value): string
|
||||
{
|
||||
if ($value === null) {
|
||||
return 'null';
|
||||
}
|
||||
if ($value === true) {
|
||||
return 'true';
|
||||
}
|
||||
if ($value === false) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
return (string)$value;
|
||||
}
|
||||
}
|
115
vendor/cakephp/core/Configure/Engine/JsonConfig.php
vendored
Normal file
115
vendor/cakephp/core/Configure/Engine/JsonConfig.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Configure\Engine;
|
||||
|
||||
use Cake\Core\Configure\ConfigEngineInterface;
|
||||
use Cake\Core\Configure\FileConfigTrait;
|
||||
use Cake\Core\Exception\CakeException;
|
||||
|
||||
/**
|
||||
* JSON engine allows Configure to load configuration values from
|
||||
* files containing JSON strings.
|
||||
*
|
||||
* An example JSON file would look like::
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* "debug": false,
|
||||
* "App": {
|
||||
* "namespace": "MyApp"
|
||||
* },
|
||||
* "Security": {
|
||||
* "salt": "its-secret"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class JsonConfig implements ConfigEngineInterface
|
||||
{
|
||||
use FileConfigTrait;
|
||||
|
||||
/**
|
||||
* File extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_extension = '.json';
|
||||
|
||||
/**
|
||||
* Constructor for JSON Config file reading.
|
||||
*
|
||||
* @param string|null $path The path to read config files from. Defaults to CONFIG.
|
||||
*/
|
||||
public function __construct(?string $path = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
$path = CONFIG;
|
||||
}
|
||||
$this->_path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a config file and return its contents.
|
||||
*
|
||||
* Files with `.` in the name will be treated as values in plugins. Instead of
|
||||
* reading from the initialized path, plugin keys will be located using Plugin::path().
|
||||
*
|
||||
* @param string $key The identifier to read from. If the key has a . it will be treated
|
||||
* as a plugin prefix.
|
||||
* @return array Parsed configuration values.
|
||||
* @throws \Cake\Core\Exception\CakeException When files don't exist or when
|
||||
* files contain '..' (as this could lead to abusive reads) or when there
|
||||
* is an error parsing the JSON string.
|
||||
*/
|
||||
public function read(string $key): array
|
||||
{
|
||||
$file = $this->_getFilePath($key, true);
|
||||
|
||||
$values = json_decode(file_get_contents($file), true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new CakeException(sprintf(
|
||||
'Error parsing JSON string fetched from config file "%s.json": %s',
|
||||
$key,
|
||||
json_last_error_msg()
|
||||
));
|
||||
}
|
||||
if (!is_array($values)) {
|
||||
throw new CakeException(sprintf(
|
||||
'Decoding JSON config file "%s.json" did not return an array',
|
||||
$key
|
||||
));
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the provided $data into a JSON string that can be used saved
|
||||
* into a file and loaded later.
|
||||
*
|
||||
* @param string $key The identifier to write to. If the key has a . it will
|
||||
* be treated as a plugin prefix.
|
||||
* @param array $data Data to dump.
|
||||
* @return bool Success
|
||||
*/
|
||||
public function dump(string $key, array $data): bool
|
||||
{
|
||||
$filename = $this->_getFilePath($key);
|
||||
|
||||
return file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT)) > 0;
|
||||
}
|
||||
}
|
114
vendor/cakephp/core/Configure/Engine/PhpConfig.php
vendored
Normal file
114
vendor/cakephp/core/Configure/Engine/PhpConfig.php
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 2.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Configure\Engine;
|
||||
|
||||
use Cake\Core\Configure\ConfigEngineInterface;
|
||||
use Cake\Core\Configure\FileConfigTrait;
|
||||
use Cake\Core\Exception\CakeException;
|
||||
|
||||
/**
|
||||
* PHP engine allows Configure to load configuration values from
|
||||
* files containing simple PHP arrays.
|
||||
*
|
||||
* Files compatible with PhpConfig should return an array that
|
||||
* contains all the configuration data contained in the file.
|
||||
*
|
||||
* An example configuration file would look like::
|
||||
*
|
||||
* ```
|
||||
* <?php
|
||||
* return [
|
||||
* 'debug' => false,
|
||||
* 'Security' => [
|
||||
* 'salt' => 'its-secret'
|
||||
* ],
|
||||
* 'App' => [
|
||||
* 'namespace' => 'App'
|
||||
* ]
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* @see \Cake\Core\Configure::load() for how to load custom configuration files.
|
||||
*/
|
||||
class PhpConfig implements ConfigEngineInterface
|
||||
{
|
||||
use FileConfigTrait;
|
||||
|
||||
/**
|
||||
* File extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_extension = '.php';
|
||||
|
||||
/**
|
||||
* Constructor for PHP Config file reading.
|
||||
*
|
||||
* @param string|null $path The path to read config files from. Defaults to CONFIG.
|
||||
*/
|
||||
public function __construct(?string $path = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
$path = CONFIG;
|
||||
}
|
||||
$this->_path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a config file and return its contents.
|
||||
*
|
||||
* Files with `.` in the name will be treated as values in plugins. Instead of
|
||||
* reading from the initialized path, plugin keys will be located using Plugin::path().
|
||||
*
|
||||
* @param string $key The identifier to read from. If the key has a . it will be treated
|
||||
* as a plugin prefix.
|
||||
* @return array Parsed configuration values.
|
||||
* @throws \Cake\Core\Exception\CakeException when files don't exist or they don't contain `$config`.
|
||||
* Or when files contain '..' as this could lead to abusive reads.
|
||||
*/
|
||||
public function read(string $key): array
|
||||
{
|
||||
$file = $this->_getFilePath($key, true);
|
||||
|
||||
$config = null;
|
||||
|
||||
$return = include $file;
|
||||
if (is_array($return)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
throw new CakeException(sprintf('Config file "%s" did not return an array', $key . '.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the provided $data into a string of PHP code that can
|
||||
* be used saved into a file and loaded later.
|
||||
*
|
||||
* @param string $key The identifier to write to. If the key has a . it will be treated
|
||||
* as a plugin prefix.
|
||||
* @param array $data Data to dump.
|
||||
* @return bool Success
|
||||
*/
|
||||
public function dump(string $key, array $data): bool
|
||||
{
|
||||
$contents = '<?php' . "\n" . 'return ' . var_export($data, true) . ';';
|
||||
|
||||
$filename = $this->_getFilePath($key);
|
||||
|
||||
return file_put_contents($filename, $contents) > 0;
|
||||
}
|
||||
}
|
72
vendor/cakephp/core/Configure/FileConfigTrait.php
vendored
Normal file
72
vendor/cakephp/core/Configure/FileConfigTrait.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Configure;
|
||||
|
||||
use Cake\Core\Exception\CakeException;
|
||||
use Cake\Core\Plugin;
|
||||
use function Cake\Core\pluginSplit;
|
||||
|
||||
/**
|
||||
* Trait providing utility methods for file based config engines.
|
||||
*/
|
||||
trait FileConfigTrait
|
||||
{
|
||||
/**
|
||||
* The path this engine finds files on.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_path = '';
|
||||
|
||||
/**
|
||||
* Get file path
|
||||
*
|
||||
* @param string $key The identifier to write to. If the key has a . it will be treated
|
||||
* as a plugin prefix.
|
||||
* @param bool $checkExists Whether to check if file exists. Defaults to false.
|
||||
* @return string Full file path
|
||||
* @throws \Cake\Core\Exception\CakeException When files don't exist or when
|
||||
* files contain '..' as this could lead to abusive reads.
|
||||
*/
|
||||
protected function _getFilePath(string $key, bool $checkExists = false): string
|
||||
{
|
||||
if (strpos($key, '..') !== false) {
|
||||
throw new CakeException('Cannot load/dump configuration files with ../ in them.');
|
||||
}
|
||||
|
||||
[$plugin, $key] = pluginSplit($key);
|
||||
|
||||
if ($plugin) {
|
||||
$file = Plugin::configPath($plugin) . $key;
|
||||
} else {
|
||||
$file = $this->_path . $key;
|
||||
}
|
||||
|
||||
$file .= $this->_extension;
|
||||
|
||||
if (!$checkExists || is_file($file)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
$realPath = realpath($file);
|
||||
if ($realPath !== false && is_file($realPath)) {
|
||||
return $realPath;
|
||||
}
|
||||
|
||||
throw new CakeException(sprintf('Could not load configuration file: %s', $file));
|
||||
}
|
||||
}
|
42
vendor/cakephp/core/ConsoleApplicationInterface.php
vendored
Normal file
42
vendor/cakephp/core/ConsoleApplicationInterface.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.5.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Console\CommandCollection;
|
||||
|
||||
/**
|
||||
* An interface defining the methods that the
|
||||
* console runner depend on.
|
||||
*/
|
||||
interface ConsoleApplicationInterface
|
||||
{
|
||||
/**
|
||||
* Load all the application configuration and bootstrap logic.
|
||||
*
|
||||
* Override this method to add additional bootstrap logic for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function bootstrap(): void;
|
||||
|
||||
/**
|
||||
* Define the console commands for an application.
|
||||
*
|
||||
* @param \Cake\Console\CommandCollection $commands The CommandCollection to add commands into.
|
||||
* @return \Cake\Console\CommandCollection The updated collection.
|
||||
*/
|
||||
public function console(CommandCollection $commands): CommandCollection;
|
||||
}
|
28
vendor/cakephp/core/Container.php
vendored
Normal file
28
vendor/cakephp/core/Container.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 4.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use League\Container\Container as LeagueContainer;
|
||||
|
||||
/**
|
||||
* Dependency Injection container
|
||||
*
|
||||
* Based on the container out of League\Container
|
||||
*/
|
||||
class Container extends LeagueContainer implements ContainerInterface
|
||||
{
|
||||
}
|
45
vendor/cakephp/core/ContainerApplicationInterface.php
vendored
Normal file
45
vendor/cakephp/core/ContainerApplicationInterface.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 4.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
/**
|
||||
* Interface for applications that configure and use a dependency injection container.
|
||||
*/
|
||||
interface ContainerApplicationInterface
|
||||
{
|
||||
/**
|
||||
* Register services to the container
|
||||
*
|
||||
* Registered services can have instances fetched out of the container
|
||||
* using `get()`. Dependencies and parameters will be resolved based
|
||||
* on service definitions.
|
||||
*
|
||||
* @param \Cake\Core\ContainerInterface $container The container to add services to
|
||||
* @return void
|
||||
*/
|
||||
public function services(ContainerInterface $container): void;
|
||||
|
||||
/**
|
||||
* Create a new container and register services.
|
||||
*
|
||||
* This will `register()` services provided by both the application
|
||||
* and any plugins if the application has plugin support.
|
||||
*
|
||||
* @return \Cake\Core\ContainerInterface A populated container
|
||||
*/
|
||||
public function getContainer(): ContainerInterface;
|
||||
}
|
32
vendor/cakephp/core/ContainerInterface.php
vendored
Normal file
32
vendor/cakephp/core/ContainerInterface.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 4.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use League\Container\DefinitionContainerInterface;
|
||||
|
||||
/**
|
||||
* Interface for the Dependency Injection Container in CakePHP applications
|
||||
*
|
||||
* This interface extends the PSR-11 container interface and adds
|
||||
* methods to add services and service providers to the container.
|
||||
*
|
||||
* The methods defined in this interface use the conventions provided
|
||||
* by league/container as that is the library that CakePHP uses.
|
||||
*/
|
||||
interface ContainerInterface extends DefinitionContainerInterface
|
||||
{
|
||||
}
|
156
vendor/cakephp/core/ConventionsTrait.php
vendored
Normal file
156
vendor/cakephp/core/ConventionsTrait.php
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
/**
|
||||
* Provides methods that allow other classes access to conventions based inflections.
|
||||
*/
|
||||
trait ConventionsTrait
|
||||
{
|
||||
/**
|
||||
* Creates a fixture name
|
||||
*
|
||||
* @param string $name Model class name
|
||||
* @return string Singular model key
|
||||
*/
|
||||
protected function _fixtureName(string $name): string
|
||||
{
|
||||
return Inflector::camelize($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the proper entity name (singular) for the specified name
|
||||
*
|
||||
* @param string $name Name
|
||||
* @return string Camelized and plural model name
|
||||
*/
|
||||
protected function _entityName(string $name): string
|
||||
{
|
||||
return Inflector::singularize(Inflector::camelize($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the proper underscored model key for associations
|
||||
*
|
||||
* If the input contains a dot, assume that the right side is the real table name.
|
||||
*
|
||||
* @param string $name Model class name
|
||||
* @return string Singular model key
|
||||
*/
|
||||
protected function _modelKey(string $name): string
|
||||
{
|
||||
[, $name] = pluginSplit($name);
|
||||
|
||||
return Inflector::underscore(Inflector::singularize($name)) . '_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the proper model name from a foreign key
|
||||
*
|
||||
* @param string $key Foreign key
|
||||
* @return string Model name
|
||||
*/
|
||||
protected function _modelNameFromKey(string $key): string
|
||||
{
|
||||
$key = str_replace('_id', '', $key);
|
||||
|
||||
return Inflector::camelize(Inflector::pluralize($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the singular name for use in views.
|
||||
*
|
||||
* @param string $name Name to use
|
||||
* @return string Variable name
|
||||
*/
|
||||
protected function _singularName(string $name): string
|
||||
{
|
||||
return Inflector::variable(Inflector::singularize($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the plural variable name for views
|
||||
*
|
||||
* @param string $name Name to use
|
||||
* @return string Plural name for views
|
||||
*/
|
||||
protected function _variableName(string $name): string
|
||||
{
|
||||
return Inflector::variable($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the singular human name used in views
|
||||
*
|
||||
* @param string $name Controller name
|
||||
* @return string Singular human name
|
||||
*/
|
||||
protected function _singularHumanName(string $name): string
|
||||
{
|
||||
return Inflector::humanize(Inflector::underscore(Inflector::singularize($name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a camelized version of $name
|
||||
*
|
||||
* @param string $name name
|
||||
* @return string Camelized name
|
||||
*/
|
||||
protected function _camelize(string $name): string
|
||||
{
|
||||
return Inflector::camelize($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the plural human name used in views
|
||||
*
|
||||
* @param string $name Controller name
|
||||
* @return string Plural human name
|
||||
*/
|
||||
protected function _pluralHumanName(string $name): string
|
||||
{
|
||||
return Inflector::humanize(Inflector::underscore($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the correct path for a plugin. Scans $pluginPaths for the plugin you want.
|
||||
*
|
||||
* @param string $pluginName Name of the plugin you want ie. DebugKit
|
||||
* @return string path path to the correct plugin.
|
||||
*/
|
||||
protected function _pluginPath(string $pluginName): string
|
||||
{
|
||||
if (Plugin::isLoaded($pluginName)) {
|
||||
return Plugin::path($pluginName);
|
||||
}
|
||||
|
||||
return current(App::path('plugins')) . $pluginName . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return plugin's namespace
|
||||
*
|
||||
* @param string $pluginName Plugin name
|
||||
* @return string Plugin's namespace
|
||||
*/
|
||||
protected function _pluginNamespace(string $pluginName): string
|
||||
{
|
||||
return str_replace('/', '\\', $pluginName);
|
||||
}
|
||||
}
|
123
vendor/cakephp/core/Exception/CakeException.php
vendored
Normal file
123
vendor/cakephp/core/Exception/CakeException.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
use function Cake\Core\deprecationWarning;
|
||||
|
||||
/**
|
||||
* Base class that all CakePHP Exceptions extend.
|
||||
*
|
||||
* @method int getCode() Gets the Exception code.
|
||||
*/
|
||||
class CakeException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Array of attributes that are passed in from the constructor, and
|
||||
* made available in the view when a development error is displayed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_attributes = [];
|
||||
|
||||
/**
|
||||
* Template string that has attributes sprintf()'ed into it.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_messageTemplate = '';
|
||||
|
||||
/**
|
||||
* Array of headers to be passed to {@link \Cake\Http\Response::withHeader()}
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $_responseHeaders;
|
||||
|
||||
/**
|
||||
* Default exception code
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_defaultCode = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Allows you to create exceptions that are treated as framework errors and disabled
|
||||
* when debug mode is off.
|
||||
*
|
||||
* @param array|string $message Either the string of the error message, or an array of attributes
|
||||
* that are made available in the view, and sprintf()'d into Exception::$_messageTemplate
|
||||
* @param int|null $code The error code
|
||||
* @param \Throwable|null $previous the previous exception.
|
||||
*/
|
||||
public function __construct($message = '', ?int $code = null, ?Throwable $previous = null)
|
||||
{
|
||||
if (is_array($message)) {
|
||||
$this->_attributes = $message;
|
||||
$message = vsprintf($this->_messageTemplate, $message);
|
||||
}
|
||||
parent::__construct($message, $code ?? $this->_defaultCode, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the passed in attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->_attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set the response header to be used
|
||||
*
|
||||
* See also {@link \Cake\Http\Response::withHeader()}
|
||||
*
|
||||
* @param array|string|null $header A single header string or an associative
|
||||
* array of "header name" => "header value"
|
||||
* @param string|null $value The header value.
|
||||
* @return array|null
|
||||
* @deprecated 4.2.0 Use `HttpException::setHeaders()` instead. Response headers
|
||||
* should be set for HttpException only.
|
||||
*/
|
||||
public function responseHeader($header = null, $value = null): ?array
|
||||
{
|
||||
if ($header === null) {
|
||||
return $this->_responseHeaders;
|
||||
}
|
||||
|
||||
deprecationWarning(
|
||||
'Setting HTTP response headers from Exception directly is deprecated. ' .
|
||||
'If your exceptions extend Exception, they must now extend HttpException. ' .
|
||||
'You should only set HTTP headers on HttpException instances via the `setHeaders()` method.'
|
||||
);
|
||||
if (is_array($header)) {
|
||||
return $this->_responseHeaders = $header;
|
||||
}
|
||||
|
||||
return $this->_responseHeaders = [$header => $value];
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:disable
|
||||
class_alias(
|
||||
'Cake\Core\Exception\CakeException',
|
||||
'Cake\Core\Exception\Exception'
|
||||
);
|
||||
// phpcs:enable
|
21
vendor/cakephp/core/Exception/Exception.php
vendored
Normal file
21
vendor/cakephp/core/Exception/Exception.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use function Cake\Core\deprecationWarning;
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @since 4.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
deprecationWarning(
|
||||
'Since 4.2.0: Cake\Core\Exception\Exception is deprecated.' .
|
||||
'Use Cake\Core\Exception\CakeException instead.'
|
||||
);
|
||||
class_exists('Cake\Core\Exception\CakeException');
|
26
vendor/cakephp/core/Exception/MissingPluginException.php
vendored
Normal file
26
vendor/cakephp/core/Exception/MissingPluginException.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core\Exception;
|
||||
|
||||
/**
|
||||
* Exception raised when a plugin could not be found
|
||||
*/
|
||||
class MissingPluginException extends CakeException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $_messageTemplate = 'Plugin %s could not be found.';
|
||||
}
|
43
vendor/cakephp/core/HttpApplicationInterface.php
vendored
Normal file
43
vendor/cakephp/core/HttpApplicationInterface.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.5.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Http\MiddlewareQueue;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
/**
|
||||
* An interface defining the methods that the
|
||||
* http server depend on.
|
||||
*/
|
||||
interface HttpApplicationInterface extends RequestHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Load all the application configuration and bootstrap logic.
|
||||
*
|
||||
* Override this method to add additional bootstrap logic for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function bootstrap(): void;
|
||||
|
||||
/**
|
||||
* Define the HTTP middleware layers for an application.
|
||||
*
|
||||
* @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to set in your App Class
|
||||
* @return \Cake\Http\MiddlewareQueue
|
||||
*/
|
||||
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue;
|
||||
}
|
312
vendor/cakephp/core/InstanceConfigTrait.php
vendored
Normal file
312
vendor/cakephp/core/InstanceConfigTrait.php
vendored
Normal file
@ -0,0 +1,312 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Core\Exception\CakeException;
|
||||
use Cake\Utility\Hash;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* A trait for reading and writing instance config
|
||||
*
|
||||
* Implementing objects are expected to declare a `$_defaultConfig` property.
|
||||
*/
|
||||
trait InstanceConfigTrait
|
||||
{
|
||||
/**
|
||||
* Runtime config
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected $_config = [];
|
||||
|
||||
/**
|
||||
* Whether the config property has already been configured with defaults
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_configInitialized = false;
|
||||
|
||||
/**
|
||||
* Sets the config.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* Setting a specific value:
|
||||
*
|
||||
* ```
|
||||
* $this->setConfig('key', $value);
|
||||
* ```
|
||||
*
|
||||
* Setting a nested value:
|
||||
*
|
||||
* ```
|
||||
* $this->setConfig('some.nested.key', $value);
|
||||
* ```
|
||||
*
|
||||
* Updating multiple config settings at the same time:
|
||||
*
|
||||
* ```
|
||||
* $this->setConfig(['one' => 'value', 'another' => 'value']);
|
||||
* ```
|
||||
*
|
||||
* @param array<string, mixed>|string $key The key to set, or a complete array of configs.
|
||||
* @param mixed|null $value The value to set.
|
||||
* @param bool $merge Whether to recursively merge or overwrite existing config, defaults to true.
|
||||
* @return $this
|
||||
* @throws \Cake\Core\Exception\CakeException When trying to set a key that is invalid.
|
||||
*/
|
||||
public function setConfig($key, $value = null, $merge = true)
|
||||
{
|
||||
if (!$this->_configInitialized) {
|
||||
$this->_config = $this->_defaultConfig;
|
||||
$this->_configInitialized = true;
|
||||
}
|
||||
|
||||
$this->_configWrite($key, $value, $merge);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* Reading the whole config:
|
||||
*
|
||||
* ```
|
||||
* $this->getConfig();
|
||||
* ```
|
||||
*
|
||||
* Reading a specific value:
|
||||
*
|
||||
* ```
|
||||
* $this->getConfig('key');
|
||||
* ```
|
||||
*
|
||||
* Reading a nested value:
|
||||
*
|
||||
* ```
|
||||
* $this->getConfig('some.nested.key');
|
||||
* ```
|
||||
*
|
||||
* Reading with default value:
|
||||
*
|
||||
* ```
|
||||
* $this->getConfig('some-key', 'default-value');
|
||||
* ```
|
||||
*
|
||||
* @param string|null $key The key to get or null for the whole config.
|
||||
* @param mixed $default The return value when the key does not exist.
|
||||
* @return mixed Configuration data at the named key or null if the key does not exist.
|
||||
*/
|
||||
public function getConfig(?string $key = null, $default = null)
|
||||
{
|
||||
if (!$this->_configInitialized) {
|
||||
$this->_config = $this->_defaultConfig;
|
||||
$this->_configInitialized = true;
|
||||
}
|
||||
|
||||
$return = $this->_configRead($key);
|
||||
|
||||
return $return ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config for this specific key.
|
||||
*
|
||||
* The config value for this key must exist, it can never be null.
|
||||
*
|
||||
* @param string $key The key to get.
|
||||
* @return mixed Configuration data at the named key
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function getConfigOrFail(string $key)
|
||||
{
|
||||
$config = $this->getConfig($key);
|
||||
if ($config === null) {
|
||||
throw new InvalidArgumentException(sprintf('Expected configuration `%s` not found.', $key));
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge provided config with existing config. Unlike `config()` which does
|
||||
* a recursive merge for nested keys, this method does a simple merge.
|
||||
*
|
||||
* Setting a specific value:
|
||||
*
|
||||
* ```
|
||||
* $this->configShallow('key', $value);
|
||||
* ```
|
||||
*
|
||||
* Setting a nested value:
|
||||
*
|
||||
* ```
|
||||
* $this->configShallow('some.nested.key', $value);
|
||||
* ```
|
||||
*
|
||||
* Updating multiple config settings at the same time:
|
||||
*
|
||||
* ```
|
||||
* $this->configShallow(['one' => 'value', 'another' => 'value']);
|
||||
* ```
|
||||
*
|
||||
* @param array<string, mixed>|string $key The key to set, or a complete array of configs.
|
||||
* @param mixed|null $value The value to set.
|
||||
* @return $this
|
||||
*/
|
||||
public function configShallow($key, $value = null)
|
||||
{
|
||||
if (!$this->_configInitialized) {
|
||||
$this->_config = $this->_defaultConfig;
|
||||
$this->_configInitialized = true;
|
||||
}
|
||||
|
||||
$this->_configWrite($key, $value, 'shallow');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a config key.
|
||||
*
|
||||
* @param string|null $key Key to read.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _configRead(?string $key)
|
||||
{
|
||||
if ($key === null) {
|
||||
return $this->_config;
|
||||
}
|
||||
|
||||
if (strpos($key, '.') === false) {
|
||||
return $this->_config[$key] ?? null;
|
||||
}
|
||||
|
||||
$return = $this->_config;
|
||||
|
||||
foreach (explode('.', $key) as $k) {
|
||||
if (!is_array($return) || !isset($return[$k])) {
|
||||
$return = null;
|
||||
break;
|
||||
}
|
||||
|
||||
$return = $return[$k];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a config key.
|
||||
*
|
||||
* @param array<string, mixed>|string $key Key to write to.
|
||||
* @param mixed $value Value to write.
|
||||
* @param string|bool $merge True to merge recursively, 'shallow' for simple merge,
|
||||
* false to overwrite, defaults to false.
|
||||
* @return void
|
||||
* @throws \Cake\Core\Exception\CakeException if attempting to clobber existing config
|
||||
*/
|
||||
protected function _configWrite($key, $value, $merge = false): void
|
||||
{
|
||||
if (is_string($key) && $value === null) {
|
||||
$this->_configDelete($key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($merge) {
|
||||
$update = is_array($key) ? $key : [$key => $value];
|
||||
if ($merge === 'shallow') {
|
||||
$this->_config = array_merge($this->_config, Hash::expand($update));
|
||||
} else {
|
||||
$this->_config = Hash::merge($this->_config, Hash::expand($update));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($key)) {
|
||||
foreach ($key as $k => $val) {
|
||||
$this->_configWrite($k, $val);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($key, '.') === false) {
|
||||
$this->_config[$key] = $value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update = &$this->_config;
|
||||
$stack = explode('.', $key);
|
||||
|
||||
foreach ($stack as $k) {
|
||||
if (!is_array($update)) {
|
||||
throw new CakeException(sprintf('Cannot set %s value', $key));
|
||||
}
|
||||
|
||||
$update[$k] = $update[$k] ?? [];
|
||||
|
||||
$update = &$update[$k];
|
||||
}
|
||||
|
||||
$update = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single config key.
|
||||
*
|
||||
* @param string $key Key to delete.
|
||||
* @return void
|
||||
* @throws \Cake\Core\Exception\CakeException if attempting to clobber existing config
|
||||
*/
|
||||
protected function _configDelete(string $key): void
|
||||
{
|
||||
if (strpos($key, '.') === false) {
|
||||
unset($this->_config[$key]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update = &$this->_config;
|
||||
$stack = explode('.', $key);
|
||||
$length = count($stack);
|
||||
|
||||
foreach ($stack as $i => $k) {
|
||||
if (!is_array($update)) {
|
||||
throw new CakeException(sprintf('Cannot unset %s value', $key));
|
||||
}
|
||||
|
||||
if (!isset($update[$k])) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($i === $length - 1) {
|
||||
unset($update[$k]);
|
||||
break;
|
||||
}
|
||||
|
||||
$update = &$update[$k];
|
||||
}
|
||||
}
|
||||
}
|
22
vendor/cakephp/core/LICENSE.txt
vendored
Normal file
22
vendor/cakephp/core/LICENSE.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
|
||||
Copyright (c) 2005-2020, Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
416
vendor/cakephp/core/ObjectRegistry.php
vendored
Normal file
416
vendor/cakephp/core/ObjectRegistry.php
vendored
Normal file
@ -0,0 +1,416 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use ArrayIterator;
|
||||
use Cake\Event\EventDispatcherInterface;
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use RuntimeException;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Acts as a registry/factory for objects.
|
||||
*
|
||||
* Provides registry & factory functionality for object types. Used
|
||||
* as a super class for various composition based re-use features in CakePHP.
|
||||
*
|
||||
* Each subclass needs to implement the various abstract methods to complete
|
||||
* the template method load().
|
||||
*
|
||||
* The ObjectRegistry is EventManager aware, but each extending class will need to use
|
||||
* \Cake\Event\EventDispatcherTrait to attach and detach on set and bind
|
||||
*
|
||||
* @see \Cake\Controller\ComponentRegistry
|
||||
* @see \Cake\View\HelperRegistry
|
||||
* @see \Cake\Console\TaskRegistry
|
||||
* @template TObject of object
|
||||
* @template-implements \IteratorAggregate<string, TObject>
|
||||
*/
|
||||
abstract class ObjectRegistry implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Map of loaded objects.
|
||||
*
|
||||
* @var array<object>
|
||||
* @psalm-var array<array-key, TObject>
|
||||
*/
|
||||
protected $_loaded = [];
|
||||
|
||||
/**
|
||||
* Loads/constructs an object instance.
|
||||
*
|
||||
* Will return the instance in the registry if it already exists.
|
||||
* If a subclass provides event support, you can use `$config['enabled'] = false`
|
||||
* to exclude constructed objects from being registered for events.
|
||||
*
|
||||
* Using {@link \Cake\Controller\Component::$components} as an example. You can alias
|
||||
* an object by setting the 'className' key, i.e.,
|
||||
*
|
||||
* ```
|
||||
* protected $components = [
|
||||
* 'Email' => [
|
||||
* 'className' => 'App\Controller\Component\AliasedEmailComponent'
|
||||
* ];
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* All calls to the `Email` component would use `AliasedEmail` instead.
|
||||
*
|
||||
* @param string $name The name/class of the object to load.
|
||||
* @param array<string, mixed> $config Additional settings to use when loading the object.
|
||||
* @return mixed
|
||||
* @psalm-return TObject
|
||||
* @throws \Exception If the class cannot be found.
|
||||
*/
|
||||
public function load(string $name, array $config = [])
|
||||
{
|
||||
if (isset($config['className'])) {
|
||||
$objName = $name;
|
||||
$name = $config['className'];
|
||||
} else {
|
||||
[, $objName] = pluginSplit($name);
|
||||
}
|
||||
|
||||
$loaded = isset($this->_loaded[$objName]);
|
||||
if ($loaded && !empty($config)) {
|
||||
$this->_checkDuplicate($objName, $config);
|
||||
}
|
||||
if ($loaded) {
|
||||
return $this->_loaded[$objName];
|
||||
}
|
||||
|
||||
$className = $name;
|
||||
if (is_string($name)) {
|
||||
$className = $this->_resolveClassName($name);
|
||||
if ($className === null) {
|
||||
[$plugin, $name] = pluginSplit($name);
|
||||
$this->_throwMissingClassError($name, $plugin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-var TObject $instance
|
||||
* @psalm-suppress PossiblyNullArgument
|
||||
**/
|
||||
$instance = $this->_create($className, $objName, $config);
|
||||
$this->_loaded[$objName] = $instance;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for duplicate object loading.
|
||||
*
|
||||
* If a duplicate is being loaded and has different configuration, that is
|
||||
* bad and an exception will be raised.
|
||||
*
|
||||
* An exception is raised, as replacing the object will not update any
|
||||
* references other objects may have. Additionally, simply updating the runtime
|
||||
* configuration is not a good option as we may be missing important constructor
|
||||
* logic dependent on the configuration.
|
||||
*
|
||||
* @param string $name The name of the alias in the registry.
|
||||
* @param array<string, mixed> $config The config data for the new instance.
|
||||
* @return void
|
||||
* @throws \RuntimeException When a duplicate is found.
|
||||
*/
|
||||
protected function _checkDuplicate(string $name, array $config): void
|
||||
{
|
||||
$existing = $this->_loaded[$name];
|
||||
$msg = sprintf('The "%s" alias has already been loaded.', $name);
|
||||
$hasConfig = method_exists($existing, 'getConfig');
|
||||
if (!$hasConfig) {
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
if (empty($config)) {
|
||||
return;
|
||||
}
|
||||
$existingConfig = $existing->getConfig();
|
||||
unset($config['enabled'], $existingConfig['enabled']);
|
||||
|
||||
$failure = null;
|
||||
foreach ($config as $key => $value) {
|
||||
if (!array_key_exists($key, $existingConfig)) {
|
||||
$failure = " The `{$key}` was not defined in the previous configuration data.";
|
||||
break;
|
||||
}
|
||||
if (isset($existingConfig[$key]) && $existingConfig[$key] !== $value) {
|
||||
$failure = sprintf(
|
||||
' The `%s` key has a value of `%s` but previously had a value of `%s`',
|
||||
$key,
|
||||
json_encode($value),
|
||||
json_encode($existingConfig[$key])
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($failure) {
|
||||
throw new RuntimeException($msg . $failure);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should resolve the classname for a given object type.
|
||||
*
|
||||
* @param string $class The class to resolve.
|
||||
* @return string|null The resolved name or null for failure.
|
||||
* @psalm-return class-string|null
|
||||
*/
|
||||
abstract protected function _resolveClassName(string $class): ?string;
|
||||
|
||||
/**
|
||||
* Throw an exception when the requested object name is missing.
|
||||
*
|
||||
* @param string $class The class that is missing.
|
||||
* @param string|null $plugin The plugin $class is missing from.
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
abstract protected function _throwMissingClassError(string $class, ?string $plugin): void;
|
||||
|
||||
/**
|
||||
* Create an instance of a given classname.
|
||||
*
|
||||
* This method should construct and do any other initialization logic
|
||||
* required.
|
||||
*
|
||||
* @param object|string $class The class to build.
|
||||
* @param string $alias The alias of the object.
|
||||
* @param array<string, mixed> $config The Configuration settings for construction
|
||||
* @return object
|
||||
* @psalm-param TObject|string $class
|
||||
* @psalm-return TObject
|
||||
*/
|
||||
abstract protected function _create($class, string $alias, array $config);
|
||||
|
||||
/**
|
||||
* Get the list of loaded objects.
|
||||
*
|
||||
* @return array<string> List of object names.
|
||||
*/
|
||||
public function loaded(): array
|
||||
{
|
||||
return array_keys($this->_loaded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given object is loaded.
|
||||
*
|
||||
* @param string $name The object name to check for.
|
||||
* @return bool True is object is loaded else false.
|
||||
*/
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return isset($this->_loaded[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get loaded object instance.
|
||||
*
|
||||
* @param string $name Name of object.
|
||||
* @return object Object instance.
|
||||
* @throws \RuntimeException If not loaded or found.
|
||||
* @psalm-return TObject
|
||||
*/
|
||||
public function get(string $name)
|
||||
{
|
||||
if (!isset($this->_loaded[$name])) {
|
||||
throw new RuntimeException(sprintf('Unknown object "%s"', $name));
|
||||
}
|
||||
|
||||
return $this->_loaded[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide public read access to the loaded objects
|
||||
*
|
||||
* @param string $name Name of property to read
|
||||
* @return object|null
|
||||
* @psalm-return TObject|null
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
return $this->_loaded[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide isset access to _loaded
|
||||
*
|
||||
* @param string $name Name of object being checked.
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset(string $name): bool
|
||||
{
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an object.
|
||||
*
|
||||
* @param string $name Name of a property to set.
|
||||
* @param object $object Object to set.
|
||||
* @psalm-param TObject $object
|
||||
* @return void
|
||||
*/
|
||||
public function __set(string $name, $object): void
|
||||
{
|
||||
$this->set($name, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets an object.
|
||||
*
|
||||
* @param string $name Name of a property to unset.
|
||||
* @return void
|
||||
*/
|
||||
public function __unset(string $name): void
|
||||
{
|
||||
$this->unload($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes an object array, creates an array that makes lazy loading
|
||||
* easier
|
||||
*
|
||||
* @param array $objects Array of child objects to normalize.
|
||||
* @return array<string, array> Array of normalized objects.
|
||||
*/
|
||||
public function normalizeArray(array $objects): array
|
||||
{
|
||||
$normal = [];
|
||||
foreach ($objects as $i => $objectName) {
|
||||
$config = [];
|
||||
if (!is_int($i)) {
|
||||
$config = (array)$objectName;
|
||||
$objectName = $i;
|
||||
}
|
||||
[, $name] = pluginSplit($objectName);
|
||||
if (isset($config['class'])) {
|
||||
$normal[$name] = $config + ['config' => []];
|
||||
} else {
|
||||
$normal[$name] = ['class' => $objectName, 'config' => $config];
|
||||
}
|
||||
}
|
||||
|
||||
return $normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear loaded instances in the registry.
|
||||
*
|
||||
* If the registry subclass has an event manager, the objects will be detached from events as well.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
foreach (array_keys($this->_loaded) as $name) {
|
||||
$this->unload((string)$name);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object directly into the registry by name.
|
||||
*
|
||||
* If this collection implements events, the passed object will
|
||||
* be attached into the event manager
|
||||
*
|
||||
* @param string $name The name of the object to set in the registry.
|
||||
* @param object $object instance to store in the registry
|
||||
* @return $this
|
||||
* @psalm-param TObject $object
|
||||
*/
|
||||
public function set(string $name, object $object)
|
||||
{
|
||||
[, $objName] = pluginSplit($name);
|
||||
|
||||
// Just call unload if the object was loaded before
|
||||
if (array_key_exists($name, $this->_loaded)) {
|
||||
$this->unload($name);
|
||||
}
|
||||
if ($this instanceof EventDispatcherInterface && $object instanceof EventListenerInterface) {
|
||||
$this->getEventManager()->on($object);
|
||||
}
|
||||
$this->_loaded[$objName] = $object;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an object from the registry.
|
||||
*
|
||||
* If this registry has an event manager, the object will be detached from any events as well.
|
||||
*
|
||||
* @param string $name The name of the object to remove from the registry.
|
||||
* @return $this
|
||||
*/
|
||||
public function unload(string $name)
|
||||
{
|
||||
if (empty($this->_loaded[$name])) {
|
||||
[$plugin, $name] = pluginSplit($name);
|
||||
$this->_throwMissingClassError($name, $plugin);
|
||||
}
|
||||
|
||||
$object = $this->_loaded[$name];
|
||||
if ($this instanceof EventDispatcherInterface && $object instanceof EventListenerInterface) {
|
||||
$this->getEventManager()->off($object);
|
||||
}
|
||||
unset($this->_loaded[$name]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array iterator.
|
||||
*
|
||||
* @return \Traversable
|
||||
* @psalm-return \Traversable<string, TObject>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->_loaded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of loaded objects.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->_loaded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug friendly object properties.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
$properties = get_object_vars($this);
|
||||
if (isset($properties['_loaded'])) {
|
||||
$properties['_loaded'] = array_keys($properties['_loaded']);
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
}
|
136
vendor/cakephp/core/Plugin.php
vendored
Normal file
136
vendor/cakephp/core/Plugin.php
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 2.0.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
/**
|
||||
* Plugin is used to load and locate plugins.
|
||||
*
|
||||
* It also can retrieve plugin paths and load their bootstrap and routes files.
|
||||
*
|
||||
* @link https://book.cakephp.org/4/en/plugins.html
|
||||
*/
|
||||
class Plugin
|
||||
{
|
||||
/**
|
||||
* Holds a list of all loaded plugins and their configuration
|
||||
*
|
||||
* @var \Cake\Core\PluginCollection|null
|
||||
*/
|
||||
protected static $plugins;
|
||||
|
||||
/**
|
||||
* Returns the filesystem path for a plugin
|
||||
*
|
||||
* @param string $name name of the plugin in CamelCase format
|
||||
* @return string path to the plugin folder
|
||||
* @throws \Cake\Core\Exception\MissingPluginException If the folder for plugin was not found
|
||||
* or plugin has not been loaded.
|
||||
*/
|
||||
public static function path(string $name): string
|
||||
{
|
||||
$plugin = static::getCollection()->get($name);
|
||||
|
||||
return $plugin->getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filesystem path for plugin's folder containing class files.
|
||||
*
|
||||
* @param string $name name of the plugin in CamelCase format.
|
||||
* @return string Path to the plugin folder containing class files.
|
||||
* @throws \Cake\Core\Exception\MissingPluginException If plugin has not been loaded.
|
||||
*/
|
||||
public static function classPath(string $name): string
|
||||
{
|
||||
$plugin = static::getCollection()->get($name);
|
||||
|
||||
return $plugin->getClassPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filesystem path for plugin's folder containing config files.
|
||||
*
|
||||
* @param string $name name of the plugin in CamelCase format.
|
||||
* @return string Path to the plugin folder containing config files.
|
||||
* @throws \Cake\Core\Exception\MissingPluginException If plugin has not been loaded.
|
||||
*/
|
||||
public static function configPath(string $name): string
|
||||
{
|
||||
$plugin = static::getCollection()->get($name);
|
||||
|
||||
return $plugin->getConfigPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filesystem path for plugin's folder containing template files.
|
||||
*
|
||||
* @param string $name name of the plugin in CamelCase format.
|
||||
* @return string Path to the plugin folder containing template files.
|
||||
* @throws \Cake\Core\Exception\MissingPluginException If plugin has not been loaded.
|
||||
*/
|
||||
public static function templatePath(string $name): string
|
||||
{
|
||||
$plugin = static::getCollection()->get($name);
|
||||
|
||||
return $plugin->getTemplatePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the plugin $plugin is already loaded.
|
||||
*
|
||||
* @param string $plugin Plugin name.
|
||||
* @return bool
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public static function isLoaded(string $plugin): bool
|
||||
{
|
||||
return static::getCollection()->has($plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of loaded plugins.
|
||||
*
|
||||
* @return array<string> A list of plugins that have been loaded
|
||||
*/
|
||||
public static function loaded(): array
|
||||
{
|
||||
$names = [];
|
||||
foreach (static::getCollection() as $plugin) {
|
||||
$names[] = $plugin->getName();
|
||||
}
|
||||
sort($names);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shared plugin collection.
|
||||
*
|
||||
* This method should generally not be used during application
|
||||
* runtime as plugins should be set during Application startup.
|
||||
*
|
||||
* @return \Cake\Core\PluginCollection
|
||||
*/
|
||||
public static function getCollection(): PluginCollection
|
||||
{
|
||||
if (!isset(static::$plugins)) {
|
||||
static::$plugins = new PluginCollection();
|
||||
}
|
||||
|
||||
return static::$plugins;
|
||||
}
|
||||
}
|
75
vendor/cakephp/core/PluginApplicationInterface.php
vendored
Normal file
75
vendor/cakephp/core/PluginApplicationInterface.php
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 3.6.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Cake\Core;
|
||||
|
||||
use Cake\Console\CommandCollection;
|
||||
use Cake\Event\EventDispatcherInterface;
|
||||
use Cake\Http\MiddlewareQueue;
|
||||
use Cake\Routing\RouteBuilder;
|
||||
|
||||
/**
|
||||
* Interface for Applications that leverage plugins & events.
|
||||
*
|
||||
* Events can be bound to the application event manager during
|
||||
* the application's bootstrap and plugin bootstrap.
|
||||
*/
|
||||
interface PluginApplicationInterface extends EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Add a plugin to the loaded plugin set.
|
||||
*
|
||||
* If the named plugin does not exist, or does not define a Plugin class, an
|
||||
* instance of `Cake\Core\BasePlugin` will be used. This generated class will have
|
||||
* all plugin hooks enabled.
|
||||
*
|
||||
* @param \Cake\Core\PluginInterface|string $name The plugin name or plugin object.
|
||||
* @param array<string, mixed> $config The configuration data for the plugin if using a string for $name
|
||||
* @return $this
|
||||
*/
|
||||
public function addPlugin($name, array $config = []);
|
||||
|
||||
/**
|
||||
* Run bootstrap logic for loaded plugins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function pluginBootstrap(): void;
|
||||
|
||||
/**
|
||||
* Run routes hooks for loaded plugins
|
||||
*
|
||||
* @param \Cake\Routing\RouteBuilder $routes The route builder to use.
|
||||
* @return \Cake\Routing\RouteBuilder
|
||||
*/
|
||||
public function pluginRoutes(RouteBuilder $routes): RouteBuilder;
|
||||
|
||||
/**
|
||||
* Run middleware hooks for plugins
|
||||
*
|
||||
* @param \Cake\Http\MiddlewareQueue $middleware The MiddlewareQueue to use.
|
||||
* @return \Cake\Http\MiddlewareQueue
|
||||
*/
|
||||
public function pluginMiddleware(MiddlewareQueue $middleware): MiddlewareQueue;
|
||||
|
||||
/**
|
||||
* Run console hooks for plugins
|
||||
*
|
||||
* @param \Cake\Console\CommandCollection $commands The CommandCollection to use.
|
||||
* @return \Cake\Console\CommandCollection
|
||||
*/
|
||||
public function pluginConsole(CommandCollection $commands): CommandCollection;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user