mirror of
https://github.com/Icinga/icinga-php-library.git
synced 2025-10-24 08:43:52 +02:00
Version v0.16.0-dev
This commit is contained in:
parent
fc173db4b1
commit
7ed568e5ea
26
asset/css/action-link-and-button-link.less
Normal file
26
asset/css/action-link-and-button-link.less
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
.action-link {
|
||||||
|
color: var(--control-color, @control-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-link {
|
||||||
|
.action-link();
|
||||||
|
.rounded-corners(3px);
|
||||||
|
|
||||||
|
background: var(--default-input-bg, @default-input-bg);
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--default-input-hover-bg, @default-input-hover-bg);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[aria-disabled="true"] {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid var(--control-disabled-color, @control-disabled-color);
|
||||||
|
color: var(--control-disabled-color, @control-disabled-color);
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
.user-select(none);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,18 +2,27 @@
|
|||||||
|
|
||||||
.ball {
|
.ball {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ball-size-xs {
|
.ball-size-xs {
|
||||||
height: 1/3em;
|
height: 1/3em;
|
||||||
width: 1/3em;
|
width: 1/3em;
|
||||||
|
|
||||||
|
i.icon, span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ball-size-s {
|
.ball-size-s {
|
||||||
height: 0.5em;
|
height: 0.5em;
|
||||||
width: 0.5em;
|
width: 0.5em;
|
||||||
|
|
||||||
|
i.icon, span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ball-size-m {
|
.ball-size-m {
|
||||||
@ -21,10 +30,14 @@
|
|||||||
width: 0.75em;
|
width: 0.75em;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
font-size: .75 - @ball-pad * 2;
|
font-size: .75 - @ball-pad * 2;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ball-size-ml {
|
.ball-size-ml {
|
||||||
@ -35,11 +48,15 @@
|
|||||||
i.icon {
|
i.icon {
|
||||||
line-height: 0.3;
|
line-height: 0.3;
|
||||||
|
|
||||||
&:before {
|
&::before {
|
||||||
font-size: 0.8 - @ball-pad * 2;
|
font-size: 0.8 - @ball-pad * 2;
|
||||||
line-height: 1 - @ball-pad * 2;
|
line-height: 1 - @ball-pad * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ball-size-l {
|
.ball-size-l {
|
||||||
@ -47,7 +64,7 @@
|
|||||||
width: 1.5em;
|
width: 1.5em;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before, span {
|
||||||
font-size: 1 - @ball-pad * 2;
|
font-size: 1 - @ball-pad * 2;
|
||||||
line-height: 1.5 - @ball-pad * 2;
|
line-height: 1.5 - @ball-pad * 2;
|
||||||
}
|
}
|
||||||
@ -57,7 +74,7 @@
|
|||||||
width: 2em;
|
width: 2em;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before, span {
|
||||||
line-height: 2 - @ball-pad * 2;
|
line-height: 2 - @ball-pad * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +92,7 @@
|
|||||||
.state-ball {
|
.state-ball {
|
||||||
.ball();
|
.ball();
|
||||||
|
|
||||||
&.state-pending:not(.ball-size-l):not(.ball-size-xl) {
|
&.state-pending:not(.ball-size-l, .ball-size-xl) {
|
||||||
.ball-solid(var(--state-pending, @state-pending));
|
.ball-solid(var(--state-pending, @state-pending));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +101,7 @@
|
|||||||
.ball-outline(var(--state-pending, @state-pending));
|
.ball-outline(var(--state-pending, @state-pending));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.state-up:not(.ball-size-l):not(.ball-size-xl) {
|
&.state-up:not(.ball-size-l, .ball-size-xl) {
|
||||||
.ball-solid(var(--state-up, @state-up));
|
.ball-solid(var(--state-up, @state-up));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +114,7 @@
|
|||||||
.ball-solid(var(--state-down, @state-down));
|
.ball-solid(var(--state-down, @state-down));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.state-ok:not(.ball-size-l):not(.ball-size-xl) {
|
&.state-ok:not(.ball-size-l, .ball-size-xl) {
|
||||||
.ball-solid(var(--state-ok, @state-ok));
|
.ball-solid(var(--state-ok, @state-ok));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +141,6 @@
|
|||||||
|
|
||||||
i.icon {
|
i.icon {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: block;
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
@ -133,13 +149,13 @@
|
|||||||
|
|
||||||
// Specific icon styles
|
// Specific icon styles
|
||||||
&.ball-size-l i {
|
&.ball-size-l i {
|
||||||
&.fa-sitemap:before {
|
&.fa-sitemap::before {
|
||||||
font-size: 8px; // px to ignore browser min font-size
|
font-size: 8px; // px to ignore browser min font-size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ball-size-xl i {
|
&.ball-size-xl i {
|
||||||
&.fa-sitemap:before {
|
&.fa-sitemap::before {
|
||||||
font-size: .857em;
|
font-size: .857em;
|
||||||
line-height: (2 - @ball-pad * 2) / .857;
|
line-height: (2 - @ball-pad * 2) / .857;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
.icinga-controls {
|
.icinga-controls {
|
||||||
.uploaded-files {
|
.uploaded-files {
|
||||||
background-color: @default-input-bg;
|
background-color: var(--default-input-bg, @default-input-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Icinga Web < 2.13
|
||||||
|
.button-link[aria-disabled="true"]:hover {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
form.icinga-form {
|
form.icinga-form {
|
||||||
.uploaded-files {
|
.uploaded-files {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
@ -20,6 +25,14 @@ form.icinga-form {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icinga-controls {
|
||||||
|
.required-hint {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--default-text-color-light, @default-text-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Button styles
|
// Button styles
|
||||||
|
|
||||||
// The `form` selector is only required to overrule the hover effect applied by Icinga Web.
|
// The `form` selector is only required to overrule the hover effect applied by Icinga Web.
|
||||||
@ -86,3 +99,51 @@ form.icinga-form .control-group {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// suggestion-element style
|
||||||
|
form.icinga-form .suggestion-element-group {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
.suggestion-element {
|
||||||
|
border-radius: 0 0.25em 0.25em 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-icingadb {
|
||||||
|
// Icinga DB Web (legacy) table header layout (e.g. in group details)
|
||||||
|
> .controls {
|
||||||
|
> .table-row {
|
||||||
|
display: flex;
|
||||||
|
gap: .5em;
|
||||||
|
|
||||||
|
> .col.title {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icinga DB Web (legacy) object grid layout
|
||||||
|
> .content > .item-table.group-grid:has(.col.title) {
|
||||||
|
grid-template-columns: repeat(auto-fit, 15em) !important;
|
||||||
|
|
||||||
|
> .group-grid-cell {
|
||||||
|
display: revert;
|
||||||
|
|
||||||
|
&::before, &::after {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .col.title {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
> .column-content {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
.text-ellipsis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
i:before {
|
i::before {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,11 +154,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .search-controls > .search-bar .filter-input-area {
|
> .search-controls > .search-bar .filter-input-area {
|
||||||
label {
|
--term-padding-v: 0px;
|
||||||
&::after,
|
|
||||||
input {
|
|
||||||
padding: 0 .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
.empty-state {
|
.empty-state {
|
||||||
color: @empty-state-color;
|
color: var(--empty-state-color, @empty-state-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state-bar {
|
.empty-state-bar {
|
||||||
@ -7,5 +7,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.rounded-corners();
|
.rounded-corners();
|
||||||
background-color: @empty-state-bar-bg;
|
background-color: var(--empty-state-bar-bg, @empty-state-bar-bg);
|
||||||
|
color: var(--default-text-color, @default-text-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Icinga-Icons';
|
font-family: Icinga-Icons;
|
||||||
src: url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.ttf') format('truetype'),
|
src: url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.ttf') format('truetype'),
|
||||||
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.woff') format('woff'),
|
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.woff') format('woff'),
|
||||||
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.svg') format('svg');
|
url('@{iplWebAssets}/font/icinga-icons/fonts/Icinga-Icons.svg') format('svg');
|
||||||
@ -8,9 +8,9 @@
|
|||||||
font-display: block;
|
font-display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
[class^="iicon-"]:before, [class*=" iicon-"]:before {
|
[class^="iicon-"]::before, [class*=" iicon-"]::before {
|
||||||
/* use !important to prevent issues with browser extensions that change fonts */
|
/* use !important to prevent issues with browser extensions that change fonts */
|
||||||
font-family: 'Icinga-Icons';
|
font-family: Icinga-Icons;
|
||||||
speak: none;
|
speak: none;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@ -23,42 +23,42 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.iicon-certificate:before {
|
.iicon-certificate::before {
|
||||||
content: "\e906";
|
content: "\e906";
|
||||||
}
|
}
|
||||||
.iicon-filter-check-circle:before {
|
.iicon-filter-check-circle::before {
|
||||||
content: "\e90b";
|
content: "\e90b";
|
||||||
}
|
}
|
||||||
.iicon-ca-check-circle:before {
|
.iicon-ca-check-circle::before {
|
||||||
content: "\e908";
|
content: "\e908";
|
||||||
}
|
}
|
||||||
.iicon-refresh-cert:before {
|
.iicon-refresh-cert::before {
|
||||||
content: "\e909";
|
content: "\e909";
|
||||||
}
|
}
|
||||||
.iicon-th-list:before {
|
.iicon-th-list::before {
|
||||||
content: "\e90a";
|
content: "\e90a";
|
||||||
}
|
}
|
||||||
.iicon-icinga:before {
|
.iicon-icinga::before {
|
||||||
content: "\e907";
|
content: "\e907";
|
||||||
}
|
}
|
||||||
.iicon-minimal:before,
|
.iicon-minimal::before,
|
||||||
.iicon-list-view-minimal:before {
|
.iicon-list-view-minimal::before {
|
||||||
content: "\e900";
|
content: "\e900";
|
||||||
}
|
}
|
||||||
.iicon-detailed:before,
|
.iicon-detailed::before,
|
||||||
.iicon-list-view-detailed:before {
|
.iicon-list-view-detailed::before {
|
||||||
content: "\e901";
|
content: "\e901";
|
||||||
}
|
}
|
||||||
.iicon-default:before,
|
.iicon-default::before,
|
||||||
.iicon-list-view-default:before {
|
.iicon-list-view-default::before {
|
||||||
content: "\e902";
|
content: "\e902";
|
||||||
}
|
}
|
||||||
.iicon-grid:before {
|
.iicon-grid::before {
|
||||||
content: "\e903";
|
content: "\e903";
|
||||||
}
|
}
|
||||||
.iicon-bracket-open:before {
|
.iicon-bracket-open::before {
|
||||||
content: "\e904";
|
content: "\e904";
|
||||||
}
|
}
|
||||||
.iicon-bracket-close:before {
|
.iicon-bracket-close::before {
|
||||||
content: "\e905";
|
content: "\e905";
|
||||||
}
|
}
|
||||||
|
|||||||
177
asset/css/item-layout.less
Normal file
177
asset/css/item-layout.less
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
// Layout
|
||||||
|
|
||||||
|
.item-layout {
|
||||||
|
// Note that mode specific rules are as strict as possible to avoid conflicts with nested layouts.
|
||||||
|
// Consider an item which contains another item in a different layout mode. Coincidentally, this is
|
||||||
|
// already the case in Icinga DB Web with the last comment flyout.
|
||||||
|
|
||||||
|
.flowing-content(@layout) when (@layout = "default") {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 0;
|
||||||
|
column-gap: .28125em; // calculated width
|
||||||
|
|
||||||
|
> .ellipsize, > .subject { // .subject is compat only, Icinga DB Web used it thoroughly
|
||||||
|
.text-ellipsis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flowing-content(@layout) when (@layout = "detailed") {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
column-gap: .28125em; // calculated width
|
||||||
|
}
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.visual {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: auto;
|
||||||
|
padding: .25em 0;
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
> i.icon {
|
||||||
|
font-size: 1.5em;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: .25em 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> .extended-info {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
p {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-height: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
padding-top: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.minimal-item-layout > .main > header {
|
||||||
|
max-width: 100%;
|
||||||
|
height: 1.5em;
|
||||||
|
|
||||||
|
> .caption {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 1.5em;
|
||||||
|
width: 0;
|
||||||
|
|
||||||
|
&:not(:empty) {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-ellipsis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.default-item-layout > .main {
|
||||||
|
> header {
|
||||||
|
height: 1.5em;
|
||||||
|
|
||||||
|
> .title {
|
||||||
|
.flowing-content("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
> .extended-info {
|
||||||
|
.flowing-content("default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .caption {
|
||||||
|
height: 1.5em;
|
||||||
|
|
||||||
|
.text-ellipsis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.detailed-item-layout > .main {
|
||||||
|
> header {
|
||||||
|
> .title {
|
||||||
|
.flowing-content("detailed");
|
||||||
|
|
||||||
|
word-break: break-word;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .extended-info {
|
||||||
|
.flowing-content("detailed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .caption {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.line-clamp(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style
|
||||||
|
|
||||||
|
.item-layout {
|
||||||
|
color: var(--default-text-color-light, @default-text-color-light);
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
i {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--default-text-color, @default-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
.subject {
|
||||||
|
color: var(--default-text-color, @default-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--default-text-color, @default-text-color);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--link-hover-color, @link-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
.subject {
|
||||||
|
color: var(--link-hover-color, @link-hover-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,82 +4,35 @@
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content:has(> .item-list) > .item-list > .empty-state {
|
||||||
|
.empty-state-bar();
|
||||||
|
}
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
|
|
||||||
.item-list {
|
.item-list {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.list-item {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.main {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
padding: .5em 0;
|
|
||||||
width: 0;
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visual {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caption {
|
|
||||||
height: 3em;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.line-clamp();
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-height: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .empty-state-bar {
|
> .empty-state-bar {
|
||||||
margin: 0 1em;
|
margin: 0 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-list.default-layout .list-item {
|
|
||||||
.title {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: baseline;
|
|
||||||
white-space: nowrap;
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
margin: 0 .28125em; // 0 calculated width
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.subject {
|
|
||||||
.text-ellipsis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls .list-item:not(:last-child) {
|
.controls .list-item:not(:last-child) {
|
||||||
margin-bottom: .5em;
|
margin-bottom: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:not(.dashboard) > .container > .content:has(> .item-list), // compat only, for Icinga Web (See #286)
|
||||||
|
.content:has(> .item-list) {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
|
> .item-list > .list-item {
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
> .item-list > .empty-state {
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -4,79 +4,116 @@ ul.item-table {
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row {
|
.content:has(> .item-table) > .item-table > .empty-state {
|
||||||
color: @default-text-color-light;
|
.empty-state-bar();
|
||||||
|
|
||||||
.title {
|
|
||||||
.subject {
|
|
||||||
color: @default-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @list-item-title-hover-color;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
.item-table li.page-break-follows:not(:last-of-type) {
|
|
||||||
.col {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visual {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
|
|
||||||
.table-row {
|
ul.item-table {
|
||||||
.title {
|
// Grid specific rules
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) repeat(var(--columns), auto);
|
||||||
|
&:has(> li > .visual) {
|
||||||
|
grid-template-columns: auto minmax(0, 1fr) repeat(var(--columns), auto);
|
||||||
|
}
|
||||||
|
|
||||||
.visual {
|
> li {
|
||||||
width: 2.5em;
|
display: contents;
|
||||||
padding: .5em 0;
|
|
||||||
margin-top: -.5em;
|
&.item-layout .main {
|
||||||
margin-bottom: -.5em;
|
// Usually, the parent is flex, but here it's contents. .main is still stretched though,
|
||||||
|
// because it's a grid item with a width of 1fr. But the default-item-layout sets a width
|
||||||
|
// which needs to be overridden.
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-content {
|
.col, &::before, &::after {
|
||||||
flex: 1 1 auto;
|
// The li might get a background on hover. Though, this won't be visible
|
||||||
width: 0;
|
// as it has no box model since we apply display:contents to it.
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> * {
|
:not(.dashboard) > .container > .content:has(> .item-table), // compat only, for Icinga Web (See #286)
|
||||||
.text-ellipsis();
|
.content:has(> .item-table) {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
|
> .item-table > .empty-state {
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul.item-table {
|
||||||
|
// Again, since the li has no box model, it cannot have padding. So the first
|
||||||
|
// and last child need to get the left and right padding respectively.
|
||||||
|
// But we don't want to have a border that spans to the very right or left,
|
||||||
|
// so pseudo elements are required. We could add empty cells instead, but
|
||||||
|
// that would require hard coding the width here, which I'd like to avoid.
|
||||||
|
|
||||||
|
grid-template-columns: ~"auto minmax(0, 1fr) repeat(var(--columns), auto) auto";
|
||||||
|
&:has(> li > .visual) {
|
||||||
|
grid-template-columns: ~"auto auto minmax(0, 1fr) repeat(var(--columns), auto) auto";
|
||||||
|
}
|
||||||
|
|
||||||
|
> li.table-row {
|
||||||
|
&::before, &::after {
|
||||||
|
display: inline-block;
|
||||||
|
content: '\00a0';
|
||||||
|
width: 0;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.col {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.item-table {
|
|
||||||
display: grid;
|
|
||||||
|
|
||||||
> .table-row {
|
|
||||||
.col:not(.title) {
|
|
||||||
display: grid;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.item-table {
|
ul.item-table {
|
||||||
|
// General rules
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
.col {
|
||||||
|
margin-right: 0; // Otherwise background has gaps
|
||||||
|
padding: .5em 1em .5em 0;
|
||||||
|
&:last-child {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for the legacy layout only
|
||||||
|
// TODO: Drop this together with BaseTableRowItem
|
||||||
|
.col.title:has(> .visual) {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> .visual {
|
||||||
|
padding-right: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
.col {
|
||||||
|
border-bottom: 1px solid @list-item-separation-bg;
|
||||||
|
|
||||||
|
&.visual {
|
||||||
|
border-color: @default-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.item-table {
|
div.item-table {
|
||||||
@ -85,11 +122,10 @@ div.item-table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.table-row {
|
@media print {
|
||||||
display: flex;
|
.item-table li.page-break-follows:not(:last-of-type) {
|
||||||
column-gap: 1em;
|
.col {
|
||||||
|
border-bottom: none;
|
||||||
.title {
|
}
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
// Style
|
// Style
|
||||||
|
|
||||||
.list-item {
|
.list-item {
|
||||||
color: @default-text-color-light;
|
|
||||||
|
|
||||||
&:not(:first-child) > .main {
|
&:not(:first-child) > .main {
|
||||||
border-top: 1px solid @list-item-separation-bg;
|
border-top: 1px solid @list-item-separation-bg;
|
||||||
}
|
}
|
||||||
@ -10,40 +8,6 @@
|
|||||||
&:not(:first-child) .visual {
|
&:not(:first-child) .visual {
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.caption {
|
|
||||||
i {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: @default-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
.subject {
|
|
||||||
color: @default-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: @default-text-color;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @list-item-title-hover-color;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
.subject {
|
|
||||||
color: @list-item-title-hover-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
padding-top: .5em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
@ -56,34 +20,10 @@
|
|||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
|
|
||||||
.list-item {
|
.list-item.item-layout {
|
||||||
|
.main,
|
||||||
.visual {
|
.visual {
|
||||||
padding: .5em 0;
|
padding-top: .5em;
|
||||||
width: 2.5em;
|
padding-bottom: .5em;
|
||||||
}
|
|
||||||
|
|
||||||
.caption {
|
|
||||||
p {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-right: 1em;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
> * {
|
|
||||||
font-size: .857em;
|
|
||||||
line-height: 1.5*.857em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,3 +39,8 @@
|
|||||||
.monospace-font() {
|
.monospace-font() {
|
||||||
font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
|
font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-select(@user-select) {
|
||||||
|
-webkit-user-select: @user-select;
|
||||||
|
user-select: @user-select;
|
||||||
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: @schedule-element-fields-disabled-color;
|
color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@
|
|||||||
.monthly, .ordinal:not(.annually) {
|
.monthly, .ordinal:not(.annually) {
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
margin-left: -.5em;
|
margin-left: -.5em;
|
||||||
border: 1px solid @schedule-element-fields-border-color;
|
border: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
|
||||||
.rounded-corners(.75em);
|
.rounded-corners(.75em);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,13 +56,13 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: @schedule-element-fields-disabled-color;
|
color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
|
||||||
background-color: @schedule-element-fields-disabled-bg;
|
background-color: var(--schedule-element-fields-disabled-bg, @schedule-element-fields-disabled-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked + label {
|
input:checked + label {
|
||||||
background: @schedule-element-fields-disabled-selected-bg;
|
background: var(--schedule-element-fields-disabled-selected-bg, @schedule-element-fields-disabled-selected-bg);
|
||||||
color: @schedule-element-fields-disabled-color;
|
color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,11 +75,11 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: .75em 0;
|
padding: .75em 0;
|
||||||
background: @schedule-element-fields-bg;
|
background: var(--schedule-element-fields-bg, @schedule-element-fields-bg);
|
||||||
color: @schedule-element-fields-color;
|
color: var(--schedule-element-fields-color, @schedule-element-fields-color);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @schedule-element-fields-hover-bg;
|
background-color: var(--schedule-element-fields-hover-bg, @schedule-element-fields-hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@ -88,27 +88,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
input:checked + label {
|
input:checked + label {
|
||||||
background-color: @schedule-element-fields-selected-bg;
|
background-color: var(--schedule-element-fields-selected-bg, @schedule-element-fields-selected-bg);
|
||||||
color: @schedule-element-fields-selected-color;
|
color: var(--schedule-element-fields-selected-color, @schedule-element-fields-selected-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked + label:hover {
|
input:checked + label:hover {
|
||||||
background-color: @schedule-element-fields-selected-hover-bg;
|
background-color: var(--schedule-element-fields-selected-hover-bg, @schedule-element-fields-selected-hover-bg);
|
||||||
border-color: @schedule-element-fields-selected-hover-bg;
|
border-color: var(--schedule-element-fields-selected-hover-bg, @schedule-element-fields-selected-hover-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.multiple-fields {
|
&.multiple-fields {
|
||||||
li:not(:last-child) label {
|
li:not(:last-child) label {
|
||||||
border-right: 1px solid @schedule-element-fields-border-color;
|
border-right: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus + label {
|
input:focus + label {
|
||||||
box-shadow: inset 0 0 0 3px @schedule-element-fields-outline-color;
|
box-shadow: inset 0 0 0 3px var(--schedule-element-fields-outline-color, @schedule-element-fields-outline-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked:focus + label {
|
input:checked:focus + label {
|
||||||
box-shadow: inset 0 0 0 3px @schedule-element-fields-selected-outline-color;
|
box-shadow: inset 0 0 0 3px var(--schedule-element-fields-selected-outline-color, @schedule-element-fields-selected-outline-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:focus-within {
|
&:focus-within {
|
||||||
outline: 3px solid @schedule-element-fields-outline-color;
|
outline: 3px solid var(--schedule-element-fields-outline-color, @schedule-element-fields-outline-color);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
input:checked + label:hover {
|
input:checked + label:hover {
|
||||||
background-color: @schedule-element-fields-selected-bg;
|
background-color: var(--schedule-element-fields-selected-bg, @schedule-element-fields-selected-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,20 +145,17 @@
|
|||||||
.note {
|
.note {
|
||||||
display: none;
|
display: none;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
background: @schedule-element-keyboard-note-bg;
|
background: var(--schedule-element-keyboard-note-bg, @schedule-element-keyboard-note-bg);
|
||||||
.rounded-corners(.25em);
|
.rounded-corners(.25em);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .weekly */
|
|
||||||
.weekly { }
|
|
||||||
|
|
||||||
/* .monthly styles */
|
/* .monthly styles */
|
||||||
.monthly {
|
.monthly {
|
||||||
li label {
|
li label {
|
||||||
border-top: 1px solid @schedule-element-fields-border-color;
|
border-top: 1px solid var(--schedule-element-fields-border-color, @schedule-element-fields-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
li:first-child,
|
li:first-child,
|
||||||
@ -189,14 +186,13 @@
|
|||||||
li:nth-child(4n) label {
|
li:nth-child(4n) label {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.toggle-slider-controls {
|
.toggle-slider-controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
column-gap: 1em;
|
column-gap: 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 1em;
|
margin-bottom: -.6em;
|
||||||
margin-bottom: -.6em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +201,6 @@
|
|||||||
padding-top: 0.5625em;
|
padding-top: 0.5625em;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: @schedule-element-fields-disabled-color;
|
color: var(--schedule-element-fields-disabled-color, @schedule-element-fields-disabled-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Submit button styles
|
// Submit button styles
|
||||||
input[type=submit],
|
input[type="submit"],
|
||||||
button[type=submit],
|
button[type="submit"],
|
||||||
button:not([type]) {
|
button:not([type]) {
|
||||||
background: var(--primary-button-bg, @primary-button-bg);
|
background: var(--primary-button-bg, @primary-button-bg);
|
||||||
color: var(--primary-button-color, @primary-button-color);
|
color: var(--primary-button-color, @primary-button-color);
|
||||||
@ -26,20 +26,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hide the submit button, it must exist, but shouldn't be shown to the user
|
// Hide the submit button, it must exist, but shouldn't be shown to the user
|
||||||
input[type=submit][value="hidden"] {
|
input[type="submit"][value="hidden"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left-most search dropdown style
|
// Left-most search dropdown style
|
||||||
button.search-options {
|
button.search-options {
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
color: var(--control-color, @control-color);
|
color: var(--control-color, @control-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
color: var(--control-disabled-color, @control-disabled-color);
|
color: var(--control-disabled-color, @control-disabled-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@
|
|||||||
background-color: var(--search-condition-remove-bg, @search-condition-remove-bg);
|
background-color: var(--search-condition-remove-bg, @search-condition-remove-bg);
|
||||||
color: var(--search-condition-remove-color, @search-condition-remove-color);
|
color: var(--search-condition-remove-color, @search-condition-remove-color);
|
||||||
|
|
||||||
&:after {
|
&::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: .4em;
|
width: .4em;
|
||||||
@ -77,7 +77,7 @@
|
|||||||
.terms > .filter-condition:first-child button {
|
.terms > .filter-condition:first-child button {
|
||||||
border-radius: 0 .4em .4em 0;
|
border-radius: 0 .4em .4em 0;
|
||||||
|
|
||||||
&:before {
|
&::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: .4em;
|
width: .4em;
|
||||||
@ -92,14 +92,14 @@
|
|||||||
border-bottom-right-radius: .4em;
|
border-bottom-right-radius: .4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&::after {
|
||||||
content: none;
|
content: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logical_operator,
|
.logical-operator,
|
||||||
.grouping_operator_open,
|
.grouping-operator-open,
|
||||||
.grouping_operator_close {
|
.grouping-operator-close {
|
||||||
input {
|
input {
|
||||||
.rounded-corners();
|
.rounded-corners();
|
||||||
background-color: var(--search-logical-operator-bg, @search-logical-operator-bg);
|
background-color: var(--search-logical-operator-bg, @search-logical-operator-bg);
|
||||||
@ -108,9 +108,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.operator,
|
.operator,
|
||||||
.logical_operator,
|
.logical-operator,
|
||||||
.grouping_operator_open,
|
.grouping-operator-open,
|
||||||
.grouping_operator_close {
|
.grouping-operator-close {
|
||||||
input {
|
input {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@
|
|||||||
li {
|
li {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
||||||
&:not(:first-of-type):before {
|
&:not(:first-of-type)::before {
|
||||||
display: inline;
|
display: inline;
|
||||||
content: ', ';
|
content: ', ';
|
||||||
}
|
}
|
||||||
@ -193,12 +193,12 @@
|
|||||||
left: ~"calc(-2em - 2px)"; // That's min-width + margin-right of an operator
|
left: ~"calc(-2em - 2px)"; // That's min-width + margin-right of an operator
|
||||||
line-height: 16/12; // 16 (px) desired / default font size (px)
|
line-height: 16/12; // 16 (px) desired / default font size (px)
|
||||||
|
|
||||||
i:before {
|
i::before {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(._hover_delay):hover button {
|
&:not([data-hover-delay]):hover button {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,9 +210,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
&.logical_operator,
|
&.logical-operator,
|
||||||
&.grouping_operator_open,
|
&.grouping-operator-open,
|
||||||
&.grouping_operator_close {
|
&.grouping-operator-close {
|
||||||
margin-left: 1px; // adds up to 2px with the previous term
|
margin-left: 1px; // adds up to 2px with the previous term
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,20 +58,29 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid-reason {
|
.term-input-area {
|
||||||
padding: .25em;
|
.invalid-reason {
|
||||||
.rounded-corners(.25em);
|
padding: .25em;
|
||||||
border: 1px solid black;
|
.rounded-corners(.25em);
|
||||||
font-weight: bold;
|
border: 1px solid black;
|
||||||
background: var(--search-term-invalid-reason-bg, @search-term-invalid-reason-bg);
|
font-weight: bold;
|
||||||
|
background: var(--search-term-invalid-reason-bg, @search-term-invalid-reason-bg);
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: opacity 2s, visibility 2s;
|
transition: opacity 2s, visibility 2s;
|
||||||
&.visible {
|
|
||||||
opacity: 1;
|
&.visible {
|
||||||
visibility: visible;
|
opacity: 1;
|
||||||
transition: none;
|
visibility: visible;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-action {
|
||||||
|
background: var(--search-term-remove-action-bg, @search-term-remove-action-bg);
|
||||||
|
color: var(--search-term-remove-action-color, @search-term-remove-action-color);
|
||||||
|
.rounded-corners(0.25em);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,12 +162,15 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
// Layout
|
// Layout
|
||||||
.search-bar .filter-input-area,
|
.search-bar .filter-input-area,
|
||||||
.term-input-area:not(.vertical) {
|
.term-input-area:not(.vertical) {
|
||||||
|
--term-padding-v: .25em;
|
||||||
|
--term-padding-h: .5em;
|
||||||
|
|
||||||
overflow: auto hidden;
|
overflow: auto hidden;
|
||||||
overflow-x: overlay; // Not invalid, but proprietary feature by chrome/webkit
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: ~"calc(2em + 10px)"; // Search bar height + approximate scrollbar height
|
// input line-height + (input vertical padding * 2) + approximate scrollbar height
|
||||||
|
height: ~"calc(20px + calc(var(--term-padding-v) * 2) + 10px)";
|
||||||
|
|
||||||
// Lets inputs grow based on their contents, Inspired by https://css-tricks.com/auto-growing-inputs-textareas/
|
// Lets inputs grow based on their contents, Inspired by https://css-tricks.com/auto-growing-inputs-textareas/
|
||||||
label {
|
label {
|
||||||
@ -170,7 +182,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
&::after,
|
&::after,
|
||||||
input {
|
input {
|
||||||
width: auto;
|
width: auto;
|
||||||
padding: .25em .5em;
|
padding: var(--term-padding-v) var(--term-padding-h);
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +220,11 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.read-only [data-index] .remove-action {
|
||||||
|
line-height: 20/12;
|
||||||
|
padding: var(--term-padding-v) var(--term-padding-h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.term-input-area.vertical {
|
.term-input-area.vertical {
|
||||||
@ -278,7 +295,6 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
padding-left: 1.5em;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@ -305,6 +321,36 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
top: 85%;
|
top: 85%;
|
||||||
left: .5em;
|
left: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.remove-action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
visibility: visible;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
i.icon {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-action-label {
|
||||||
|
margin-right: auto;
|
||||||
|
.text-ellipsis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input:invalid ~ .remove-action,
|
||||||
|
input.invalid ~ .remove-action {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:hover) .remove-action {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +370,7 @@ fieldset:disabled .term-input-area [data-drag-initiator] {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
li.suggestion-title {
|
li.suggestion-title {
|
||||||
padding: 1.25em .625em 0 .625em;
|
padding: 1.25em .625em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
li.failure-message {
|
li.failure-message {
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
.rounded-corners(0);
|
.rounded-corners(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
color: var(--search-editor-control-color, @search-editor-control-color);
|
color: var(--search-editor-control-color, @search-editor-control-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@
|
|||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&::before {
|
||||||
// The left pointing arrow
|
// The left pointing arrow
|
||||||
border-bottom: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
|
border-bottom: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
|
||||||
border-left: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
|
border-left: 1px solid var(--search-editor-context-menu-border-color, @search-editor-context-menu-border-color);
|
||||||
@ -118,7 +118,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover i.icon:before {
|
&:hover i.icon::before {
|
||||||
.rounded-corners();
|
.rounded-corners();
|
||||||
background: var(--primary-button-bg, @primary-button-bg);
|
background: var(--primary-button-bg, @primary-button-bg);
|
||||||
color: var(--primary-button-color, @primary-button-color);
|
color: var(--primary-button-color, @primary-button-color);
|
||||||
@ -202,7 +202,7 @@
|
|||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@ -227,7 +227,7 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&::before {
|
||||||
// The left pointing arrow
|
// The left pointing arrow
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
@ -246,7 +246,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon:before {
|
i.icon::before {
|
||||||
padding: ((28/18)-1)/2em; // (Container pixels / default font size) - line height / (padding-top,padding-bottom)
|
padding: ((28/18)-1)/2em; // (Container pixels / default font size) - line height / (padding-top,padding-bottom)
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
29
asset/css/suggestion-element.less
Normal file
29
asset/css/suggestion-element.less
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.suggestion-element-group {
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
.suggestion-element,
|
||||||
|
.suggestion-element-icon {
|
||||||
|
line-height: normal;
|
||||||
|
height: 2.25em;
|
||||||
|
padding: 0.5em;
|
||||||
|
background-color: var(--default-input-bg, @default-input-bg);
|
||||||
|
color: var(--default-text-color, @default-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion-element {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 0 0.25em 0.25em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion-element-icon {
|
||||||
|
padding-right: 0;
|
||||||
|
border-radius: 0.25em 0 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border-radius: 0.25em;
|
||||||
|
outline: 3px solid var(--default-input-outline-color, @default-input-outline-color);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,6 +41,12 @@
|
|||||||
@default-text-color-light: fade(@default-text-color, 75%);
|
@default-text-color-light: fade(@default-text-color, 75%);
|
||||||
@default-text-color-inverted: @default-bg;
|
@default-text-color-inverted: @default-bg;
|
||||||
@default-input-bg: #404d72;
|
@default-input-bg: #404d72;
|
||||||
|
@default-input-hover-bg: #434374;
|
||||||
|
@default-input-outline-color: @base-primary-light;
|
||||||
|
@default-remove-bg: @state-critical;
|
||||||
|
@default-remove-color: @default-text-color-inverted;
|
||||||
|
@default-delete-bg: @state-critical;
|
||||||
|
@default-delete-color: @default-text-color-inverted;
|
||||||
|
|
||||||
@state-ok: #44bb77;
|
@state-ok: #44bb77;
|
||||||
@state-up: @state-ok;
|
@state-up: @state-ok;
|
||||||
@ -54,6 +60,7 @@
|
|||||||
@primary-button-color: @default-text-color-inverted;
|
@primary-button-color: @default-text-color-inverted;
|
||||||
@primary-button-bg: @base-primary-bg;
|
@primary-button-bg: @base-primary-bg;
|
||||||
@primary-button-hover-bg: @base-primary-dark;
|
@primary-button-hover-bg: @base-primary-dark;
|
||||||
|
@link-hover-color: @base-primary-color;
|
||||||
|
|
||||||
@search-term-bg: @base-gray;
|
@search-term-bg: @base-gray;
|
||||||
@search-term-color: @default-text-color-inverted;
|
@search-term-color: @default-text-color-inverted;
|
||||||
@ -66,6 +73,8 @@
|
|||||||
@search-term-highlighted-bg: @base-primary-bg;
|
@search-term-highlighted-bg: @base-primary-bg;
|
||||||
@search-term-highlighted-color: @default-text-color-inverted;
|
@search-term-highlighted-color: @default-text-color-inverted;
|
||||||
@search-term-drag-border-color: @base-gray;
|
@search-term-drag-border-color: @base-gray;
|
||||||
|
@search-term-remove-action-bg: @default-remove-bg;
|
||||||
|
@search-term-remove-action-color: @default-remove-color;
|
||||||
|
|
||||||
@search-condition-remove-bg: @state-critical;
|
@search-condition-remove-bg: @state-critical;
|
||||||
@search-condition-remove-color: @default-text-color-inverted;
|
@search-condition-remove-color: @default-text-color-inverted;
|
||||||
@ -115,7 +124,7 @@
|
|||||||
@schedule-element-fields-selected-bg: @primary-button-bg;
|
@schedule-element-fields-selected-bg: @primary-button-bg;
|
||||||
@schedule-element-fields-selected-color: @default-text-color-inverted;
|
@schedule-element-fields-selected-color: @default-text-color-inverted;
|
||||||
@schedule-element-fields-hover-bg: @base-primary-light;
|
@schedule-element-fields-hover-bg: @base-primary-light;
|
||||||
@schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
|
@schedule-element-fields-outline-color: @default-input-outline-color;
|
||||||
@schedule-element-fields-selected-outline-color: fade(#fff, 50%);
|
@schedule-element-fields-selected-outline-color: fade(#fff, 50%);
|
||||||
@schedule-element-fields-selected-hover-bg: @primary-button-hover-bg;
|
@schedule-element-fields-selected-hover-bg: @primary-button-hover-bg;
|
||||||
@schedule-element-fields-disabled-color: @base-gray;
|
@schedule-element-fields-disabled-color: @base-gray;
|
||||||
@ -126,7 +135,7 @@
|
|||||||
@empty-state-color: @base-gray-semilight;
|
@empty-state-color: @base-gray-semilight;
|
||||||
@empty-state-bar-bg: @base-gray-lighter;
|
@empty-state-bar-bg: @base-gray-lighter;
|
||||||
|
|
||||||
@list-item-title-hover-color: @base-primary-color;
|
@list-item-title-hover-color: @link-hover-color;
|
||||||
@list-item-separation-bg: @base-gray-light;
|
@list-item-separation-bg: @base-gray-light;
|
||||||
|
|
||||||
@iplWebLightRules: {
|
@iplWebLightRules: {
|
||||||
@ -143,10 +152,17 @@
|
|||||||
--default-text-color-light: fade(#535353, 75%); // --default-text-color
|
--default-text-color-light: fade(#535353, 75%); // --default-text-color
|
||||||
--default-text-color-inverted: #F5F9FA;
|
--default-text-color-inverted: #F5F9FA;
|
||||||
--default-input-bg: #DEECF1;
|
--default-input-bg: #DEECF1;
|
||||||
|
--default-input-hover-bg: #C0CCCD;
|
||||||
|
--default-input-outline-color: @base-primary-light;
|
||||||
|
--default-remove-bg: var(--base-remove-bg);
|
||||||
|
--default-remove-color: var(--default-text-color-inverted);
|
||||||
|
--default-delete-bg: var(--base-remove-bg);
|
||||||
|
--default-delete-color: var(--default-text-color-inverted);
|
||||||
|
|
||||||
--primary-button-color: var(--default-text-color-inverted);
|
--primary-button-color: var(--default-text-color-inverted);
|
||||||
--primary-button-bg: @primary-button-bg;
|
--primary-button-bg: @primary-button-bg;
|
||||||
--primary-button-hover-bg: @primary-button-hover-bg;
|
--primary-button-hover-bg: @primary-button-hover-bg;
|
||||||
|
--link-hover-color: var(--base-primary-color);
|
||||||
|
|
||||||
--searchbar-bg: var(--default-input-bg);
|
--searchbar-bg: var(--default-input-bg);
|
||||||
--searchbar-scrollbar-bg: var(--base-gray-light);
|
--searchbar-scrollbar-bg: var(--base-gray-light);
|
||||||
@ -162,6 +178,8 @@
|
|||||||
--search-term-highlighted-bg: var(--primary-button-bg);
|
--search-term-highlighted-bg: var(--primary-button-bg);
|
||||||
--search-term-highlighted-color: var(--default-text-color-inverted);
|
--search-term-highlighted-color: var(--default-text-color-inverted);
|
||||||
--search-term-drag-border-color: var(--base-gray);
|
--search-term-drag-border-color: var(--base-gray);
|
||||||
|
--search-term-remove-action-bg: var(--default-remove-bg);
|
||||||
|
--search-term-remove-action-color: var(--default-remove-color);
|
||||||
|
|
||||||
--search-condition-remove-bg: var(--base-remove-bg);
|
--search-condition-remove-bg: var(--base-remove-bg);
|
||||||
--search-condition-remove-color: var(--default-text-color-inverted);
|
--search-condition-remove-color: var(--default-text-color-inverted);
|
||||||
@ -203,7 +221,7 @@
|
|||||||
--schedule-element-fields-selected-bg: var(--primary-button-bg);
|
--schedule-element-fields-selected-bg: var(--primary-button-bg);
|
||||||
--schedule-element-fields-selected-color: var(--default-text-color-inverted);
|
--schedule-element-fields-selected-color: var(--default-text-color-inverted);
|
||||||
--schedule-element-fields-hover-bg: @base-primary-light;
|
--schedule-element-fields-hover-bg: @base-primary-light;
|
||||||
--schedule-element-fields-outline-color: fade(@base-primary-bg, 50%);
|
--schedule-element-fields-outline-color: @default-input-outline-color;
|
||||||
--schedule-element-fields-selected-outline-color: fade(#fff, 50%);
|
--schedule-element-fields-selected-outline-color: fade(#fff, 50%);
|
||||||
--schedule-element-fields-selected-hover-bg: var(--primary-button-hover-bg);
|
--schedule-element-fields-selected-hover-bg: var(--primary-button-hover-bg);
|
||||||
--schedule-element-fields-disabled-color: var(--base-gray);
|
--schedule-element-fields-disabled-color: var(--base-gray);
|
||||||
@ -214,7 +232,7 @@
|
|||||||
--empty-state-color: var(--base-gray-semilight);
|
--empty-state-color: var(--base-gray-semilight);
|
||||||
--empty-state-bar-bg: var(--base-gray-lighter);
|
--empty-state-bar-bg: var(--base-gray-lighter);
|
||||||
|
|
||||||
--list-item-title-hover-color: var(--base-primary-color);
|
--list-item-title-hover-color: var(--link-hover-color);
|
||||||
--list-item-separation-bg: var(--base-gray-light);
|
--list-item-separation-bg: var(--base-gray-light);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
96
asset/js/iterator.js
Normal file
96
asset/js/iterator.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
(function (root, factory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (typeof define === "function" && define.icinga) {
|
||||||
|
define(["exports"], factory);
|
||||||
|
} else {
|
||||||
|
factory(root.icingaIteratorPolyfill = root.icingaIteratorPolyfill || {});
|
||||||
|
}
|
||||||
|
}(self, function (exports) {
|
||||||
|
/**
|
||||||
|
* Polyfill for `Iterator.filter`
|
||||||
|
*
|
||||||
|
* @param {Symbol.iterator} iterator
|
||||||
|
* @param {function} callback
|
||||||
|
* @returns {Generator<*, void, *>}
|
||||||
|
*/
|
||||||
|
function* filter(iterator, callback) {
|
||||||
|
if (typeof iterator.filter === "function") {
|
||||||
|
yield* iterator.filter(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of iterator) {
|
||||||
|
if (callback(item)) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polyfill for `Iterator.find`
|
||||||
|
*
|
||||||
|
* @param {Symbol.iterator} iterator
|
||||||
|
* @param {function} callback
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
function find(iterator, callback) {
|
||||||
|
if (typeof iterator.find === "function") {
|
||||||
|
return iterator.find(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of iterator) {
|
||||||
|
if (callback(item)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polyfill for `Iterator.map`
|
||||||
|
*
|
||||||
|
* @param {Symbol.iterator} iterator
|
||||||
|
* @param {function} callback
|
||||||
|
* @returns {Generator<*, void, *>}
|
||||||
|
*/
|
||||||
|
function* map(iterator, callback) {
|
||||||
|
if (typeof iterator.map === "function") {
|
||||||
|
yield* iterator.map(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of iterator) {
|
||||||
|
yield callback(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the first key in the map whose value satisfies the provided testing function.
|
||||||
|
* @param {Map} map
|
||||||
|
* @param {function} callback Passed arguments are: value, key, map
|
||||||
|
* @returns {*} Returns undefined if no key satisfies the testing function.
|
||||||
|
*/
|
||||||
|
function findKey(map, callback) {
|
||||||
|
for (const key of findKeys(map, callback)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all keys in the map whose value satisfies the provided testing function.
|
||||||
|
* @param {Map} map
|
||||||
|
* @param {function} callback Passed arguments are: value, key, map
|
||||||
|
* @returns {Generator<*, void, *>}
|
||||||
|
*/
|
||||||
|
function* findKeys(map, callback) {
|
||||||
|
for (const [ key, value ] of map) {
|
||||||
|
if (callback(value, key, map)) {
|
||||||
|
yield key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.findKeys = findKeys;
|
||||||
|
exports.findKey = findKey;
|
||||||
|
exports.filter = filter;
|
||||||
|
exports.find = find;
|
||||||
|
exports.map = map;
|
||||||
|
}));
|
||||||
@ -632,7 +632,11 @@ define(["../notjQuery", "Completer"], function ($, Completer) {
|
|||||||
let eventData = { submittedBy: input };
|
let eventData = { submittedBy: input };
|
||||||
if (changeType === 'paste') {
|
if (changeType === 'paste') {
|
||||||
// Ensure that what's pasted is also transmitted as value
|
// Ensure that what's pasted is also transmitted as value
|
||||||
eventData['terms'] = this.termsToQueryString(data['terms']) + this.separator + data['input'];
|
if (data['terms'].length === 0) {
|
||||||
|
eventData['terms'] = data['input'];
|
||||||
|
} else {
|
||||||
|
eventData['terms'] = this.termsToQueryString(data['terms']) + this.separator + data['input'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(this.input.form).trigger('submit', eventData);
|
$(this.input.form).trigger('submit', eventData);
|
||||||
@ -713,7 +717,14 @@ define(["../notjQuery", "Completer"], function ($, Completer) {
|
|||||||
this.input.name = '';
|
this.input.name = '';
|
||||||
|
|
||||||
// Set the hidden input's value, it's what's sent
|
// Set the hidden input's value, it's what's sent
|
||||||
if (event.detail && 'terms' in event.detail) {
|
if (
|
||||||
|
event.detail
|
||||||
|
&& 'terms' in event.detail
|
||||||
|
&& (
|
||||||
|
! ('submittedBy' in event.detail)
|
||||||
|
|| event.detail.submittedBy === this.input
|
||||||
|
)
|
||||||
|
) {
|
||||||
this.termInput.value = event.detail.terms;
|
this.termInput.value = event.detail.terms;
|
||||||
} else {
|
} else {
|
||||||
let renderedTerms = this.termsToQueryString(this.usedTerms);
|
let renderedTerms = this.termsToQueryString(this.usedTerms);
|
||||||
|
|||||||
@ -13,7 +13,7 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
|
|||||||
*
|
*
|
||||||
* @type {{}}
|
* @type {{}}
|
||||||
*/
|
*/
|
||||||
this.negationOperator = { label: '!', search: '!', class: 'logical_operator', type: 'negation_operator' };
|
this.negationOperator = { label: '!', search: '!', class: 'logical-operator', type: 'negation_operator' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported grouping operators
|
* Supported grouping operators
|
||||||
@ -21,8 +21,8 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
|
|||||||
* @type {{close: {}, open: {}}}
|
* @type {{close: {}, open: {}}}
|
||||||
*/
|
*/
|
||||||
this.grouping_operators = {
|
this.grouping_operators = {
|
||||||
open: { label: '(', search: '(', class: 'grouping_operator_open', type: 'grouping_operator' },
|
open: { label: '(', search: '(', class: 'grouping-operator-open', type: 'grouping_operator' },
|
||||||
close: { label: ')', search: ')', class: 'grouping_operator_close', type: 'grouping_operator' }
|
close: { label: ')', search: ')', class: 'grouping-operator-close', type: 'grouping_operator' }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,8 +33,8 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
|
|||||||
* @type {{}[]}
|
* @type {{}[]}
|
||||||
*/
|
*/
|
||||||
this.logical_operators = [
|
this.logical_operators = [
|
||||||
{ label: '&', search: '&', class: 'logical_operator', type: 'logical_operator', default: true },
|
{ label: '&', search: '&', class: 'logical-operator', type: 'logical_operator', default: true },
|
||||||
{ label: '|', search: '|', class: 'logical_operator', type: 'logical_operator' },
|
{ label: '|', search: '|', class: 'logical-operator', type: 'logical_operator' },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -958,7 +958,7 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
|
|||||||
label.dataset.type = termData.type;
|
label.dataset.type = termData.type;
|
||||||
|
|
||||||
if (! termData.class) {
|
if (! termData.class) {
|
||||||
label.classList.add(termData.type);
|
label.classList.add(termData.type.replace('_', '-'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (termData.counterpart >= 0) {
|
if (termData.counterpart >= 0) {
|
||||||
@ -1256,11 +1256,11 @@ define(["../notjQuery", "BaseInput"], function ($, BaseInput) {
|
|||||||
let label = event.currentTarget;
|
let label = event.currentTarget;
|
||||||
|
|
||||||
if (['column', 'operator', 'value'].includes(label.dataset.type)) {
|
if (['column', 'operator', 'value'].includes(label.dataset.type)) {
|
||||||
// This adds a class to delay the remove button. If it's shown instantly upon hover
|
// This adds an attr to delay the remove button. If it's shown instantly upon hover
|
||||||
// it's too easy to accidentally click it instead of the desired grouping operator.
|
// it's too easy to accidentally click it instead of the desired grouping operator.
|
||||||
label.parentNode.classList.add('_hover_delay');
|
label.parentNode.dataset.hoverDelay = "";
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
label.parentNode.classList.remove('_hover_delay');
|
delete label.parentNode.dataset.hoverDelay;
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -187,8 +187,16 @@ define(["../notjQuery", "../vendor/Sortable", "BaseInput"], function ($, Sortabl
|
|||||||
const label = super.renderTerm(termData, termIndex);
|
const label = super.renderTerm(termData, termIndex);
|
||||||
|
|
||||||
if (this.readOnly) {
|
if (this.readOnly) {
|
||||||
|
const removeLabel = this.termContainer.dataset.removeActionLabel;
|
||||||
label.firstChild.readOnly = true;
|
label.firstChild.readOnly = true;
|
||||||
label.appendChild($.render('<i class="icon fa-trash fa"></i>'));
|
label.appendChild(
|
||||||
|
$.render(
|
||||||
|
`<div class="remove-action" title="${ removeLabel }">` +
|
||||||
|
'<i class="icon fa-trash fa"></i>' +
|
||||||
|
`<span class="remove-action-label">${ removeLabel }</span>` +
|
||||||
|
'</div>'
|
||||||
|
)
|
||||||
|
);
|
||||||
label.appendChild($.render('<span class="invalid-reason"></span>'));
|
label.appendChild($.render('<span class="invalid-reason"></span>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +319,12 @@ define(["../notjQuery", "../vendor/Sortable", "BaseInput"], function ($, Sortabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
onButtonClick(event) {
|
onButtonClick(event) {
|
||||||
if (! this.hasSyntaxError()) {
|
// Exchange terms only when an Enter key is pressed while not in the term input.
|
||||||
|
// If the pointerType is not empty, the click event is triggered by clicking the Submit button in the form,
|
||||||
|
// and the default submit event should not be prevented.
|
||||||
|
// The below solution does not work if the click event is triggered by pressing Space while on the Submit button.
|
||||||
|
// In which case the Submit button needs to be clicked again to trigger the form submission.
|
||||||
|
if (! this.hasSyntaxError() && event.pointerType === '') {
|
||||||
let addedTerms = this.exchangeTerm();
|
let addedTerms = this.exchangeTerm();
|
||||||
if (Object.keys(addedTerms).length) {
|
if (Object.keys(addedTerms).length) {
|
||||||
this.togglePlaceholder();
|
this.togglePlaceholder();
|
||||||
|
|||||||
575
composer.lock
generated
575
composer.lock
generated
@ -4,30 +4,29 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "20d4022bc196691807f55d4a47c06474",
|
"content-hash": "7a1692c86b6fc70eaaf43c4bee3673aa",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.9.3",
|
"version": "0.14.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/brick/math.git",
|
"url": "https://github.com/brick/math.git",
|
||||||
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
|
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
|
"url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
|
||||||
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
|
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"php": "^8.2"
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"php-coveralls/php-coveralls": "^2.2",
|
"php-coveralls/php-coveralls": "^2.2",
|
||||||
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
|
"phpstan/phpstan": "2.1.22",
|
||||||
"vimeo/psalm": "4.9.2"
|
"phpunit/phpunit": "^11.5"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -47,101 +46,56 @@
|
|||||||
"arithmetic",
|
"arithmetic",
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"bignum",
|
"bignum",
|
||||||
|
"bignumber",
|
||||||
"brick",
|
"brick",
|
||||||
"math"
|
"decimal",
|
||||||
|
"integer",
|
||||||
|
"math",
|
||||||
|
"mathematics",
|
||||||
|
"rational"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/brick/math/issues",
|
"issues": "https://github.com/brick/math/issues",
|
||||||
"source": "https://github.com/brick/math/tree/0.9.3"
|
"source": "https://github.com/brick/math/tree/0.14.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/BenMorel",
|
"url": "https://github.com/BenMorel",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/brick/math",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-08-15T20:50:18+00:00"
|
"time": "2025-08-29T12:40:03+00:00"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cweagans/composer-patches",
|
|
||||||
"version": "1.7.3",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/cweagans/composer-patches.git",
|
|
||||||
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
|
|
||||||
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"composer-plugin-api": "^1.0 || ^2.0",
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"composer/composer": "~1.0 || ~2.0",
|
|
||||||
"phpunit/phpunit": "~4.6"
|
|
||||||
},
|
|
||||||
"type": "composer-plugin",
|
|
||||||
"extra": {
|
|
||||||
"class": "cweagans\\Composer\\Patches"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"cweagans\\Composer\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"BSD-3-Clause"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Cameron Eagans",
|
|
||||||
"email": "me@cweagans.net"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Provides a way to patch Composer packages.",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/cweagans/composer-patches/issues",
|
|
||||||
"source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
|
|
||||||
},
|
|
||||||
"time": "2022-12-20T22:53:13+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/collections",
|
"name": "doctrine/collections",
|
||||||
"version": "1.8.0",
|
"version": "2.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/collections.git",
|
"url": "https://github.com/doctrine/collections.git",
|
||||||
"reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
|
"reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
|
"url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d",
|
||||||
"reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
|
"reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/deprecations": "^0.5.3 || ^1",
|
"doctrine/deprecations": "^1",
|
||||||
"php": "^7.1.3 || ^8.0"
|
"php": "^8.1",
|
||||||
|
"symfony/polyfill-php84": "^1.30"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9.0 || ^10.0",
|
"doctrine/coding-standard": "^12",
|
||||||
"phpstan/phpstan": "^1.4.8",
|
"ext-json": "*",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
|
"phpstan/phpstan": "^1.8",
|
||||||
"vimeo/psalm": "^4.22"
|
"phpstan/phpstan-phpunit": "^1.0",
|
||||||
|
"phpunit/phpunit": "^10.5"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
|
"Doctrine\\Common\\Collections\\": "src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@ -180,9 +134,23 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/collections/issues",
|
"issues": "https://github.com/doctrine/collections/issues",
|
||||||
"source": "https://github.com/doctrine/collections/tree/1.8.0"
|
"source": "https://github.com/doctrine/collections/tree/2.3.0"
|
||||||
},
|
},
|
||||||
"time": "2022-09-01T20:12:10+00:00"
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/phpdoctrine",
|
||||||
|
"type": "patreon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-22T10:17:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/deprecations",
|
"name": "doctrine/deprecations",
|
||||||
@ -507,16 +475,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/html",
|
"name": "ipl/html",
|
||||||
"version": "v0.8.2",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-html.git",
|
"url": "https://github.com/Icinga/ipl-html.git",
|
||||||
"reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
|
"reference": "0cc98fb660f6c55ed5638d3cbbd8a848c82fd143"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
|
"url": "https://api.github.com/repos/Icinga/ipl-html/zipball/0cc98fb660f6c55ed5638d3cbbd8a848c82fd143",
|
||||||
"reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
|
"reference": "0cc98fb660f6c55ed5638d3cbbd8a848c82fd143",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -524,13 +492,15 @@
|
|||||||
"guzzlehttp/psr7": "^2.5",
|
"guzzlehttp/psr7": "^2.5",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"ipl/validator": ">=0.5.0",
|
"ipl/validator": ">=0.5.0",
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"psr/http-message": "^1.1"
|
"psr/http-message": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"ext-dom": "*",
|
||||||
"ipl/stdlib": "dev-main",
|
"ipl/stdlib": "dev-main",
|
||||||
"ipl/validator": "dev-main"
|
"ipl/validator": "dev-main"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -548,22 +518,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-html/issues",
|
"issues": "https://github.com/Icinga/ipl-html/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
|
"source": "https://github.com/Icinga/ipl-html/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2025-05-21T09:00:03+00:00"
|
"time": "2025-10-20T10:28:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/i18n",
|
"name": "ipl/i18n",
|
||||||
"version": "v0.2.2",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-i18n.git",
|
"url": "https://github.com/Icinga/ipl-i18n.git",
|
||||||
"reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
|
"reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
|
"url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
|
||||||
"reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
|
"reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -575,6 +545,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
@ -599,35 +570,36 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-i18n/issues",
|
"issues": "https://github.com/Icinga/ipl-i18n/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
|
"source": "https://github.com/Icinga/ipl-i18n/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2024-04-08T12:28:47+00:00"
|
"time": "2025-06-12T11:57:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/orm",
|
"name": "ipl/orm",
|
||||||
"version": "v0.6.3",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-orm.git",
|
"url": "https://github.com/Icinga/ipl-orm.git",
|
||||||
"reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
|
"reference": "2a0b72d21e2444501a940975f869297998c6cdfe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
|
"url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/2a0b72d21e2444501a940975f869297998c6cdfe",
|
||||||
"reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
|
"reference": "2a0b72d21e2444501a940975f869297998c6cdfe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ipl/sql": ">=0.7.0",
|
"ipl/sql": ">=0.7.0",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"php": ">=7.2"
|
"php": ">=8.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ext-pdo_sqlite": "*",
|
"ext-pdo_sqlite": "*",
|
||||||
"ipl/sql": "dev-main",
|
"ipl/sql": "dev-main",
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -647,22 +619,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-orm/issues",
|
"issues": "https://github.com/Icinga/ipl-orm/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
|
"source": "https://github.com/Icinga/ipl-orm/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2025-06-12T11:57:55+00:00"
|
"time": "2025-10-15T11:46:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/scheduler",
|
"name": "ipl/scheduler",
|
||||||
"version": "v0.1.2",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-scheduler.git",
|
"url": "https://github.com/Icinga/ipl-scheduler.git",
|
||||||
"reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
|
"reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
|
"url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
|
||||||
"reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
|
"reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -682,6 +654,7 @@
|
|||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
|
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
@ -705,22 +678,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
|
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
|
"source": "https://github.com/Icinga/ipl-scheduler/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2023-08-30T14:14:23+00:00"
|
"time": "2025-06-12T11:58:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/sql",
|
"name": "ipl/sql",
|
||||||
"version": "v0.7.1",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-sql.git",
|
"url": "https://github.com/Icinga/ipl-sql.git",
|
||||||
"reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
|
"reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
|
"url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
|
||||||
"reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
|
"reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -731,6 +704,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -749,22 +723,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-sql/issues",
|
"issues": "https://github.com/Icinga/ipl-sql/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
|
"source": "https://github.com/Icinga/ipl-sql/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2024-06-25T09:55:43+00:00"
|
"time": "2025-10-08T07:03:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/stdlib",
|
"name": "ipl/stdlib",
|
||||||
"version": "v0.14.0",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-stdlib.git",
|
"url": "https://github.com/Icinga/ipl-stdlib.git",
|
||||||
"reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
|
"reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
|
"url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
|
||||||
"reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
|
"reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -772,6 +746,7 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"php": ">=7.2"
|
"php": ">=7.2"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
@ -788,22 +763,22 @@
|
|||||||
"description": "ipl Standard Library",
|
"description": "ipl Standard Library",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
|
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
|
"source": "https://github.com/Icinga/ipl-stdlib/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2024-04-22T08:47:08+00:00"
|
"time": "2025-09-05T12:07:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/validator",
|
"name": "ipl/validator",
|
||||||
"version": "v0.5.0",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-validator.git",
|
"url": "https://github.com/Icinga/ipl-validator.git",
|
||||||
"reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
|
"reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
|
"url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
|
||||||
"reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
|
"reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -812,11 +787,14 @@
|
|||||||
"ipl/i18n": ">=0.2.0",
|
"ipl/i18n": ">=0.2.0",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"php": ">=7.2",
|
"php": ">=7.2",
|
||||||
"psr/http-message": "~1.0"
|
"psr/http-message": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"guzzlehttp/psr7": "^1"
|
"guzzlehttp/psr7": "^1",
|
||||||
|
"ipl/i18n": "dev-main",
|
||||||
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -831,33 +809,33 @@
|
|||||||
"homepage": "https://github.com/Icinga/ipl-validator",
|
"homepage": "https://github.com/Icinga/ipl-validator",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-validator/issues",
|
"issues": "https://github.com/Icinga/ipl-validator/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
|
"source": "https://github.com/Icinga/ipl-validator/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2023-03-21T15:59:00+00:00"
|
"time": "2025-06-12T11:59:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/web",
|
"name": "ipl/web",
|
||||||
"version": "v0.10.2",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-web.git",
|
"url": "https://github.com/Icinga/ipl-web.git",
|
||||||
"reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
|
"reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
|
"url": "https://api.github.com/repos/Icinga/ipl-web/zipball/1fdd7aa977f8da19e17cc4535b023c0760aa442a",
|
||||||
"reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
|
"reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"fortawesome/font-awesome": "^6",
|
"fortawesome/font-awesome": "^6",
|
||||||
"ipl/html": ">=0.8.0",
|
"ipl/html": ">=0.9.0",
|
||||||
"ipl/i18n": ">=0.2.0",
|
"ipl/i18n": ">=0.2.0",
|
||||||
"ipl/orm": ">=0.5.2",
|
"ipl/orm": ">=0.5.2",
|
||||||
"ipl/scheduler": ">=0.1.0",
|
"ipl/scheduler": ">=0.1.0",
|
||||||
"ipl/stdlib": ">=0.13.0",
|
"ipl/stdlib": ">=0.13.0",
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"psr/http-message": "^1.1",
|
"psr/http-message": "^1.1",
|
||||||
"wikimedia/less.php": "^3.2.1"
|
"wikimedia/less.php": "^3.2.1"
|
||||||
},
|
},
|
||||||
@ -869,6 +847,7 @@
|
|||||||
"ipl/stdlib": "dev-main",
|
"ipl/stdlib": "dev-main",
|
||||||
"shardj/zf1-future": "^1.22"
|
"shardj/zf1-future": "^1.22"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -886,9 +865,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-web/issues",
|
"issues": "https://github.com/Icinga/ipl-web/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
|
"source": "https://github.com/Icinga/ipl-web/tree/main"
|
||||||
},
|
},
|
||||||
"time": "2025-03-26T07:49:58+00:00"
|
"time": "2025-10-17T12:11:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/http-factory",
|
"name": "psr/http-factory",
|
||||||
@ -1094,40 +1073,49 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/collection",
|
"name": "ramsey/collection",
|
||||||
"version": "1.1.4",
|
"version": "2.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/collection.git",
|
"url": "https://github.com/ramsey/collection.git",
|
||||||
"reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
|
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
|
"url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||||
"reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
|
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2 || ^8"
|
"php": "^8.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"captainhook/captainhook": "^5.3",
|
"captainhook/plugin-composer": "^5.3",
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
"ergebnis/composer-normalize": "^2.45",
|
||||||
"ergebnis/composer-normalize": "^2.6",
|
"fakerphp/faker": "^1.24",
|
||||||
"fakerphp/faker": "^1.5",
|
"hamcrest/hamcrest-php": "^2.0",
|
||||||
"hamcrest/hamcrest-php": "^2",
|
"jangregor/phpstan-prophecy": "^2.1",
|
||||||
"jangregor/phpstan-prophecy": "^0.8",
|
"mockery/mockery": "^1.6",
|
||||||
"mockery/mockery": "^1.3",
|
"php-parallel-lint/php-console-highlighter": "^1.0",
|
||||||
"phpstan/extension-installer": "^1",
|
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||||
"phpstan/phpstan": "^0.12.32",
|
"phpspec/prophecy-phpunit": "^2.3",
|
||||||
"phpstan/phpstan-mockery": "^0.12.5",
|
"phpstan/extension-installer": "^1.4",
|
||||||
"phpstan/phpstan-phpunit": "^0.12.11",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpunit/phpunit": "^8.5 || ^9",
|
"phpstan/phpstan-mockery": "^2.0",
|
||||||
"psy/psysh": "^0.10.4",
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
"slevomat/coding-standard": "^6.3",
|
"phpunit/phpunit": "^10.5",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"ramsey/coding-standard": "^2.3",
|
||||||
"vimeo/psalm": "^4.4"
|
"ramsey/conventional-commits": "^1.6",
|
||||||
|
"roave/security-advisories": "dev-latest"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"captainhook": {
|
||||||
|
"force-install": true
|
||||||
|
},
|
||||||
|
"ramsey/conventional-commits": {
|
||||||
|
"configFile": "conventional-commits.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Ramsey\\Collection\\": "src/"
|
"Ramsey\\Collection\\": "src/"
|
||||||
@ -1144,7 +1132,7 @@
|
|||||||
"homepage": "https://benramsey.com"
|
"homepage": "https://benramsey.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A PHP 7.2+ library for representing and manipulating collections.",
|
"description": "A PHP library for representing and manipulating collections.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"array",
|
"array",
|
||||||
"collection",
|
"collection",
|
||||||
@ -1155,70 +1143,53 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ramsey/collection/issues",
|
"issues": "https://github.com/ramsey/collection/issues",
|
||||||
"source": "https://github.com/ramsey/collection/tree/1.1.4"
|
"source": "https://github.com/ramsey/collection/tree/2.1.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"time": "2025-03-22T05:38:12+00:00"
|
||||||
{
|
|
||||||
"url": "https://github.com/ramsey",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2021-07-30T00:58:27+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/uuid",
|
"name": "ramsey/uuid",
|
||||||
"version": "4.2.3",
|
"version": "4.9.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/uuid.git",
|
"url": "https://github.com/ramsey/uuid.git",
|
||||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
|
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
"url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
|
||||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"brick/math": "^0.8 || ^0.9",
|
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
|
||||||
"ext-json": "*",
|
"php": "^8.0",
|
||||||
"php": "^7.2 || ^8.0",
|
"ramsey/collection": "^1.2 || ^2.0"
|
||||||
"ramsey/collection": "^1.0",
|
|
||||||
"symfony/polyfill-ctype": "^1.8",
|
|
||||||
"symfony/polyfill-php80": "^1.14"
|
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"rhumsaa/uuid": "self.version"
|
"rhumsaa/uuid": "self.version"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"captainhook/captainhook": "^5.10",
|
"captainhook/captainhook": "^5.25",
|
||||||
"captainhook/plugin-composer": "^5.3",
|
"captainhook/plugin-composer": "^5.3",
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||||
"doctrine/annotations": "^1.8",
|
"ergebnis/composer-normalize": "^2.47",
|
||||||
"ergebnis/composer-normalize": "^2.15",
|
"mockery/mockery": "^1.6",
|
||||||
"mockery/mockery": "^1.3",
|
|
||||||
"moontoast/math": "^1.1",
|
|
||||||
"paragonie/random-lib": "^2",
|
"paragonie/random-lib": "^2",
|
||||||
"php-mock/php-mock": "^2.2",
|
"php-mock/php-mock": "^2.6",
|
||||||
"php-mock/php-mock-mockery": "^1.3",
|
"php-mock/php-mock-mockery": "^1.5",
|
||||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
"php-parallel-lint/php-parallel-lint": "^1.4.0",
|
||||||
"phpbench/phpbench": "^1.0",
|
"phpbench/phpbench": "^1.2.14",
|
||||||
"phpstan/extension-installer": "^1.0",
|
"phpstan/extension-installer": "^1.4",
|
||||||
"phpstan/phpstan": "^0.12",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpstan/phpstan-mockery": "^0.12",
|
"phpstan/phpstan-mockery": "^2.0",
|
||||||
"phpstan/phpstan-phpunit": "^0.12",
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
"phpunit/phpunit": "^8.5 || ^9",
|
"phpunit/phpunit": "^9.6",
|
||||||
"slevomat/coding-standard": "^7.0",
|
"slevomat/coding-standard": "^8.18",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"squizlabs/php_codesniffer": "^3.13"
|
||||||
"vimeo/psalm": "^4.9"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||||
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
|
|
||||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||||
@ -1228,9 +1199,6 @@
|
|||||||
"extra": {
|
"extra": {
|
||||||
"captainhook": {
|
"captainhook": {
|
||||||
"force-install": true
|
"force-install": true
|
||||||
},
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "4.x-dev"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -1253,19 +1221,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ramsey/uuid/issues",
|
"issues": "https://github.com/ramsey/uuid/issues",
|
||||||
"source": "https://github.com/ramsey/uuid/tree/4.2.3"
|
"source": "https://github.com/ramsey/uuid/tree/4.9.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"time": "2025-09-04T20:59:21+00:00"
|
||||||
{
|
|
||||||
"url": "https://github.com/ramsey",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2021-09-25T23:10:38+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "react/event-loop",
|
"name": "react/event-loop",
|
||||||
@ -1471,100 +1429,17 @@
|
|||||||
"time": "2024-12-12T15:39:24+00:00"
|
"time": "2024-12-12T15:39:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-php84",
|
||||||
"version": "v1.33.0",
|
"version": "v1.33.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-php84.git",
|
||||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
|
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
|
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
|
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.2"
|
|
||||||
},
|
|
||||||
"provide": {
|
|
||||||
"ext-ctype": "*"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-ctype": "For best performance"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"thanks": {
|
|
||||||
"url": "https://github.com/symfony/polyfill",
|
|
||||||
"name": "symfony/polyfill"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"bootstrap.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Ctype\\": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Gert de Pagter",
|
|
||||||
"email": "BackEndTea@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "https://symfony.com/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Symfony polyfill for ctype functions",
|
|
||||||
"homepage": "https://symfony.com",
|
|
||||||
"keywords": [
|
|
||||||
"compatibility",
|
|
||||||
"ctype",
|
|
||||||
"polyfill",
|
|
||||||
"portable"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/nicolas-grekas",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2024-09-09T11:45:10+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "symfony/polyfill-php80",
|
|
||||||
"version": "v1.33.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
|
||||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
|
||||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1582,7 +1457,7 @@
|
|||||||
"bootstrap.php"
|
"bootstrap.php"
|
||||||
],
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Polyfill\\Php80\\": ""
|
"Symfony\\Polyfill\\Php84\\": ""
|
||||||
},
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"Resources/stubs"
|
"Resources/stubs"
|
||||||
@ -1593,10 +1468,6 @@
|
|||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Ion Bazan",
|
|
||||||
"email": "ion.bazan@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Nicolas Grekas",
|
"name": "Nicolas Grekas",
|
||||||
"email": "p@tchwork.com"
|
"email": "p@tchwork.com"
|
||||||
@ -1606,7 +1477,7 @@
|
|||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"compatibility",
|
"compatibility",
|
||||||
@ -1615,7 +1486,7 @@
|
|||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
|
"source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1635,32 +1506,32 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-01-02T08:10:11+00:00"
|
"time": "2025-06-24T13:30:11+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "1.11.0",
|
"version": "1.12.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webmozarts/assert.git",
|
"url": "https://github.com/webmozarts/assert.git",
|
||||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
|
"reference": "541057574806f942c94662b817a50f63f7345360"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
"url": "https://api.github.com/repos/webmozarts/assert/zipball/541057574806f942c94662b817a50f63f7345360",
|
||||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
"reference": "541057574806f942c94662b817a50f63f7345360",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
|
"ext-date": "*",
|
||||||
|
"ext-filter": "*",
|
||||||
"php": "^7.2 || ^8.0"
|
"php": "^7.2 || ^8.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"suggest": {
|
||||||
"phpstan/phpstan": "<0.12.20",
|
"ext-intl": "",
|
||||||
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
"ext-simplexml": "",
|
||||||
},
|
"ext-spl": ""
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^8.5.13"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
@ -1691,9 +1562,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/webmozarts/assert/issues",
|
"issues": "https://github.com/webmozarts/assert/issues",
|
||||||
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
|
"source": "https://github.com/webmozarts/assert/tree/1.12.0"
|
||||||
},
|
},
|
||||||
"time": "2022-06-03T18:03:27+00:00"
|
"time": "2025-10-20T12:43:39+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wikimedia/less.php",
|
"name": "wikimedia/less.php",
|
||||||
@ -1772,17 +1643,75 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [
|
||||||
"minimum-stability": "stable",
|
{
|
||||||
"stability-flags": [],
|
"package": "ipl/html",
|
||||||
"prefer-stable": false,
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/i18n",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/orm",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/scheduler",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/sql",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/stdlib",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/validator",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "ipl/web",
|
||||||
|
"version": "dev-main",
|
||||||
|
"alias": "99.x-dev",
|
||||||
|
"alias_normalized": "99.9999999.9999999.9999999-dev"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"stability-flags": {
|
||||||
|
"ipl/html": 20,
|
||||||
|
"ipl/i18n": 20,
|
||||||
|
"ipl/orm": 20,
|
||||||
|
"ipl/scheduler": 20,
|
||||||
|
"ipl/sql": 20,
|
||||||
|
"ipl/stdlib": 20,
|
||||||
|
"ipl/validator": 20,
|
||||||
|
"ipl/web": 20
|
||||||
|
},
|
||||||
|
"prefer-stable": true,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=7.2"
|
"php": ">=7.2"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.2.9"
|
"php": "8.2"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|||||||
7
vendor/autoload.php
vendored
7
vendor/autoload.php
vendored
@ -14,12 +14,9 @@ if (PHP_VERSION_ID < 50600) {
|
|||||||
echo $err;
|
echo $err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trigger_error(
|
throw new RuntimeException($err);
|
||||||
$err,
|
|
||||||
E_USER_ERROR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once __DIR__ . '/composer/autoload_real.php';
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
return ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474::getLoader();
|
return ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa::getLoader();
|
||||||
|
|||||||
14
vendor/brick/math/composer.json
vendored
14
vendor/brick/math/composer.json
vendored
@ -5,22 +5,26 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"Brick",
|
"Brick",
|
||||||
"Math",
|
"Math",
|
||||||
|
"Mathematics",
|
||||||
"Arbitrary-precision",
|
"Arbitrary-precision",
|
||||||
"Arithmetic",
|
"Arithmetic",
|
||||||
"BigInteger",
|
"BigInteger",
|
||||||
"BigDecimal",
|
"BigDecimal",
|
||||||
"BigRational",
|
"BigRational",
|
||||||
"Bignum"
|
"BigNumber",
|
||||||
|
"Bignum",
|
||||||
|
"Decimal",
|
||||||
|
"Rational",
|
||||||
|
"Integer"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1 || ^8.0",
|
"php": "^8.2"
|
||||||
"ext-json": "*"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
|
"phpunit/phpunit": "^11.5",
|
||||||
"php-coveralls/php-coveralls": "^2.2",
|
"php-coveralls/php-coveralls": "^2.2",
|
||||||
"vimeo/psalm": "4.9.2"
|
"phpstan/phpstan": "2.1.22"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|||||||
347
vendor/brick/math/src/BigDecimal.php
vendored
347
vendor/brick/math/src/BigDecimal.php
vendored
@ -8,13 +8,13 @@ use Brick\Math\Exception\DivisionByZeroException;
|
|||||||
use Brick\Math\Exception\MathException;
|
use Brick\Math\Exception\MathException;
|
||||||
use Brick\Math\Exception\NegativeNumberException;
|
use Brick\Math\Exception\NegativeNumberException;
|
||||||
use Brick\Math\Internal\Calculator;
|
use Brick\Math\Internal\Calculator;
|
||||||
|
use Brick\Math\Internal\CalculatorRegistry;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable, arbitrary-precision signed decimal numbers.
|
* Immutable, arbitrary-precision signed decimal numbers.
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
final class BigDecimal extends BigNumber
|
final readonly class BigDecimal extends BigNumber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The unscaled value of this decimal number.
|
* The unscaled value of this decimal number.
|
||||||
@ -22,25 +22,23 @@ final class BigDecimal extends BigNumber
|
|||||||
* This is a string of digits with an optional leading minus sign.
|
* This is a string of digits with an optional leading minus sign.
|
||||||
* No leading zero must be present.
|
* No leading zero must be present.
|
||||||
* No leading minus sign must be present if the value is 0.
|
* No leading minus sign must be present if the value is 0.
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $value;
|
private string $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scale (number of digits after the decimal point) of this decimal number.
|
* The scale (number of digits after the decimal point) of this decimal number.
|
||||||
*
|
*
|
||||||
* This must be zero or more.
|
* This must be zero or more.
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
*/
|
||||||
private $scale;
|
private int $scale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected constructor. Use a factory method to obtain an instance.
|
* Protected constructor. Use a factory method to obtain an instance.
|
||||||
*
|
*
|
||||||
* @param string $value The unscaled value, validated.
|
* @param string $value The unscaled value, validated.
|
||||||
* @param int $scale The scale, validated.
|
* @param int $scale The scale, validated.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
protected function __construct(string $value, int $scale = 0)
|
protected function __construct(string $value, int $scale = 0)
|
||||||
{
|
{
|
||||||
@ -48,20 +46,10 @@ final class BigDecimal extends BigNumber
|
|||||||
$this->scale = $scale;
|
$this->scale = $scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* Creates a BigDecimal of the given value.
|
protected static function from(BigNumber $number): static
|
||||||
*
|
|
||||||
* @param BigNumber|int|float|string $value
|
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*
|
|
||||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
|
||||||
public static function of($value) : BigNumber
|
|
||||||
{
|
{
|
||||||
return parent::of($value)->toBigDecimal();
|
return $number->toBigDecimal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,36 +58,33 @@ final class BigDecimal extends BigNumber
|
|||||||
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
|
* 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 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.
|
* @param int $scale The scale of the number. If negative, the scale will be set to zero
|
||||||
|
* and the unscaled value will be adjusted accordingly.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the scale is negative.
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal
|
public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
|
||||||
{
|
{
|
||||||
|
$value = (string) BigInteger::of($value);
|
||||||
|
|
||||||
if ($scale < 0) {
|
if ($scale < 0) {
|
||||||
throw new \InvalidArgumentException('The scale cannot be negative.');
|
if ($value !== '0') {
|
||||||
|
$value .= \str_repeat('0', -$scale);
|
||||||
|
}
|
||||||
|
$scale = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BigDecimal((string) BigInteger::of($value), $scale);
|
return new BigDecimal($value, $scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a BigDecimal representing zero, with a scale of zero.
|
* Returns a BigDecimal representing zero, with a scale of zero.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function zero() : BigDecimal
|
public static function zero() : BigDecimal
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigDecimal|null $zero */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigDecimal|null $zero
|
|
||||||
*/
|
|
||||||
static $zero;
|
static $zero;
|
||||||
|
|
||||||
if ($zero === null) {
|
if ($zero === null) {
|
||||||
@ -112,16 +97,11 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigDecimal representing one, with a scale of zero.
|
* Returns a BigDecimal representing one, with a scale of zero.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function one() : BigDecimal
|
public static function one() : BigDecimal
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigDecimal|null $one */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigDecimal|null $one
|
|
||||||
*/
|
|
||||||
static $one;
|
static $one;
|
||||||
|
|
||||||
if ($one === null) {
|
if ($one === null) {
|
||||||
@ -134,16 +114,11 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigDecimal representing ten, with a scale of zero.
|
* Returns a BigDecimal representing ten, with a scale of zero.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function ten() : BigDecimal
|
public static function ten() : BigDecimal
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigDecimal|null $ten */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigDecimal|null $ten
|
|
||||||
*/
|
|
||||||
static $ten;
|
static $ten;
|
||||||
|
|
||||||
if ($ten === null) {
|
if ($ten === null) {
|
||||||
@ -160,11 +135,11 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function plus($that) : BigDecimal
|
public function plus(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -178,7 +153,7 @@ final class BigDecimal extends BigNumber
|
|||||||
|
|
||||||
[$a, $b] = $this->scaleValues($this, $that);
|
[$a, $b] = $this->scaleValues($this, $that);
|
||||||
|
|
||||||
$value = Calculator::get()->add($a, $b);
|
$value = CalculatorRegistry::get()->add($a, $b);
|
||||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||||
|
|
||||||
return new BigDecimal($value, $scale);
|
return new BigDecimal($value, $scale);
|
||||||
@ -191,11 +166,11 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function minus($that) : BigDecimal
|
public function minus(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -205,7 +180,7 @@ final class BigDecimal extends BigNumber
|
|||||||
|
|
||||||
[$a, $b] = $this->scaleValues($this, $that);
|
[$a, $b] = $this->scaleValues($this, $that);
|
||||||
|
|
||||||
$value = Calculator::get()->sub($a, $b);
|
$value = CalculatorRegistry::get()->sub($a, $b);
|
||||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||||
|
|
||||||
return new BigDecimal($value, $scale);
|
return new BigDecimal($value, $scale);
|
||||||
@ -218,11 +193,11 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function multipliedBy($that) : BigDecimal
|
public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -234,7 +209,7 @@ final class BigDecimal extends BigNumber
|
|||||||
return $that;
|
return $that;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->mul($this->value, $that->value);
|
$value = CalculatorRegistry::get()->mul($this->value, $that->value);
|
||||||
$scale = $this->scale + $that->scale;
|
$scale = $this->scale + $that->scale;
|
||||||
|
|
||||||
return new BigDecimal($value, $scale);
|
return new BigDecimal($value, $scale);
|
||||||
@ -245,14 +220,14 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor.
|
* @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|null $scale The desired scale, or null to use the scale of this number.
|
||||||
* @param int $roundingMode An optional rounding mode.
|
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
|
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
|
||||||
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -273,7 +248,7 @@ final class BigDecimal extends BigNumber
|
|||||||
$p = $this->valueWithMinScale($that->scale + $scale);
|
$p = $this->valueWithMinScale($that->scale + $scale);
|
||||||
$q = $that->valueWithMinScale($this->scale - $scale);
|
$q = $that->valueWithMinScale($this->scale - $scale);
|
||||||
|
|
||||||
$result = Calculator::get()->divRound($p, $q, $roundingMode);
|
$result = CalculatorRegistry::get()->divRound($p, $q, $roundingMode);
|
||||||
|
|
||||||
return new BigDecimal($result, $scale);
|
return new BigDecimal($result, $scale);
|
||||||
}
|
}
|
||||||
@ -285,12 +260,12 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
|
* @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.
|
* or the result yields an infinite number of digits.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function exactlyDividedBy($that) : BigDecimal
|
public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -303,7 +278,7 @@ final class BigDecimal extends BigNumber
|
|||||||
$d = \rtrim($b, '0');
|
$d = \rtrim($b, '0');
|
||||||
$scale = \strlen($b) - \strlen($d);
|
$scale = \strlen($b) - \strlen($d);
|
||||||
|
|
||||||
$calculator = Calculator::get();
|
$calculator = CalculatorRegistry::get();
|
||||||
|
|
||||||
foreach ([5, 2] as $prime) {
|
foreach ([5, 2] as $prime) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -321,16 +296,36 @@ final class BigDecimal extends BigNumber
|
|||||||
return $this->dividedBy($that, $scale)->stripTrailingZeros();
|
return $this->dividedBy($that, $scale)->stripTrailingZeros();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits (clamps) this number between the given minimum and maximum values.
|
||||||
|
*
|
||||||
|
* If the number is lower than $min, returns a copy of $min.
|
||||||
|
* If the number is greater than $max, returns a copy of $max.
|
||||||
|
* Otherwise, returns this number unchanged.
|
||||||
|
*
|
||||||
|
* @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigDecimal.
|
||||||
|
* @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigDecimal.
|
||||||
|
*
|
||||||
|
* @throws MathException If min/max are not convertible to a BigDecimal.
|
||||||
|
*/
|
||||||
|
public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigDecimal
|
||||||
|
{
|
||||||
|
if ($this->isLessThan($min)) {
|
||||||
|
return BigDecimal::of($min);
|
||||||
|
} elseif ($this->isGreaterThan($max)) {
|
||||||
|
return BigDecimal::of($max);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns this number exponentiated to the given value.
|
* Returns this number exponentiated to the given value.
|
||||||
*
|
*
|
||||||
* The result has a scale of `$this->scale * $exponent`.
|
* The result has a scale of `$this->scale * $exponent`.
|
||||||
*
|
*
|
||||||
* @param int $exponent The exponent.
|
|
||||||
*
|
|
||||||
* @return BigDecimal The result.
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function power(int $exponent) : BigDecimal
|
public function power(int $exponent) : BigDecimal
|
||||||
{
|
{
|
||||||
@ -350,21 +345,21 @@ final class BigDecimal extends BigNumber
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
|
return new BigDecimal(CalculatorRegistry::get()->pow($this->value, $exponent), $this->scale * $exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the quotient of the division of this number by this given one.
|
* Returns the quotient of the division of this number by the given one.
|
||||||
*
|
*
|
||||||
* The quotient has a scale of `0`.
|
* The quotient has a scale of `0`.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The quotient.
|
|
||||||
*
|
|
||||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotient($that) : BigDecimal
|
public function quotient(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -375,23 +370,23 @@ final class BigDecimal extends BigNumber
|
|||||||
$p = $this->valueWithMinScale($that->scale);
|
$p = $this->valueWithMinScale($that->scale);
|
||||||
$q = $that->valueWithMinScale($this->scale);
|
$q = $that->valueWithMinScale($this->scale);
|
||||||
|
|
||||||
$quotient = Calculator::get()->divQ($p, $q);
|
$quotient = CalculatorRegistry::get()->divQ($p, $q);
|
||||||
|
|
||||||
return new BigDecimal($quotient, 0);
|
return new BigDecimal($quotient, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remainder of the division of this number by this given one.
|
* Returns the remainder of the division of this number by the given one.
|
||||||
*
|
*
|
||||||
* The remainder has a scale of `max($this->scale, $that->scale)`.
|
* 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.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The remainder.
|
|
||||||
*
|
|
||||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function remainder($that) : BigDecimal
|
public function remainder(BigNumber|int|float|string $that) : BigDecimal
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -402,7 +397,7 @@ final class BigDecimal extends BigNumber
|
|||||||
$p = $this->valueWithMinScale($that->scale);
|
$p = $this->valueWithMinScale($that->scale);
|
||||||
$q = $that->valueWithMinScale($this->scale);
|
$q = $that->valueWithMinScale($this->scale);
|
||||||
|
|
||||||
$remainder = Calculator::get()->divR($p, $q);
|
$remainder = CalculatorRegistry::get()->divR($p, $q);
|
||||||
|
|
||||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||||
|
|
||||||
@ -416,11 +411,13 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal[] An array containing the quotient and the remainder.
|
* @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder.
|
||||||
*
|
*
|
||||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotientAndRemainder($that) : array
|
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
|
||||||
{
|
{
|
||||||
$that = BigDecimal::of($that);
|
$that = BigDecimal::of($that);
|
||||||
|
|
||||||
@ -431,7 +428,7 @@ final class BigDecimal extends BigNumber
|
|||||||
$p = $this->valueWithMinScale($that->scale);
|
$p = $this->valueWithMinScale($that->scale);
|
||||||
$q = $that->valueWithMinScale($this->scale);
|
$q = $that->valueWithMinScale($this->scale);
|
||||||
|
|
||||||
[$quotient, $remainder] = Calculator::get()->divQR($p, $q);
|
[$quotient, $remainder] = CalculatorRegistry::get()->divQR($p, $q);
|
||||||
|
|
||||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||||
|
|
||||||
@ -444,12 +441,10 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the square root of this number, rounded down to the given number of decimals.
|
* Returns the square root of this number, rounded down to the given number of decimals.
|
||||||
*
|
*
|
||||||
* @param int $scale
|
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the scale is negative.
|
* @throws \InvalidArgumentException If the scale is negative.
|
||||||
* @throws NegativeNumberException If this number is negative.
|
* @throws NegativeNumberException If this number is negative.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function sqrt(int $scale) : BigDecimal
|
public function sqrt(int $scale) : BigDecimal
|
||||||
{
|
{
|
||||||
@ -481,7 +476,7 @@ final class BigDecimal extends BigNumber
|
|||||||
$value = \substr($value, 0, $addDigits);
|
$value = \substr($value, 0, $addDigits);
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->sqrt($value);
|
$value = CalculatorRegistry::get()->sqrt($value);
|
||||||
|
|
||||||
return new BigDecimal($value, $scale);
|
return new BigDecimal($value, $scale);
|
||||||
}
|
}
|
||||||
@ -489,9 +484,7 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
|
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
|
||||||
*
|
*
|
||||||
* @param int $n
|
* @pure
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*/
|
*/
|
||||||
public function withPointMovedLeft(int $n) : BigDecimal
|
public function withPointMovedLeft(int $n) : BigDecimal
|
||||||
{
|
{
|
||||||
@ -509,9 +502,7 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
|
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
|
||||||
*
|
*
|
||||||
* @param int $n
|
* @pure
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*/
|
*/
|
||||||
public function withPointMovedRight(int $n) : BigDecimal
|
public function withPointMovedRight(int $n) : BigDecimal
|
||||||
{
|
{
|
||||||
@ -539,7 +530,7 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function stripTrailingZeros() : BigDecimal
|
public function stripTrailingZeros() : BigDecimal
|
||||||
{
|
{
|
||||||
@ -572,7 +563,7 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the absolute value of this number.
|
* Returns the absolute value of this number.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function abs() : BigDecimal
|
public function abs() : BigDecimal
|
||||||
{
|
{
|
||||||
@ -582,17 +573,15 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the negated value of this number.
|
* Returns the negated value of this number.
|
||||||
*
|
*
|
||||||
* @return BigDecimal
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function negated() : BigDecimal
|
public function negated() : BigDecimal
|
||||||
{
|
{
|
||||||
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
|
return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function compareTo(BigNumber|int|float|string $that) : int
|
||||||
*/
|
|
||||||
public function compareTo($that) : int
|
|
||||||
{
|
{
|
||||||
$that = BigNumber::of($that);
|
$that = BigNumber::of($that);
|
||||||
|
|
||||||
@ -603,42 +592,69 @@ final class BigDecimal extends BigNumber
|
|||||||
if ($that instanceof BigDecimal) {
|
if ($that instanceof BigDecimal) {
|
||||||
[$a, $b] = $this->scaleValues($this, $that);
|
[$a, $b] = $this->scaleValues($this, $that);
|
||||||
|
|
||||||
return Calculator::get()->cmp($a, $b);
|
return CalculatorRegistry::get()->cmp($a, $b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return - $that->compareTo($this);
|
return - $that->compareTo($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getSign() : int
|
public function getSign() : int
|
||||||
{
|
{
|
||||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getUnscaledValue() : BigInteger
|
public function getUnscaledValue() : BigInteger
|
||||||
{
|
{
|
||||||
return BigInteger::create($this->value);
|
return self::newBigInteger($this->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getScale() : int
|
public function getScale() : int
|
||||||
{
|
{
|
||||||
return $this->scale;
|
return $this->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of significant digits in the number.
|
||||||
|
*
|
||||||
|
* This is the number of digits to both sides of the decimal point, stripped of leading zeros.
|
||||||
|
* The sign has no impact on the result.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* 0 => 0
|
||||||
|
* 0.0 => 0
|
||||||
|
* 123 => 3
|
||||||
|
* 123.456 => 6
|
||||||
|
* 0.00123 => 3
|
||||||
|
* 0.0012300 => 5
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
*/
|
||||||
|
public function getPrecision(): int
|
||||||
|
{
|
||||||
|
$value = $this->value;
|
||||||
|
|
||||||
|
if ($value === '0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = \strlen($value);
|
||||||
|
|
||||||
|
return ($value[0] === '-') ? $length - 1 : $length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representing the integral part of this decimal number.
|
* Returns a string representing the integral part of this decimal number.
|
||||||
*
|
*
|
||||||
* Example: `-123.456` => `-123`.
|
* Example: `-123.456` => `-123`.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getIntegralPart() : string
|
public function getIntegralPart() : string
|
||||||
{
|
{
|
||||||
@ -658,7 +674,7 @@ final class BigDecimal extends BigNumber
|
|||||||
*
|
*
|
||||||
* Examples: `-123.456` => '456', `123` => ''.
|
* Examples: `-123.456` => '456', `123` => ''.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getFractionalPart() : string
|
public function getFractionalPart() : string
|
||||||
{
|
{
|
||||||
@ -674,46 +690,38 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns whether this decimal number has a non-zero fractional part.
|
* Returns whether this decimal number has a non-zero fractional part.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function hasNonZeroFractionalPart() : bool
|
public function hasNonZeroFractionalPart() : bool
|
||||||
{
|
{
|
||||||
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigInteger() : BigInteger
|
public function toBigInteger() : BigInteger
|
||||||
{
|
{
|
||||||
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
|
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
|
||||||
|
|
||||||
return BigInteger::create($zeroScaleDecimal->value);
|
return self::newBigInteger($zeroScaleDecimal->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigDecimal() : BigDecimal
|
public function toBigDecimal() : BigDecimal
|
||||||
{
|
{
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigRational() : BigRational
|
public function toBigRational() : BigRational
|
||||||
{
|
{
|
||||||
$numerator = BigInteger::create($this->value);
|
$numerator = self::newBigInteger($this->value);
|
||||||
$denominator = BigInteger::create('1' . \str_repeat('0', $this->scale));
|
$denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
|
||||||
|
|
||||||
return BigRational::create($numerator, $denominator, false);
|
return self::newBigRational($numerator, $denominator, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||||
*/
|
|
||||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
|
||||||
{
|
{
|
||||||
if ($scale === $this->scale) {
|
if ($scale === $this->scale) {
|
||||||
return $this;
|
return $this;
|
||||||
@ -722,33 +730,32 @@ final class BigDecimal extends BigNumber
|
|||||||
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toInt() : int
|
public function toInt() : int
|
||||||
{
|
{
|
||||||
return $this->toBigInteger()->toInt();
|
return $this->toBigInteger()->toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toFloat() : float
|
public function toFloat() : float
|
||||||
{
|
{
|
||||||
return (float) (string) $this;
|
return (float) (string) $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* @return numeric-string
|
||||||
*/
|
*/
|
||||||
|
#[Override]
|
||||||
public function __toString() : string
|
public function __toString() : string
|
||||||
{
|
{
|
||||||
if ($this->scale === 0) {
|
if ($this->scale === 0) {
|
||||||
|
/** @var numeric-string */
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||||
|
|
||||||
|
/** @phpstan-ignore return.type */
|
||||||
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
|
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,67 +775,29 @@ final class BigDecimal extends BigNumber
|
|||||||
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
|
||||||
*
|
*
|
||||||
* @param array{value: string, scale: int} $data
|
* @param array{value: string, scale: int} $data
|
||||||
*
|
*
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws \LogicException
|
* @throws \LogicException
|
||||||
*/
|
*/
|
||||||
public function __unserialize(array $data): void
|
public function __unserialize(array $data): void
|
||||||
{
|
{
|
||||||
|
/** @phpstan-ignore isset.initializedProperty */
|
||||||
if (isset($this->value)) {
|
if (isset($this->value)) {
|
||||||
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @phpstan-ignore deadCode.unreachable */
|
||||||
$this->value = $data['value'];
|
$this->value = $data['value'];
|
||||||
$this->scale = $data['scale'];
|
$this->scale = $data['scale'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @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.
|
* Puts the internal values of the given decimal numbers on the same scale.
|
||||||
*
|
*
|
||||||
* @param BigDecimal $x The first decimal number.
|
|
||||||
* @param BigDecimal $y The second decimal number.
|
|
||||||
*
|
|
||||||
* @return array{string, string} The scaled integer values of $x and $y.
|
* @return array{string, string} The scaled integer values of $x and $y.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
|
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
|
||||||
{
|
{
|
||||||
@ -845,9 +814,7 @@ final class BigDecimal extends BigNumber
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $scale
|
* @pure
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function valueWithMinScale(int $scale) : string
|
private function valueWithMinScale(int $scale) : string
|
||||||
{
|
{
|
||||||
@ -863,7 +830,7 @@ final class BigDecimal extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
|
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function getUnscaledValueWithLeadingZeros() : string
|
private function getUnscaledValueWithLeadingZeros() : string
|
||||||
{
|
{
|
||||||
|
|||||||
403
vendor/brick/math/src/BigInteger.php
vendored
403
vendor/brick/math/src/BigInteger.php
vendored
@ -10,51 +10,41 @@ use Brick\Math\Exception\MathException;
|
|||||||
use Brick\Math\Exception\NegativeNumberException;
|
use Brick\Math\Exception\NegativeNumberException;
|
||||||
use Brick\Math\Exception\NumberFormatException;
|
use Brick\Math\Exception\NumberFormatException;
|
||||||
use Brick\Math\Internal\Calculator;
|
use Brick\Math\Internal\Calculator;
|
||||||
|
use Brick\Math\Internal\CalculatorRegistry;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An arbitrary-size integer.
|
* An arbitrary-size integer.
|
||||||
*
|
*
|
||||||
* All methods accepting a number as a parameter accept either a BigInteger instance,
|
* All methods accepting a number as a parameter accept either a BigInteger instance,
|
||||||
* an integer, or a string representing an arbitrary size integer.
|
* an integer, or a string representing an arbitrary size integer.
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
final class BigInteger extends BigNumber
|
final readonly class BigInteger extends BigNumber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The value, as a string of digits with optional leading minus sign.
|
* The value, as a string of digits with optional leading minus sign.
|
||||||
*
|
*
|
||||||
* No leading zeros must be present.
|
* No leading zeros must be present.
|
||||||
* No leading minus sign must be present if the number is zero.
|
* No leading minus sign must be present if the number is zero.
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $value;
|
private string $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected constructor. Use a factory method to obtain an instance.
|
* Protected constructor. Use a factory method to obtain an instance.
|
||||||
*
|
*
|
||||||
* @param string $value A string of digits, with optional leading minus sign.
|
* @param string $value A string of digits, with optional leading minus sign.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
protected function __construct(string $value)
|
protected function __construct(string $value)
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* Creates a BigInteger of the given value.
|
protected static function from(BigNumber $number): static
|
||||||
*
|
|
||||||
* @param BigNumber|int|float|string $value
|
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws MathException If the value cannot be converted to a BigInteger.
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
|
||||||
public static function of($value) : BigNumber
|
|
||||||
{
|
{
|
||||||
return parent::of($value)->toBigInteger();
|
return $number->toBigInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,12 +61,10 @@ final class BigInteger extends BigNumber
|
|||||||
* @param string $number The number to convert, in the given base.
|
* @param string $number The number to convert, in the given base.
|
||||||
* @param int $base The base of the number, between 2 and 36.
|
* @param int $base The base of the number, between 2 and 36.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
|
* @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
|
||||||
* @throws \InvalidArgumentException If the base is out of range.
|
* @throws \InvalidArgumentException If the base is out of range.
|
||||||
*
|
*
|
||||||
* @psalm-pure
|
* @pure
|
||||||
*/
|
*/
|
||||||
public static function fromBase(string $number, int $base) : BigInteger
|
public static function fromBase(string $number, int $base) : BigInteger
|
||||||
{
|
{
|
||||||
@ -125,7 +113,7 @@ final class BigInteger extends BigNumber
|
|||||||
return new BigInteger($sign . $number);
|
return new BigInteger($sign . $number);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = Calculator::get()->fromBase($number, $base);
|
$result = CalculatorRegistry::get()->fromBase($number, $base);
|
||||||
|
|
||||||
return new BigInteger($sign . $result);
|
return new BigInteger($sign . $result);
|
||||||
}
|
}
|
||||||
@ -138,12 +126,10 @@ final class BigInteger extends BigNumber
|
|||||||
* @param string $number The number to parse.
|
* @param string $number The number to parse.
|
||||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
|
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
|
||||||
* @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
|
* @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
|
||||||
*
|
*
|
||||||
* @psalm-pure
|
* @pure
|
||||||
*/
|
*/
|
||||||
public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger
|
public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger
|
||||||
{
|
{
|
||||||
@ -163,7 +149,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw NumberFormatException::charNotInAlphabet($matches[0]);
|
throw NumberFormatException::charNotInAlphabet($matches[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base);
|
$number = CalculatorRegistry::get()->fromArbitraryBase($number, $alphabet, $base);
|
||||||
|
|
||||||
return new BigInteger($number);
|
return new BigInteger($number);
|
||||||
}
|
}
|
||||||
@ -183,9 +169,9 @@ final class BigInteger extends BigNumber
|
|||||||
* @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading
|
* @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading
|
||||||
* sign bit.
|
* sign bit.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws NumberFormatException If the string is empty.
|
* @throws NumberFormatException If the string is empty.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public static function fromBytes(string $value, bool $signed = true) : BigInteger
|
public static function fromBytes(string $value, bool $signed = true) : BigInteger
|
||||||
{
|
{
|
||||||
@ -217,14 +203,10 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* Using the default random bytes generator, this method is suitable for cryptographic use.
|
* Using the default random bytes generator, this method is suitable for cryptographic use.
|
||||||
*
|
*
|
||||||
* @psalm-param callable(int): string $randomBytesGenerator
|
* @param int $numBits The number of bits.
|
||||||
*
|
* @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
|
||||||
* @param int $numBits The number of bits.
|
* a string of random bytes of the given length. Defaults
|
||||||
* @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a
|
* to the `random_bytes()` function.
|
||||||
* string of random bytes of the given length. Defaults to the
|
|
||||||
* `random_bytes()` function.
|
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException If $numBits is negative.
|
* @throws \InvalidArgumentException If $numBits is negative.
|
||||||
*/
|
*/
|
||||||
@ -239,9 +221,10 @@ final class BigInteger extends BigNumber
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($randomBytesGenerator === null) {
|
if ($randomBytesGenerator === null) {
|
||||||
$randomBytesGenerator = 'random_bytes';
|
$randomBytesGenerator = random_bytes(...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var int<1, max> $byteLength */
|
||||||
$byteLength = \intdiv($numBits - 1, 8) + 1;
|
$byteLength = \intdiv($numBits - 1, 8) + 1;
|
||||||
|
|
||||||
$extraBits = ($byteLength * 8 - $numBits);
|
$extraBits = ($byteLength * 8 - $numBits);
|
||||||
@ -258,21 +241,20 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* Using the default random bytes generator, this method is suitable for cryptographic use.
|
* Using the default random bytes generator, this method is suitable for cryptographic use.
|
||||||
*
|
*
|
||||||
* @psalm-param (callable(int): string)|null $randomBytesGenerator
|
* @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
|
||||||
*
|
* @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
|
||||||
* @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
|
* @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
|
||||||
* @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
|
* a string of random bytes of the given length. Defaults
|
||||||
* @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer,
|
* to the `random_bytes()` function.
|
||||||
* and returns a string of random bytes of the given length.
|
|
||||||
* Defaults to the `random_bytes()` function.
|
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*
|
*
|
||||||
* @throws MathException If one of the parameters cannot be converted to a BigInteger,
|
* @throws MathException If one of the parameters cannot be converted to a BigInteger,
|
||||||
* or `$min` is greater than `$max`.
|
* or `$min` is greater than `$max`.
|
||||||
*/
|
*/
|
||||||
public static function randomRange($min, $max, ?callable $randomBytesGenerator = null) : BigInteger
|
public static function randomRange(
|
||||||
{
|
BigNumber|int|float|string $min,
|
||||||
|
BigNumber|int|float|string $max,
|
||||||
|
?callable $randomBytesGenerator = null
|
||||||
|
) : BigInteger {
|
||||||
$min = BigInteger::of($min);
|
$min = BigInteger::of($min);
|
||||||
$max = BigInteger::of($max);
|
$max = BigInteger::of($max);
|
||||||
|
|
||||||
@ -298,16 +280,11 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigInteger representing zero.
|
* Returns a BigInteger representing zero.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function zero() : BigInteger
|
public static function zero() : BigInteger
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigInteger|null $zero */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigInteger|null $zero
|
|
||||||
*/
|
|
||||||
static $zero;
|
static $zero;
|
||||||
|
|
||||||
if ($zero === null) {
|
if ($zero === null) {
|
||||||
@ -320,16 +297,11 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigInteger representing one.
|
* Returns a BigInteger representing one.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function one() : BigInteger
|
public static function one() : BigInteger
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigInteger|null $one */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigInteger|null $one
|
|
||||||
*/
|
|
||||||
static $one;
|
static $one;
|
||||||
|
|
||||||
if ($one === null) {
|
if ($one === null) {
|
||||||
@ -342,16 +314,11 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigInteger representing ten.
|
* Returns a BigInteger representing ten.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function ten() : BigInteger
|
public static function ten() : BigInteger
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigInteger|null $ten */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigInteger|null $ten
|
|
||||||
*/
|
|
||||||
static $ten;
|
static $ten;
|
||||||
|
|
||||||
if ($ten === null) {
|
if ($ten === null) {
|
||||||
@ -361,16 +328,34 @@ final class BigInteger extends BigNumber
|
|||||||
return $ten;
|
return $ten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pure
|
||||||
|
*/
|
||||||
|
public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
|
||||||
|
{
|
||||||
|
$result = $a;
|
||||||
|
|
||||||
|
foreach ($n as $next) {
|
||||||
|
$result = $result->gcd($next);
|
||||||
|
|
||||||
|
if ($result->isEqualTo(1)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the sum of this number and the given one.
|
* Returns the sum of this number and the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function plus($that) : BigInteger
|
public function plus(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -382,7 +367,7 @@ final class BigInteger extends BigNumber
|
|||||||
return $that;
|
return $that;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->add($this->value, $that->value);
|
$value = CalculatorRegistry::get()->add($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -392,11 +377,11 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function minus($that) : BigInteger
|
public function minus(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -404,7 +389,7 @@ final class BigInteger extends BigNumber
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->sub($this->value, $that->value);
|
$value = CalculatorRegistry::get()->sub($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -414,11 +399,11 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
|
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function multipliedBy($that) : BigInteger
|
public function multipliedBy(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -430,7 +415,7 @@ final class BigInteger extends BigNumber
|
|||||||
return $that;
|
return $that;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->mul($this->value, $that->value);
|
$value = CalculatorRegistry::get()->mul($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -439,14 +424,14 @@ final class BigInteger extends BigNumber
|
|||||||
* Returns the result of the division of this number by the given one.
|
* Returns the result of the division of this number by the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||||
* @param int $roundingMode An optional rounding mode.
|
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||||
*
|
|
||||||
* @return BigInteger The result.
|
|
||||||
*
|
*
|
||||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
|
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
|
||||||
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
|
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
|
public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -458,19 +443,40 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::divisionByZero();
|
throw DivisionByZeroException::divisionByZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = Calculator::get()->divRound($this->value, $that->value, $roundingMode);
|
$result = CalculatorRegistry::get()->divRound($this->value, $that->value, $roundingMode);
|
||||||
|
|
||||||
return new BigInteger($result);
|
return new BigInteger($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits (clamps) this number between the given minimum and maximum values.
|
||||||
|
*
|
||||||
|
* If the number is lower than $min, returns a copy of $min.
|
||||||
|
* If the number is greater than $max, returns a copy of $max.
|
||||||
|
* Otherwise, returns this number unchanged.
|
||||||
|
*
|
||||||
|
* @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigInteger.
|
||||||
|
* @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigInteger.
|
||||||
|
*
|
||||||
|
* @throws MathException If min/max are not convertible to a BigInteger.
|
||||||
|
*/
|
||||||
|
public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigInteger
|
||||||
|
{
|
||||||
|
if ($this->isLessThan($min)) {
|
||||||
|
return BigInteger::of($min);
|
||||||
|
} elseif ($this->isGreaterThan($max)) {
|
||||||
|
return BigInteger::of($max);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns this number exponentiated to the given value.
|
* Returns this number exponentiated to the given value.
|
||||||
*
|
*
|
||||||
* @param int $exponent The exponent.
|
|
||||||
*
|
|
||||||
* @return BigInteger The result.
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function power(int $exponent) : BigInteger
|
public function power(int $exponent) : BigInteger
|
||||||
{
|
{
|
||||||
@ -490,7 +496,7 @@ final class BigInteger extends BigNumber
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BigInteger(Calculator::get()->pow($this->value, $exponent));
|
return new BigInteger(CalculatorRegistry::get()->pow($this->value, $exponent));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -498,11 +504,11 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws DivisionByZeroException If the divisor is zero.
|
* @throws DivisionByZeroException If the divisor is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotient($that) : BigInteger
|
public function quotient(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -514,7 +520,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::divisionByZero();
|
throw DivisionByZeroException::divisionByZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$quotient = Calculator::get()->divQ($this->value, $that->value);
|
$quotient = CalculatorRegistry::get()->divQ($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($quotient);
|
return new BigInteger($quotient);
|
||||||
}
|
}
|
||||||
@ -526,11 +532,11 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws DivisionByZeroException If the divisor is zero.
|
* @throws DivisionByZeroException If the divisor is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function remainder($that) : BigInteger
|
public function remainder(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -542,7 +548,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::divisionByZero();
|
throw DivisionByZeroException::divisionByZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$remainder = Calculator::get()->divR($this->value, $that->value);
|
$remainder = CalculatorRegistry::get()->divR($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($remainder);
|
return new BigInteger($remainder);
|
||||||
}
|
}
|
||||||
@ -552,11 +558,13 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger[] An array containing the quotient and the remainder.
|
* @return array{BigInteger, BigInteger} An array containing the quotient and the remainder.
|
||||||
*
|
*
|
||||||
* @throws DivisionByZeroException If the divisor is zero.
|
* @throws DivisionByZeroException If the divisor is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotientAndRemainder($that) : array
|
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -564,7 +572,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::divisionByZero();
|
throw DivisionByZeroException::divisionByZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
[$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value);
|
[$quotient, $remainder] = CalculatorRegistry::get()->divQR($this->value, $that->value);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
new BigInteger($quotient),
|
new BigInteger($quotient),
|
||||||
@ -582,11 +590,11 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws DivisionByZeroException If the divisor is zero.
|
* @throws DivisionByZeroException If the divisor is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function mod($that) : BigInteger
|
public function mod(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -594,7 +602,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::modulusMustNotBeZero();
|
throw DivisionByZeroException::modulusMustNotBeZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->mod($this->value, $that->value);
|
$value = CalculatorRegistry::get()->mod($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -602,14 +610,12 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the modular multiplicative inverse of this BigInteger modulo $m.
|
* Returns the modular multiplicative inverse of this BigInteger modulo $m.
|
||||||
*
|
*
|
||||||
* @param BigInteger $m
|
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws DivisionByZeroException If $m is zero.
|
* @throws DivisionByZeroException If $m is zero.
|
||||||
* @throws NegativeNumberException If $m is negative.
|
* @throws NegativeNumberException If $m is negative.
|
||||||
* @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
|
* @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
|
||||||
* is not relatively prime to m).
|
* is not relatively prime to m).
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function modInverse(BigInteger $m) : BigInteger
|
public function modInverse(BigInteger $m) : BigInteger
|
||||||
{
|
{
|
||||||
@ -625,7 +631,7 @@ final class BigInteger extends BigNumber
|
|||||||
return BigInteger::zero();
|
return BigInteger::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->modInverse($this->value, $m->value);
|
$value = CalculatorRegistry::get()->modInverse($this->value, $m->value);
|
||||||
|
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
throw new MathException('Unable to compute the modInverse for the given modulus.');
|
throw new MathException('Unable to compute the modInverse for the given modulus.');
|
||||||
@ -642,12 +648,12 @@ final class BigInteger extends BigNumber
|
|||||||
* @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
|
* @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
|
||||||
* @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
|
* @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws NegativeNumberException If any of the operands is negative.
|
* @throws NegativeNumberException If any of the operands is negative.
|
||||||
* @throws DivisionByZeroException If the modulus is zero.
|
* @throws DivisionByZeroException If the modulus is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function modPow($exp, $mod) : BigInteger
|
public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger
|
||||||
{
|
{
|
||||||
$exp = BigInteger::of($exp);
|
$exp = BigInteger::of($exp);
|
||||||
$mod = BigInteger::of($mod);
|
$mod = BigInteger::of($mod);
|
||||||
@ -660,7 +666,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw DivisionByZeroException::modulusMustNotBeZero();
|
throw DivisionByZeroException::modulusMustNotBeZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = Calculator::get()->modPow($this->value, $exp->value, $mod->value);
|
$result = CalculatorRegistry::get()->modPow($this->value, $exp->value, $mod->value);
|
||||||
|
|
||||||
return new BigInteger($result);
|
return new BigInteger($result);
|
||||||
}
|
}
|
||||||
@ -672,9 +678,9 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function gcd($that) : BigInteger
|
public function gcd(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
@ -686,7 +692,7 @@ final class BigInteger extends BigNumber
|
|||||||
return $that;
|
return $that;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->gcd($this->value, $that->value);
|
$value = CalculatorRegistry::get()->gcd($this->value, $that->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -696,9 +702,9 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* The result is the largest x such that x² ≤ n.
|
* The result is the largest x such that x² ≤ n.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
|
||||||
*
|
|
||||||
* @throws NegativeNumberException If this number is negative.
|
* @throws NegativeNumberException If this number is negative.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function sqrt() : BigInteger
|
public function sqrt() : BigInteger
|
||||||
{
|
{
|
||||||
@ -706,7 +712,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = Calculator::get()->sqrt($this->value);
|
$value = CalculatorRegistry::get()->sqrt($this->value);
|
||||||
|
|
||||||
return new BigInteger($value);
|
return new BigInteger($value);
|
||||||
}
|
}
|
||||||
@ -714,7 +720,7 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the absolute value of this number.
|
* Returns the absolute value of this number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function abs() : BigInteger
|
public function abs() : BigInteger
|
||||||
{
|
{
|
||||||
@ -724,11 +730,11 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the inverse of this number.
|
* Returns the inverse of this number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function negated() : BigInteger
|
public function negated() : BigInteger
|
||||||
{
|
{
|
||||||
return new BigInteger(Calculator::get()->neg($this->value));
|
return new BigInteger(CalculatorRegistry::get()->neg($this->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -738,13 +744,13 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function and($that) : BigInteger
|
public function and(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
return new BigInteger(Calculator::get()->and($this->value, $that->value));
|
return new BigInteger(CalculatorRegistry::get()->and($this->value, $that->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -754,13 +760,13 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function or($that) : BigInteger
|
public function or(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
return new BigInteger(Calculator::get()->or($this->value, $that->value));
|
return new BigInteger(CalculatorRegistry::get()->or($this->value, $that->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -770,19 +776,19 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function xor($that) : BigInteger
|
public function xor(BigNumber|int|float|string $that) : BigInteger
|
||||||
{
|
{
|
||||||
$that = BigInteger::of($that);
|
$that = BigInteger::of($that);
|
||||||
|
|
||||||
return new BigInteger(Calculator::get()->xor($this->value, $that->value));
|
return new BigInteger(CalculatorRegistry::get()->xor($this->value, $that->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bitwise-not of this BigInteger.
|
* Returns the bitwise-not of this BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function not() : BigInteger
|
public function not() : BigInteger
|
||||||
{
|
{
|
||||||
@ -792,9 +798,7 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the integer left shifted by a given number of bits.
|
* Returns the integer left shifted by a given number of bits.
|
||||||
*
|
*
|
||||||
* @param int $distance The distance to shift.
|
* @pure
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*/
|
*/
|
||||||
public function shiftedLeft(int $distance) : BigInteger
|
public function shiftedLeft(int $distance) : BigInteger
|
||||||
{
|
{
|
||||||
@ -812,9 +816,7 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the integer right shifted by a given number of bits.
|
* Returns the integer right shifted by a given number of bits.
|
||||||
*
|
*
|
||||||
* @param int $distance The distance to shift.
|
* @pure
|
||||||
*
|
|
||||||
* @return BigInteger
|
|
||||||
*/
|
*/
|
||||||
public function shiftedRight(int $distance) : BigInteger
|
public function shiftedRight(int $distance) : BigInteger
|
||||||
{
|
{
|
||||||
@ -841,7 +843,7 @@ final class BigInteger extends BigNumber
|
|||||||
* For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
|
* For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
|
||||||
* Computes (ceil(log2(this < 0 ? -this : this+1))).
|
* Computes (ceil(log2(this < 0 ? -this : this+1))).
|
||||||
*
|
*
|
||||||
* @return int
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getBitLength() : int
|
public function getBitLength() : int
|
||||||
{
|
{
|
||||||
@ -861,7 +863,7 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* Returns -1 if this BigInteger contains no one bits.
|
* Returns -1 if this BigInteger contains no one bits.
|
||||||
*
|
*
|
||||||
* @return int
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getLowestSetBit() : int
|
public function getLowestSetBit() : int
|
||||||
{
|
{
|
||||||
@ -882,7 +884,7 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns whether this number is even.
|
* Returns whether this number is even.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isEven() : bool
|
public function isEven() : bool
|
||||||
{
|
{
|
||||||
@ -892,7 +894,7 @@ final class BigInteger extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns whether this number is odd.
|
* Returns whether this number is odd.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isOdd() : bool
|
public function isOdd() : bool
|
||||||
{
|
{
|
||||||
@ -906,9 +908,9 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param int $n The bit to test, 0-based.
|
* @param int $n The bit to test, 0-based.
|
||||||
*
|
*
|
||||||
* @return bool
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the bit to test is negative.
|
* @throws \InvalidArgumentException If the bit to test is negative.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function testBit(int $n) : bool
|
public function testBit(int $n) : bool
|
||||||
{
|
{
|
||||||
@ -919,63 +921,49 @@ final class BigInteger extends BigNumber
|
|||||||
return $this->shiftedRight($n)->isOdd();
|
return $this->shiftedRight($n)->isOdd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function compareTo(BigNumber|int|float|string $that) : int
|
||||||
*/
|
|
||||||
public function compareTo($that) : int
|
|
||||||
{
|
{
|
||||||
$that = BigNumber::of($that);
|
$that = BigNumber::of($that);
|
||||||
|
|
||||||
if ($that instanceof BigInteger) {
|
if ($that instanceof BigInteger) {
|
||||||
return Calculator::get()->cmp($this->value, $that->value);
|
return CalculatorRegistry::get()->cmp($this->value, $that->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return - $that->compareTo($this);
|
return - $that->compareTo($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getSign() : int
|
public function getSign() : int
|
||||||
{
|
{
|
||||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigInteger() : BigInteger
|
public function toBigInteger() : BigInteger
|
||||||
{
|
{
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigDecimal() : BigDecimal
|
public function toBigDecimal() : BigDecimal
|
||||||
{
|
{
|
||||||
return BigDecimal::create($this->value);
|
return self::newBigDecimal($this->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigRational() : BigRational
|
public function toBigRational() : BigRational
|
||||||
{
|
{
|
||||||
return BigRational::create($this, BigInteger::one(), false);
|
return self::newBigRational($this, BigInteger::one(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||||
*/
|
|
||||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
|
||||||
{
|
{
|
||||||
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toInt() : int
|
public function toInt() : int
|
||||||
{
|
{
|
||||||
$intValue = (int) $this->value;
|
$intValue = (int) $this->value;
|
||||||
@ -987,9 +975,7 @@ final class BigInteger extends BigNumber
|
|||||||
return $intValue;
|
return $intValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toFloat() : float
|
public function toFloat() : float
|
||||||
{
|
{
|
||||||
return (float) $this->value;
|
return (float) $this->value;
|
||||||
@ -1000,11 +986,9 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* The output will always be lowercase for bases greater than 10.
|
* The output will always be lowercase for bases greater than 10.
|
||||||
*
|
*
|
||||||
* @param int $base
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the base is out of range.
|
* @throws \InvalidArgumentException If the base is out of range.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function toBase(int $base) : string
|
public function toBase(int $base) : string
|
||||||
{
|
{
|
||||||
@ -1016,7 +1000,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
|
throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Calculator::get()->toBase($this->value, $base);
|
return CalculatorRegistry::get()->toBase($this->value, $base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1027,10 +1011,10 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||||
*
|
*
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws NegativeNumberException If this number is negative.
|
* @throws NegativeNumberException If this number is negative.
|
||||||
* @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
|
* @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function toArbitraryBase(string $alphabet) : string
|
public function toArbitraryBase(string $alphabet) : string
|
||||||
{
|
{
|
||||||
@ -1044,7 +1028,7 @@ final class BigInteger extends BigNumber
|
|||||||
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
|
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base);
|
return CalculatorRegistry::get()->toArbitraryBase($this->value, $alphabet, $base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1063,9 +1047,9 @@ final class BigInteger extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
|
* @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
|
||||||
*
|
*
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws NegativeNumberException If $signed is false, and the number is negative.
|
* @throws NegativeNumberException If $signed is false, and the number is negative.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function toBytes(bool $signed = true) : string
|
public function toBytes(bool $signed = true) : string
|
||||||
{
|
{
|
||||||
@ -1105,14 +1089,19 @@ final class BigInteger extends BigNumber
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return \hex2bin($hex);
|
$result = \hex2bin($hex);
|
||||||
|
assert($result !== false);
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* @return numeric-string
|
||||||
*/
|
*/
|
||||||
|
#[Override]
|
||||||
public function __toString() : string
|
public function __toString() : string
|
||||||
{
|
{
|
||||||
|
/** @var numeric-string */
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,53 +1121,19 @@ final class BigInteger extends BigNumber
|
|||||||
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
|
||||||
*
|
*
|
||||||
* @param array{value: string} $data
|
* @param array{value: string} $data
|
||||||
*
|
*
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws \LogicException
|
* @throws \LogicException
|
||||||
*/
|
*/
|
||||||
public function __unserialize(array $data): void
|
public function __unserialize(array $data): void
|
||||||
{
|
{
|
||||||
|
/** @phpstan-ignore isset.initializedProperty */
|
||||||
if (isset($this->value)) {
|
if (isset($this->value)) {
|
||||||
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @phpstan-ignore deadCode.unreachable */
|
||||||
$this->value = $data['value'];
|
$this->value = $data['value'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function serialize() : string
|
|
||||||
{
|
|
||||||
return $this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @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.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->value = $value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
428
vendor/brick/math/src/BigNumber.php
vendored
428
vendor/brick/math/src/BigNumber.php
vendored
@ -8,38 +8,46 @@ use Brick\Math\Exception\DivisionByZeroException;
|
|||||||
use Brick\Math\Exception\MathException;
|
use Brick\Math\Exception\MathException;
|
||||||
use Brick\Math\Exception\NumberFormatException;
|
use Brick\Math\Exception\NumberFormatException;
|
||||||
use Brick\Math\Exception\RoundingNecessaryException;
|
use Brick\Math\Exception\RoundingNecessaryException;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common interface for arbitrary-precision rational numbers.
|
* Base class for arbitrary-precision numbers.
|
||||||
*
|
*
|
||||||
* @psalm-immutable
|
* This class is sealed: it is part of the public API but should not be subclassed in userland.
|
||||||
|
* Protected methods may change in any version.
|
||||||
|
*
|
||||||
|
* @phpstan-sealed BigInteger|BigDecimal|BigRational
|
||||||
*/
|
*/
|
||||||
abstract class BigNumber implements \Serializable, \JsonSerializable
|
abstract readonly class BigNumber implements \JsonSerializable, \Stringable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The regular expression used to parse integer, decimal and rational numbers.
|
* The regular expression used to parse integer or decimal numbers.
|
||||||
*/
|
*/
|
||||||
private const PARSE_REGEXP =
|
private const PARSE_REGEXP_NUMERICAL =
|
||||||
'/^' .
|
'/^' .
|
||||||
'(?<sign>[\-\+])?' .
|
'(?<sign>[\-\+])?' .
|
||||||
'(?:' .
|
'(?<integral>[0-9]+)?' .
|
||||||
'(?:' .
|
'(?<point>\.)?' .
|
||||||
'(?<integral>[0-9]+)?' .
|
'(?<fractional>[0-9]+)?' .
|
||||||
'(?<point>\.)?' .
|
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
||||||
'(?<fractional>[0-9]+)?' .
|
'$/';
|
||||||
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
|
||||||
')|(?:' .
|
/**
|
||||||
'(?<numerator>[0-9]+)' .
|
* The regular expression used to parse rational numbers.
|
||||||
'\/?' .
|
*/
|
||||||
'(?<denominator>[0-9]+)' .
|
private const PARSE_REGEXP_RATIONAL =
|
||||||
')' .
|
'/^' .
|
||||||
')' .
|
'(?<sign>[\-\+])?' .
|
||||||
|
'(?<numerator>[0-9]+)' .
|
||||||
|
'\/?' .
|
||||||
|
'(?<denominator>[0-9]+)' .
|
||||||
'$/';
|
'$/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BigNumber of the given value.
|
* Creates a BigNumber of the given value.
|
||||||
*
|
*
|
||||||
* The concrete return type is dependent on the given value, with the following rules:
|
* When of() is called on BigNumber, the concrete return type is dependent on the given value, with the following
|
||||||
|
* rules:
|
||||||
*
|
*
|
||||||
* - BigNumber instances are returned as is
|
* - BigNumber instances are returned as is
|
||||||
* - integer numbers are returned as BigInteger
|
* - integer numbers are returned as BigInteger
|
||||||
@ -48,16 +56,35 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
|
* - 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
|
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $value
|
* When of() is called on BigInteger, BigDecimal, or BigRational, the resulting number is converted to an instance
|
||||||
|
* of the subclass when possible; otherwise a RoundingNecessaryException exception is thrown.
|
||||||
*
|
*
|
||||||
* @return BigNumber
|
* @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.
|
||||||
|
* @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding.
|
||||||
*
|
*
|
||||||
* @throws NumberFormatException If the format of the number is not valid.
|
* @pure
|
||||||
|
*/
|
||||||
|
final public static function of(BigNumber|int|float|string $value) : static
|
||||||
|
{
|
||||||
|
$value = self::_of($value);
|
||||||
|
|
||||||
|
if (static::class === BigNumber::class) {
|
||||||
|
assert($value instanceof static);
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::from($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
|
||||||
*
|
*
|
||||||
* @psalm-pure
|
* @pure
|
||||||
*/
|
*/
|
||||||
public static function of($value) : BigNumber
|
private static function _of(BigNumber|int|float|string $value) : BigNumber
|
||||||
{
|
{
|
||||||
if ($value instanceof BigNumber) {
|
if ($value instanceof BigNumber) {
|
||||||
return $value;
|
return $value;
|
||||||
@ -67,37 +94,22 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
return new BigInteger((string) $value);
|
return new BigInteger((string) $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @psalm-suppress RedundantCastGivenDocblockType We cannot trust the untyped $value here! */
|
if (is_float($value)) {
|
||||||
$value = \is_float($value) ? self::floatToString($value) : (string) $value;
|
$value = (string) $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 function(string $value) use ($matches) : ?string {
|
if (str_contains($value, '/')) {
|
||||||
return isset($matches[$value]) && $matches[$value] !== '' ? $matches[$value] : null;
|
// Rational number
|
||||||
};
|
if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||||
|
throw NumberFormatException::invalidFormat($value);
|
||||||
$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);
|
$sign = $matches['sign'];
|
||||||
$denominator = self::cleanUp($denominator);
|
$numerator = $matches['numerator'];
|
||||||
|
$denominator = $matches['denominator'];
|
||||||
|
|
||||||
|
$numerator = self::cleanUp($sign, $numerator);
|
||||||
|
$denominator = self::cleanUp(null, $denominator);
|
||||||
|
|
||||||
if ($denominator === '0') {
|
if ($denominator === '0') {
|
||||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||||
@ -108,88 +120,94 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
new BigInteger($denominator),
|
new BigInteger($denominator),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
|
// Integer or decimal number
|
||||||
$point = $getMatch('point');
|
if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||||
$integral = $getMatch('integral');
|
throw NumberFormatException::invalidFormat($value);
|
||||||
$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);
|
$sign = $matches['sign'];
|
||||||
|
$point = $matches['point'];
|
||||||
|
$integral = $matches['integral'];
|
||||||
|
$fractional = $matches['fractional'];
|
||||||
|
$exponent = $matches['exponent'];
|
||||||
|
|
||||||
$scale = \strlen($fractional) - $exponent;
|
if ($integral === null && $fractional === null) {
|
||||||
|
throw NumberFormatException::invalidFormat($value);
|
||||||
|
}
|
||||||
|
|
||||||
if ($scale < 0) {
|
if ($integral === null) {
|
||||||
if ($unscaledValue !== '0') {
|
$integral = '0';
|
||||||
$unscaledValue .= \str_repeat('0', - $scale);
|
}
|
||||||
|
|
||||||
|
if ($point !== null || $exponent !== null) {
|
||||||
|
$fractional ??= '';
|
||||||
|
$exponent = ($exponent !== null) ? (int)$exponent : 0;
|
||||||
|
|
||||||
|
if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
|
||||||
|
throw new NumberFormatException('Exponent too large.');
|
||||||
}
|
}
|
||||||
$scale = 0;
|
|
||||||
|
$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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BigDecimal($unscaledValue, $scale);
|
$integral = self::cleanUp($sign, $integral);
|
||||||
|
|
||||||
|
return new BigInteger($integral);
|
||||||
}
|
}
|
||||||
|
|
||||||
$integral = self::cleanUp(($sign ?? '') . $integral);
|
|
||||||
|
|
||||||
return new BigInteger($integral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely converts float to string, avoiding locale-dependent issues.
|
* Overridden by subclasses to convert a BigNumber to an instance of the subclass.
|
||||||
*
|
*
|
||||||
* @see https://github.com/brick/math/pull/20
|
* @throws RoundingNecessaryException If the value cannot be converted.
|
||||||
*
|
*
|
||||||
* @param float $float
|
* @pure
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
* @psalm-suppress ImpureFunctionCall
|
|
||||||
*/
|
*/
|
||||||
private static function floatToString(float $float) : string
|
abstract protected static function from(BigNumber $number): static;
|
||||||
{
|
|
||||||
$currentLocale = \setlocale(LC_NUMERIC, '0');
|
|
||||||
\setlocale(LC_NUMERIC, 'C');
|
|
||||||
|
|
||||||
$result = (string) $float;
|
|
||||||
|
|
||||||
\setlocale(LC_NUMERIC, $currentLocale);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy method to access protected constructors from sibling classes.
|
* Proxy method to access BigInteger's protected constructor from sibling classes.
|
||||||
*
|
*
|
||||||
|
* @pure
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @param mixed ...$args The arguments to the constructor.
|
|
||||||
*
|
|
||||||
* @return static
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
* @psalm-suppress TooManyArguments
|
|
||||||
* @psalm-suppress UnsafeInstantiation
|
|
||||||
*/
|
*/
|
||||||
protected static function create(... $args) : BigNumber
|
final protected function newBigInteger(string $value) : BigInteger
|
||||||
{
|
{
|
||||||
return new static(... $args);
|
return new BigInteger($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method to access BigDecimal's protected constructor from sibling classes.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final 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.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
|
||||||
|
{
|
||||||
|
return new BigRational($numerator, $denominator, $checkDenominator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,16 +216,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
* @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.
|
* to an instance of the class this method is called on.
|
||||||
*
|
*
|
||||||
* @return static The minimum value.
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If no values are given.
|
* @throws \InvalidArgumentException If no values are given.
|
||||||
* @throws MathException If an argument is not valid.
|
* @throws MathException If an argument is not valid.
|
||||||
*
|
*
|
||||||
* @psalm-suppress LessSpecificReturnStatement
|
* @pure
|
||||||
* @psalm-suppress MoreSpecificReturnType
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function min(...$values) : BigNumber
|
final public static function min(BigNumber|int|float|string ...$values) : static
|
||||||
{
|
{
|
||||||
$min = null;
|
$min = null;
|
||||||
|
|
||||||
@ -232,16 +246,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
* @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.
|
* to an instance of the class this method is called on.
|
||||||
*
|
*
|
||||||
* @return static The maximum value.
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If no values are given.
|
* @throws \InvalidArgumentException If no values are given.
|
||||||
* @throws MathException If an argument is not valid.
|
* @throws MathException If an argument is not valid.
|
||||||
*
|
*
|
||||||
* @psalm-suppress LessSpecificReturnStatement
|
* @pure
|
||||||
* @psalm-suppress MoreSpecificReturnType
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function max(...$values) : BigNumber
|
final public static function max(BigNumber|int|float|string ...$values) : static
|
||||||
{
|
{
|
||||||
$max = null;
|
$max = null;
|
||||||
|
|
||||||
@ -263,50 +273,43 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Returns the sum of the given values.
|
* Returns the sum of the given values.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
|
* When called on BigNumber, sum() accepts any supported type and returns a result whose type is the widest among
|
||||||
* to an instance of the class this method is called on.
|
* the given values (BigInteger < BigDecimal < BigRational).
|
||||||
*
|
*
|
||||||
* @return static The sum.
|
* When called on BigInteger, BigDecimal, or BigRational, sum() requires that all values can be converted to that
|
||||||
|
* specific subclass, and returns a result of the same type.
|
||||||
|
*
|
||||||
|
* @param BigNumber|int|float|string ...$values The values to add. All values must be convertible to the class on
|
||||||
|
* which this method is called.
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException If no values are given.
|
* @throws \InvalidArgumentException If no values are given.
|
||||||
* @throws MathException If an argument is not valid.
|
* @throws MathException If an argument is not valid.
|
||||||
*
|
*
|
||||||
* @psalm-suppress LessSpecificReturnStatement
|
* @pure
|
||||||
* @psalm-suppress MoreSpecificReturnType
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function sum(...$values) : BigNumber
|
final public static function sum(BigNumber|int|float|string ...$values) : static
|
||||||
{
|
{
|
||||||
/** @var BigNumber|null $sum */
|
$first = array_shift($values);
|
||||||
$sum = null;
|
|
||||||
|
|
||||||
foreach ($values as $value) {
|
if ($first === null) {
|
||||||
$value = static::of($value);
|
|
||||||
|
|
||||||
$sum = $sum === null ? $value : self::add($sum, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($sum === null) {
|
|
||||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sum = static::of($first);
|
||||||
|
|
||||||
|
foreach ($values as $value) {
|
||||||
|
$sum = self::add($sum, static::of($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert($sum instanceof static);
|
||||||
|
|
||||||
return $sum;
|
return $sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
|
* 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
|
* @pure
|
||||||
* 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...)
|
|
||||||
*
|
|
||||||
* @param BigNumber $a
|
|
||||||
* @param BigNumber $b
|
|
||||||
*
|
|
||||||
* @return BigNumber
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
private static function add(BigNumber $a, BigNumber $b) : BigNumber
|
private static function add(BigNumber $a, BigNumber $b) : BigNumber
|
||||||
{
|
{
|
||||||
@ -326,49 +329,34 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
return $b->plus($a);
|
return $b->plus($a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var BigInteger $a */
|
|
||||||
|
|
||||||
return $a->plus($b);
|
return $a->plus($b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes optional leading zeros and + sign from the given number.
|
* Removes optional leading zeros and applies sign.
|
||||||
*
|
*
|
||||||
* @param string $number The number, validated as a non-empty string of digits with optional leading sign.
|
* @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
|
||||||
|
* @param string $number The number, validated as a string of digits.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
private static function cleanUp(string $number) : string
|
private static function cleanUp(string|null $sign, string $number) : string
|
||||||
{
|
{
|
||||||
$firstChar = $number[0];
|
|
||||||
|
|
||||||
if ($firstChar === '+' || $firstChar === '-') {
|
|
||||||
$number = \substr($number, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$number = \ltrim($number, '0');
|
$number = \ltrim($number, '0');
|
||||||
|
|
||||||
if ($number === '') {
|
if ($number === '') {
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($firstChar === '-') {
|
return $sign === '-' ? '-' . $number : $number;
|
||||||
return '-' . $number;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this number is equal to the given one.
|
* Checks if this number is equal to the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* @pure
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isEqualTo($that) : bool
|
final public function isEqualTo(BigNumber|int|float|string $that) : bool
|
||||||
{
|
{
|
||||||
return $this->compareTo($that) === 0;
|
return $this->compareTo($that) === 0;
|
||||||
}
|
}
|
||||||
@ -376,11 +364,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is strictly lower than the given one.
|
* Checks if this number is strictly lower than the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* @pure
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isLessThan($that) : bool
|
final public function isLessThan(BigNumber|int|float|string $that) : bool
|
||||||
{
|
{
|
||||||
return $this->compareTo($that) < 0;
|
return $this->compareTo($that) < 0;
|
||||||
}
|
}
|
||||||
@ -388,11 +374,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is lower than or equal to the given one.
|
* Checks if this number is lower than or equal to the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* @pure
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isLessThanOrEqualTo($that) : bool
|
final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||||
{
|
{
|
||||||
return $this->compareTo($that) <= 0;
|
return $this->compareTo($that) <= 0;
|
||||||
}
|
}
|
||||||
@ -400,11 +384,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is strictly greater than the given one.
|
* Checks if this number is strictly greater than the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* @pure
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isGreaterThan($that) : bool
|
final public function isGreaterThan(BigNumber|int|float|string $that) : bool
|
||||||
{
|
{
|
||||||
return $this->compareTo($that) > 0;
|
return $this->compareTo($that) > 0;
|
||||||
}
|
}
|
||||||
@ -412,11 +394,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is greater than or equal to the given one.
|
* Checks if this number is greater than or equal to the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* @pure
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function isGreaterThanOrEqualTo($that) : bool
|
final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||||
{
|
{
|
||||||
return $this->compareTo($that) >= 0;
|
return $this->compareTo($that) >= 0;
|
||||||
}
|
}
|
||||||
@ -424,9 +404,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number equals zero.
|
* Checks if this number equals zero.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isZero() : bool
|
final public function isZero() : bool
|
||||||
{
|
{
|
||||||
return $this->getSign() === 0;
|
return $this->getSign() === 0;
|
||||||
}
|
}
|
||||||
@ -434,9 +414,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is strictly negative.
|
* Checks if this number is strictly negative.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isNegative() : bool
|
final public function isNegative() : bool
|
||||||
{
|
{
|
||||||
return $this->getSign() < 0;
|
return $this->getSign() < 0;
|
||||||
}
|
}
|
||||||
@ -444,9 +424,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is negative or zero.
|
* Checks if this number is negative or zero.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isNegativeOrZero() : bool
|
final public function isNegativeOrZero() : bool
|
||||||
{
|
{
|
||||||
return $this->getSign() <= 0;
|
return $this->getSign() <= 0;
|
||||||
}
|
}
|
||||||
@ -454,9 +434,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is strictly positive.
|
* Checks if this number is strictly positive.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isPositive() : bool
|
final public function isPositive() : bool
|
||||||
{
|
{
|
||||||
return $this->getSign() > 0;
|
return $this->getSign() > 0;
|
||||||
}
|
}
|
||||||
@ -464,9 +444,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Checks if this number is positive or zero.
|
* Checks if this number is positive or zero.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function isPositiveOrZero() : bool
|
final public function isPositiveOrZero() : bool
|
||||||
{
|
{
|
||||||
return $this->getSign() >= 0;
|
return $this->getSign() >= 0;
|
||||||
}
|
}
|
||||||
@ -474,58 +454,64 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
/**
|
/**
|
||||||
* Returns the sign of this number.
|
* Returns the sign of this number.
|
||||||
*
|
*
|
||||||
* @return int -1 if the number is negative, 0 if zero, 1 if positive.
|
* Returns -1 if the number is negative, 0 if zero, 1 if positive.
|
||||||
|
*
|
||||||
|
* @return -1|0|1
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function getSign() : int;
|
abstract public function getSign() : int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares this number to the given one.
|
* Compares this number to the given one.
|
||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that
|
* Returns -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`.
|
||||||
*
|
*
|
||||||
* @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
|
* @return -1|0|1
|
||||||
*
|
*
|
||||||
* @throws MathException If the number is not valid.
|
* @throws MathException If the number is not valid.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function compareTo($that) : int;
|
abstract public function compareTo(BigNumber|int|float|string $that) : int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this number to a BigInteger.
|
* Converts this number to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigInteger The converted number.
|
|
||||||
*
|
|
||||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toBigInteger() : BigInteger;
|
abstract public function toBigInteger() : BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this number to a BigDecimal.
|
* Converts this number to a BigDecimal.
|
||||||
*
|
*
|
||||||
* @return BigDecimal The converted number.
|
|
||||||
*
|
|
||||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toBigDecimal() : BigDecimal;
|
abstract public function toBigDecimal() : BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this number to a BigRational.
|
* Converts this number to a BigRational.
|
||||||
*
|
*
|
||||||
* @return BigRational The converted number.
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toBigRational() : BigRational;
|
abstract public function toBigRational() : BigRational;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
|
* 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 $scale The scale of the resulting `BigDecimal`.
|
||||||
* @param int $roundingMode A `RoundingMode` constant.
|
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||||
*
|
|
||||||
* @return BigDecimal
|
|
||||||
*
|
*
|
||||||
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
||||||
* This only applies when RoundingMode::UNNECESSARY is used.
|
* This only applies when RoundingMode::UNNECESSARY is used.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the exact value of this number as a native integer.
|
* Returns the exact value of this number as a native integer.
|
||||||
@ -533,9 +519,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
|
* 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.
|
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
|
||||||
*
|
*
|
||||||
* @return int The converted value.
|
|
||||||
*
|
|
||||||
* @throws MathException If this number cannot be exactly converted to a native integer.
|
* @throws MathException If this number cannot be exactly converted to a native integer.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toInt() : int;
|
abstract public function toInt() : int;
|
||||||
|
|
||||||
@ -548,7 +534,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* If the number is greater than the largest representable floating point number, positive infinity is returned.
|
* 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.
|
* If the number is less than the smallest representable floating point number, negative infinity is returned.
|
||||||
*
|
*
|
||||||
* @return float The converted value.
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function toFloat() : float;
|
abstract public function toFloat() : float;
|
||||||
|
|
||||||
@ -558,14 +544,12 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
|||||||
* The output of this method can be parsed by the `of()` factory method;
|
* 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.
|
* this will yield an object equal to this one, without any information loss.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function __toString() : string;
|
abstract public function __toString() : string;
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
final public function jsonSerialize() : string
|
||||||
*/
|
|
||||||
public function jsonSerialize() : string
|
|
||||||
{
|
{
|
||||||
return $this->__toString();
|
return $this->__toString();
|
||||||
}
|
}
|
||||||
|
|||||||
206
vendor/brick/math/src/BigRational.php
vendored
206
vendor/brick/math/src/BigRational.php
vendored
@ -8,29 +8,24 @@ use Brick\Math\Exception\DivisionByZeroException;
|
|||||||
use Brick\Math\Exception\MathException;
|
use Brick\Math\Exception\MathException;
|
||||||
use Brick\Math\Exception\NumberFormatException;
|
use Brick\Math\Exception\NumberFormatException;
|
||||||
use Brick\Math\Exception\RoundingNecessaryException;
|
use Brick\Math\Exception\RoundingNecessaryException;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An arbitrarily large rational number.
|
* An arbitrarily large rational number.
|
||||||
*
|
*
|
||||||
* This class is immutable.
|
* This class is immutable.
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
final class BigRational extends BigNumber
|
final readonly class BigRational extends BigNumber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The numerator.
|
* The numerator.
|
||||||
*
|
|
||||||
* @var BigInteger
|
|
||||||
*/
|
*/
|
||||||
private $numerator;
|
private BigInteger $numerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The denominator. Always strictly positive.
|
* The denominator. Always strictly positive.
|
||||||
*
|
|
||||||
* @var BigInteger
|
|
||||||
*/
|
*/
|
||||||
private $denominator;
|
private BigInteger $denominator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected constructor. Use a factory method to obtain an instance.
|
* Protected constructor. Use a factory method to obtain an instance.
|
||||||
@ -40,6 +35,8 @@ final class BigRational extends BigNumber
|
|||||||
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
|
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
|
||||||
*
|
*
|
||||||
* @throws DivisionByZeroException If the denominator is zero.
|
* @throws DivisionByZeroException If the denominator is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
|
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
|
||||||
{
|
{
|
||||||
@ -58,20 +55,10 @@ final class BigRational extends BigNumber
|
|||||||
$this->denominator = $denominator;
|
$this->denominator = $denominator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* Creates a BigRational of the given value.
|
protected static function from(BigNumber $number): static
|
||||||
*
|
|
||||||
* @param BigNumber|int|float|string $value
|
|
||||||
*
|
|
||||||
* @return BigRational
|
|
||||||
*
|
|
||||||
* @throws MathException If the value cannot be converted to a BigRational.
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
|
||||||
public static function of($value) : BigNumber
|
|
||||||
{
|
{
|
||||||
return parent::of($value)->toBigRational();
|
return $number->toBigRational();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,16 +70,16 @@ final class BigRational extends BigNumber
|
|||||||
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
|
* @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.
|
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
|
||||||
*
|
|
||||||
* @throws NumberFormatException If an argument does not represent a valid number.
|
* @throws NumberFormatException If an argument does not represent a valid number.
|
||||||
* @throws RoundingNecessaryException If an argument represents a non-integer number.
|
* @throws RoundingNecessaryException If an argument represents a non-integer number.
|
||||||
* @throws DivisionByZeroException If the denominator is zero.
|
* @throws DivisionByZeroException If the denominator is zero.
|
||||||
*
|
*
|
||||||
* @psalm-pure
|
* @pure
|
||||||
*/
|
*/
|
||||||
public static function nd($numerator, $denominator) : BigRational
|
public static function nd(
|
||||||
{
|
BigNumber|int|float|string $numerator,
|
||||||
|
BigNumber|int|float|string $denominator,
|
||||||
|
) : BigRational {
|
||||||
$numerator = BigInteger::of($numerator);
|
$numerator = BigInteger::of($numerator);
|
||||||
$denominator = BigInteger::of($denominator);
|
$denominator = BigInteger::of($denominator);
|
||||||
|
|
||||||
@ -102,16 +89,11 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigRational representing zero.
|
* Returns a BigRational representing zero.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function zero() : BigRational
|
public static function zero() : BigRational
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigRational|null $zero */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigRational|null $zero
|
|
||||||
*/
|
|
||||||
static $zero;
|
static $zero;
|
||||||
|
|
||||||
if ($zero === null) {
|
if ($zero === null) {
|
||||||
@ -124,16 +106,11 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigRational representing one.
|
* Returns a BigRational representing one.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function one() : BigRational
|
public static function one() : BigRational
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigRational|null $one */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigRational|null $one
|
|
||||||
*/
|
|
||||||
static $one;
|
static $one;
|
||||||
|
|
||||||
if ($one === null) {
|
if ($one === null) {
|
||||||
@ -146,16 +123,11 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns a BigRational representing ten.
|
* Returns a BigRational representing ten.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function ten() : BigRational
|
public static function ten() : BigRational
|
||||||
{
|
{
|
||||||
/**
|
/** @var BigRational|null $ten */
|
||||||
* @psalm-suppress ImpureStaticVariable
|
|
||||||
* @var BigRational|null $ten
|
|
||||||
*/
|
|
||||||
static $ten;
|
static $ten;
|
||||||
|
|
||||||
if ($ten === null) {
|
if ($ten === null) {
|
||||||
@ -166,7 +138,7 @@ final class BigRational extends BigNumber
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getNumerator() : BigInteger
|
public function getNumerator() : BigInteger
|
||||||
{
|
{
|
||||||
@ -174,7 +146,7 @@ final class BigRational extends BigNumber
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function getDenominator() : BigInteger
|
public function getDenominator() : BigInteger
|
||||||
{
|
{
|
||||||
@ -184,7 +156,7 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the quotient of the division of the numerator by the denominator.
|
* Returns the quotient of the division of the numerator by the denominator.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotient() : BigInteger
|
public function quotient() : BigInteger
|
||||||
{
|
{
|
||||||
@ -194,7 +166,7 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the remainder of the division of the numerator by the denominator.
|
* Returns the remainder of the division of the numerator by the denominator.
|
||||||
*
|
*
|
||||||
* @return BigInteger
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function remainder() : BigInteger
|
public function remainder() : BigInteger
|
||||||
{
|
{
|
||||||
@ -204,7 +176,9 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
||||||
*
|
*
|
||||||
* @return BigInteger[]
|
* @return array{BigInteger, BigInteger}
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function quotientAndRemainder() : array
|
public function quotientAndRemainder() : array
|
||||||
{
|
{
|
||||||
@ -216,11 +190,11 @@ final class BigRational extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to add.
|
* @param BigNumber|int|float|string $that The number to add.
|
||||||
*
|
*
|
||||||
* @return BigRational The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid.
|
* @throws MathException If the number is not valid.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function plus($that) : BigRational
|
public function plus(BigNumber|int|float|string $that) : BigRational
|
||||||
{
|
{
|
||||||
$that = BigRational::of($that);
|
$that = BigRational::of($that);
|
||||||
|
|
||||||
@ -236,11 +210,11 @@ final class BigRational extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The number to subtract.
|
* @param BigNumber|int|float|string $that The number to subtract.
|
||||||
*
|
*
|
||||||
* @return BigRational The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the number is not valid.
|
* @throws MathException If the number is not valid.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function minus($that) : BigRational
|
public function minus(BigNumber|int|float|string $that) : BigRational
|
||||||
{
|
{
|
||||||
$that = BigRational::of($that);
|
$that = BigRational::of($that);
|
||||||
|
|
||||||
@ -256,11 +230,11 @@ final class BigRational extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The multiplier.
|
* @param BigNumber|int|float|string $that The multiplier.
|
||||||
*
|
*
|
||||||
* @return BigRational The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the multiplier is not a valid number.
|
* @throws MathException If the multiplier is not a valid number.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function multipliedBy($that) : BigRational
|
public function multipliedBy(BigNumber|int|float|string $that) : BigRational
|
||||||
{
|
{
|
||||||
$that = BigRational::of($that);
|
$that = BigRational::of($that);
|
||||||
|
|
||||||
@ -275,11 +249,11 @@ final class BigRational extends BigNumber
|
|||||||
*
|
*
|
||||||
* @param BigNumber|int|float|string $that The divisor.
|
* @param BigNumber|int|float|string $that The divisor.
|
||||||
*
|
*
|
||||||
* @return BigRational The result.
|
|
||||||
*
|
|
||||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function dividedBy($that) : BigRational
|
public function dividedBy(BigNumber|int|float|string $that) : BigRational
|
||||||
{
|
{
|
||||||
$that = BigRational::of($that);
|
$that = BigRational::of($that);
|
||||||
|
|
||||||
@ -292,11 +266,9 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns this number exponentiated to the given value.
|
* Returns this number exponentiated to the given value.
|
||||||
*
|
*
|
||||||
* @param int $exponent The exponent.
|
|
||||||
*
|
|
||||||
* @return BigRational The result.
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function power(int $exponent) : BigRational
|
public function power(int $exponent) : BigRational
|
||||||
{
|
{
|
||||||
@ -322,9 +294,9 @@ final class BigRational extends BigNumber
|
|||||||
*
|
*
|
||||||
* The reciprocal has the numerator and denominator swapped.
|
* The reciprocal has the numerator and denominator swapped.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
|
||||||
*
|
|
||||||
* @throws DivisionByZeroException If the numerator is zero.
|
* @throws DivisionByZeroException If the numerator is zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function reciprocal() : BigRational
|
public function reciprocal() : BigRational
|
||||||
{
|
{
|
||||||
@ -334,7 +306,7 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the absolute value of this BigRational.
|
* Returns the absolute value of this BigRational.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function abs() : BigRational
|
public function abs() : BigRational
|
||||||
{
|
{
|
||||||
@ -344,7 +316,7 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the negated value of this BigRational.
|
* Returns the negated value of this BigRational.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function negated() : BigRational
|
public function negated() : BigRational
|
||||||
{
|
{
|
||||||
@ -354,7 +326,7 @@ final class BigRational extends BigNumber
|
|||||||
/**
|
/**
|
||||||
* Returns the simplified value of this BigRational.
|
* Returns the simplified value of this BigRational.
|
||||||
*
|
*
|
||||||
* @return BigRational
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function simplified() : BigRational
|
public function simplified() : BigRational
|
||||||
{
|
{
|
||||||
@ -366,25 +338,19 @@ final class BigRational extends BigNumber
|
|||||||
return new BigRational($numerator, $denominator, false);
|
return new BigRational($numerator, $denominator, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function compareTo(BigNumber|int|float|string $that) : int
|
||||||
*/
|
|
||||||
public function compareTo($that) : int
|
|
||||||
{
|
{
|
||||||
return $this->minus($that)->getSign();
|
return $this->minus($that)->getSign();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getSign() : int
|
public function getSign() : int
|
||||||
{
|
{
|
||||||
return $this->numerator->getSign();
|
return $this->numerator->getSign();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigInteger() : BigInteger
|
public function toBigInteger() : BigInteger
|
||||||
{
|
{
|
||||||
$simplified = $this->simplified();
|
$simplified = $this->simplified();
|
||||||
@ -396,49 +362,38 @@ final class BigRational extends BigNumber
|
|||||||
return $simplified->numerator;
|
return $simplified->numerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigDecimal() : BigDecimal
|
public function toBigDecimal() : BigDecimal
|
||||||
{
|
{
|
||||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBigRational() : BigRational
|
public function toBigRational() : BigRational
|
||||||
{
|
{
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||||
*/
|
|
||||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
|
||||||
{
|
{
|
||||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toInt() : int
|
public function toInt() : int
|
||||||
{
|
{
|
||||||
return $this->toBigInteger()->toInt();
|
return $this->toBigInteger()->toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toFloat() : float
|
public function toFloat() : float
|
||||||
{
|
{
|
||||||
return $this->numerator->toFloat() / $this->denominator->toFloat();
|
$simplified = $this->simplified();
|
||||||
|
return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __toString() : string
|
public function __toString() : string
|
||||||
{
|
{
|
||||||
$numerator = (string) $this->numerator;
|
$numerator = (string) $this->numerator;
|
||||||
@ -448,7 +403,7 @@ final class BigRational extends BigNumber
|
|||||||
return $numerator;
|
return $numerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->numerator . '/' . $this->denominator;
|
return $numerator . '/' . $denominator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -467,57 +422,20 @@ final class BigRational extends BigNumber
|
|||||||
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
* This method is only here to allow unserializing the object and cannot be accessed directly.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
|
||||||
*
|
*
|
||||||
* @param array{numerator: BigInteger, denominator: BigInteger} $data
|
* @param array{numerator: BigInteger, denominator: BigInteger} $data
|
||||||
*
|
*
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws \LogicException
|
* @throws \LogicException
|
||||||
*/
|
*/
|
||||||
public function __unserialize(array $data): void
|
public function __unserialize(array $data): void
|
||||||
{
|
{
|
||||||
|
/** @phpstan-ignore isset.initializedProperty */
|
||||||
if (isset($this->numerator)) {
|
if (isset($this->numerator)) {
|
||||||
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @phpstan-ignore deadCode.unreachable */
|
||||||
$this->numerator = $data['numerator'];
|
$this->numerator = $data['numerator'];
|
||||||
$this->denominator = $data['denominator'];
|
$this->denominator = $data['denominator'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
|
|||||||
/**
|
/**
|
||||||
* Exception thrown when a division by zero occurs.
|
* Exception thrown when a division by zero occurs.
|
||||||
*/
|
*/
|
||||||
class DivisionByZeroException extends MathException
|
final class DivisionByZeroException extends MathException
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return DivisionByZeroException
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function divisionByZero() : DivisionByZeroException
|
public static function divisionByZero() : DivisionByZeroException
|
||||||
{
|
{
|
||||||
@ -20,9 +18,7 @@ class DivisionByZeroException extends MathException
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return DivisionByZeroException
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function modulusMustNotBeZero() : DivisionByZeroException
|
public static function modulusMustNotBeZero() : DivisionByZeroException
|
||||||
{
|
{
|
||||||
@ -30,9 +26,7 @@ class DivisionByZeroException extends MathException
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return DivisionByZeroException
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,14 +9,10 @@ use Brick\Math\BigInteger;
|
|||||||
/**
|
/**
|
||||||
* Exception thrown when an integer overflow occurs.
|
* Exception thrown when an integer overflow occurs.
|
||||||
*/
|
*/
|
||||||
class IntegerOverflowException extends MathException
|
final class IntegerOverflowException extends MathException
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param BigInteger $value
|
* @pure
|
||||||
*
|
|
||||||
* @return IntegerOverflowException
|
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
|
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,8 +6,6 @@ namespace Brick\Math\Exception;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all math exceptions.
|
* Base class for all math exceptions.
|
||||||
*
|
|
||||||
* This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
|
|
||||||
*/
|
*/
|
||||||
class MathException extends \RuntimeException
|
class MathException extends \RuntimeException
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,6 +7,6 @@ namespace Brick\Math\Exception;
|
|||||||
/**
|
/**
|
||||||
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
|
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
|
||||||
*/
|
*/
|
||||||
class NegativeNumberException extends MathException
|
final class NegativeNumberException extends MathException
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,14 +7,23 @@ namespace Brick\Math\Exception;
|
|||||||
/**
|
/**
|
||||||
* Exception thrown when attempting to create a number from a string with an invalid format.
|
* Exception thrown when attempting to create a number from a string with an invalid format.
|
||||||
*/
|
*/
|
||||||
class NumberFormatException extends MathException
|
final class NumberFormatException extends MathException
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @pure
|
||||||
|
*/
|
||||||
|
public static function invalidFormat(string $value) : self
|
||||||
|
{
|
||||||
|
return new self(\sprintf(
|
||||||
|
'The given value "%s" does not represent a valid number.',
|
||||||
|
$value,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $char The failing character.
|
* @param string $char The failing character.
|
||||||
*
|
*
|
||||||
* @return NumberFormatException
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function charNotInAlphabet(string $char) : self
|
public static function charNotInAlphabet(string $char) : self
|
||||||
{
|
{
|
||||||
@ -30,6 +39,6 @@ class NumberFormatException extends MathException
|
|||||||
$char = '"' . $char . '"';
|
$char = '"' . $char . '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,10 @@ namespace Brick\Math\Exception;
|
|||||||
/**
|
/**
|
||||||
* Exception thrown when a number cannot be represented at the requested scale without rounding.
|
* Exception thrown when a number cannot be represented at the requested scale without rounding.
|
||||||
*/
|
*/
|
||||||
class RoundingNecessaryException extends MathException
|
final class RoundingNecessaryException extends MathException
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return RoundingNecessaryException
|
* @pure
|
||||||
*
|
|
||||||
* @psalm-pure
|
|
||||||
*/
|
*/
|
||||||
public static function roundingNecessary() : RoundingNecessaryException
|
public static function roundingNecessary() : RoundingNecessaryException
|
||||||
{
|
{
|
||||||
|
|||||||
235
vendor/brick/math/src/Internal/Calculator.php
vendored
235
vendor/brick/math/src/Internal/Calculator.php
vendored
@ -17,89 +17,25 @@ use Brick\Math\RoundingMode;
|
|||||||
* All methods must return strings respecting this format, unless specified otherwise.
|
* All methods must return strings respecting this format, unless specified otherwise.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
abstract class Calculator
|
abstract readonly class Calculator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The maximum exponent value allowed for the pow() method.
|
* The maximum exponent value allowed for the pow() method.
|
||||||
*/
|
*/
|
||||||
public const MAX_POWER = 1000000;
|
public const MAX_POWER = 1_000_000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The alphabet for converting from and to base 2 to 36, lowercase.
|
* The alphabet for converting from and to base 2 to 36, lowercase.
|
||||||
*/
|
*/
|
||||||
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
|
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||||
|
|
||||||
/**
|
|
||||||
* The Calculator instance in use.
|
|
||||||
*
|
|
||||||
* @var Calculator|null
|
|
||||||
*/
|
|
||||||
private static $instance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @return Calculator
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
*
|
|
||||||
* @return Calculator
|
|
||||||
*/
|
|
||||||
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.
|
* Extracts the sign & digits of the operands.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
|
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
final protected function init(string $a, string $b) : array
|
final protected function init(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
@ -115,9 +51,7 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* Returns the absolute value of a number.
|
* Returns the absolute value of a number.
|
||||||
*
|
*
|
||||||
* @param string $n The number.
|
* @pure
|
||||||
*
|
|
||||||
* @return string The absolute value.
|
|
||||||
*/
|
*/
|
||||||
final public function abs(string $n) : string
|
final public function abs(string $n) : string
|
||||||
{
|
{
|
||||||
@ -127,9 +61,7 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* Negates a number.
|
* Negates a number.
|
||||||
*
|
*
|
||||||
* @param string $n The number.
|
* @pure
|
||||||
*
|
|
||||||
* @return string The negated value.
|
|
||||||
*/
|
*/
|
||||||
final public function neg(string $n) : string
|
final public function neg(string $n) : string
|
||||||
{
|
{
|
||||||
@ -147,10 +79,11 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* Compares two numbers.
|
* Compares two numbers.
|
||||||
*
|
*
|
||||||
* @param string $a The first number.
|
* Returns -1 if the first number is less than, 0 if equal to, 1 if greater than the second number.
|
||||||
* @param string $b The second number.
|
|
||||||
*
|
*
|
||||||
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
|
* @return -1|0|1
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
final public function cmp(string $a, string $b) : int
|
final public function cmp(string $a, string $b) : int
|
||||||
{
|
{
|
||||||
@ -181,30 +114,21 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* Adds two numbers.
|
* Adds two numbers.
|
||||||
*
|
*
|
||||||
* @param string $a The augend.
|
* @pure
|
||||||
* @param string $b The addend.
|
|
||||||
*
|
|
||||||
* @return string The sum.
|
|
||||||
*/
|
*/
|
||||||
abstract public function add(string $a, string $b) : string;
|
abstract public function add(string $a, string $b) : string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtracts two numbers.
|
* Subtracts two numbers.
|
||||||
*
|
*
|
||||||
* @param string $a The minuend.
|
* @pure
|
||||||
* @param string $b The subtrahend.
|
|
||||||
*
|
|
||||||
* @return string The difference.
|
|
||||||
*/
|
*/
|
||||||
abstract public function sub(string $a, string $b) : string;
|
abstract public function sub(string $a, string $b) : string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies two numbers.
|
* Multiplies two numbers.
|
||||||
*
|
*
|
||||||
* @param string $a The multiplicand.
|
* @pure
|
||||||
* @param string $b The multiplier.
|
|
||||||
*
|
|
||||||
* @return string The product.
|
|
||||||
*/
|
*/
|
||||||
abstract public function mul(string $a, string $b) : string;
|
abstract public function mul(string $a, string $b) : string;
|
||||||
|
|
||||||
@ -215,6 +139,8 @@ abstract class Calculator
|
|||||||
* @param string $b The divisor, must not be zero.
|
* @param string $b The divisor, must not be zero.
|
||||||
*
|
*
|
||||||
* @return string The quotient.
|
* @return string The quotient.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function divQ(string $a, string $b) : string;
|
abstract public function divQ(string $a, string $b) : string;
|
||||||
|
|
||||||
@ -225,6 +151,8 @@ abstract class Calculator
|
|||||||
* @param string $b The divisor, must not be zero.
|
* @param string $b The divisor, must not be zero.
|
||||||
*
|
*
|
||||||
* @return string The remainder.
|
* @return string The remainder.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function divR(string $a, string $b) : string;
|
abstract public function divR(string $a, string $b) : string;
|
||||||
|
|
||||||
@ -234,7 +162,9 @@ abstract class Calculator
|
|||||||
* @param string $a The dividend.
|
* @param string $a The dividend.
|
||||||
* @param string $b The divisor, must not be zero.
|
* @param string $b The divisor, must not be zero.
|
||||||
*
|
*
|
||||||
* @return string[] An array containing the quotient and remainder.
|
* @return array{string, string} An array containing the quotient and remainder.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function divQR(string $a, string $b) : array;
|
abstract public function divQR(string $a, string $b) : array;
|
||||||
|
|
||||||
@ -245,14 +175,15 @@ abstract class Calculator
|
|||||||
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
|
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
|
||||||
*
|
*
|
||||||
* @return string The power.
|
* @return string The power.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function pow(string $a, int $e) : string;
|
abstract public function pow(string $a, int $e) : string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $a
|
|
||||||
* @param string $b The modulus; must not be zero.
|
* @param string $b The modulus; must not be zero.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function mod(string $a, string $b) : string
|
public function mod(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -266,10 +197,9 @@ abstract class Calculator
|
|||||||
*
|
*
|
||||||
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
|
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
|
||||||
*
|
*
|
||||||
* @param string $x
|
|
||||||
* @param string $m The modulus; must not be negative or zero.
|
* @param string $m The modulus; must not be negative or zero.
|
||||||
*
|
*
|
||||||
* @return string|null
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function modInverse(string $x, string $m) : ?string
|
public function modInverse(string $x, string $m) : ?string
|
||||||
{
|
{
|
||||||
@ -283,9 +213,7 @@ abstract class Calculator
|
|||||||
$modVal = $this->mod($x, $m);
|
$modVal = $this->mod($x, $m);
|
||||||
}
|
}
|
||||||
|
|
||||||
$x = '0';
|
[$g, $x] = $this->gcdExtended($modVal, $m);
|
||||||
$y = '0';
|
|
||||||
$g = $this->gcdExtended($modVal, $m, $x, $y);
|
|
||||||
|
|
||||||
if ($g !== '1') {
|
if ($g !== '1') {
|
||||||
return null;
|
return null;
|
||||||
@ -301,7 +229,7 @@ abstract class Calculator
|
|||||||
* @param string $exp The exponent; must be positive or zero.
|
* @param string $exp The exponent; must be positive or zero.
|
||||||
* @param string $mod The modulus; must be strictly positive.
|
* @param string $mod The modulus; must be strictly positive.
|
||||||
*
|
*
|
||||||
* @return string The power.
|
* @pure
|
||||||
*/
|
*/
|
||||||
abstract public function modPow(string $base, string $exp, string $mod) : string;
|
abstract public function modPow(string $base, string $exp, string $mod) : string;
|
||||||
|
|
||||||
@ -311,10 +239,9 @@ abstract class Calculator
|
|||||||
* This method can be overridden by the concrete implementation if the underlying library
|
* This method can be overridden by the concrete implementation if the underlying library
|
||||||
* has built-in support for GCD calculations.
|
* has built-in support for GCD calculations.
|
||||||
*
|
*
|
||||||
* @param string $a The first number.
|
|
||||||
* @param string $b The second number.
|
|
||||||
*
|
|
||||||
* @return string The GCD, always positive, or zero if both arguments are zero.
|
* @return string The GCD, always positive, or zero if both arguments are zero.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function gcd(string $a, string $b) : string
|
public function gcd(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -329,24 +256,23 @@ abstract class Calculator
|
|||||||
return $this->gcd($b, $this->divR($a, $b));
|
return $this->gcd($b, $this->divR($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function gcdExtended(string $a, string $b, string &$x, string &$y) : string
|
/**
|
||||||
|
* @return array{string, string, string} GCD, X, Y
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
*/
|
||||||
|
private function gcdExtended(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
if ($a === '0') {
|
if ($a === '0') {
|
||||||
$x = '0';
|
return [$b, '0', '1'];
|
||||||
$y = '1';
|
|
||||||
|
|
||||||
return $b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$x1 = '0';
|
[$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
|
||||||
$y1 = '0';
|
|
||||||
|
|
||||||
$gcd = $this->gcdExtended($this->mod($b, $a), $a, $x1, $y1);
|
|
||||||
|
|
||||||
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
|
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
|
||||||
$y = $x1;
|
$y = $x1;
|
||||||
|
|
||||||
return $gcd;
|
return [$gcd, $x, $y];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,9 +281,7 @@ abstract class Calculator
|
|||||||
* The result is the largest x such that x² ≤ n.
|
* The result is the largest x such that x² ≤ n.
|
||||||
* The input MUST NOT be negative.
|
* The input MUST NOT be negative.
|
||||||
*
|
*
|
||||||
* @param string $n The number.
|
* @pure
|
||||||
*
|
|
||||||
* @return string The square root.
|
|
||||||
*/
|
*/
|
||||||
abstract public function sqrt(string $n) : string;
|
abstract public function sqrt(string $n) : string;
|
||||||
|
|
||||||
@ -371,6 +295,8 @@ abstract class Calculator
|
|||||||
* @param int $base The base of the number, validated from 2 to 36.
|
* @param int $base The base of the number, validated from 2 to 36.
|
||||||
*
|
*
|
||||||
* @return string The converted number, following the Calculator conventions.
|
* @return string The converted number, following the Calculator conventions.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function fromBase(string $number, int $base) : string
|
public function fromBase(string $number, int $base) : string
|
||||||
{
|
{
|
||||||
@ -387,6 +313,8 @@ abstract class Calculator
|
|||||||
* @param int $base The base to convert to, validated from 2 to 36.
|
* @param int $base The base to convert to, validated from 2 to 36.
|
||||||
*
|
*
|
||||||
* @return string The converted number, lowercase.
|
* @return string The converted number, lowercase.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
public function toBase(string $number, int $base) : string
|
public function toBase(string $number, int $base) : string
|
||||||
{
|
{
|
||||||
@ -414,6 +342,8 @@ abstract class Calculator
|
|||||||
* @param int $base The base of the number, validated from 2 to alphabet length.
|
* @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.
|
* @return string The number in base 10, following the Calculator conventions.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
|
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||||
{
|
{
|
||||||
@ -460,6 +390,8 @@ abstract class Calculator
|
|||||||
* @param int $base The base to convert to, validated from 2 to alphabet length.
|
* @param int $base The base to convert to, validated from 2 to alphabet length.
|
||||||
*
|
*
|
||||||
* @return string The converted number in the given alphabet.
|
* @return string The converted number in the given alphabet.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
|
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||||
{
|
{
|
||||||
@ -485,16 +417,15 @@ abstract class Calculator
|
|||||||
*
|
*
|
||||||
* Rounding is performed when the remainder of the division is not zero.
|
* Rounding is performed when the remainder of the division is not zero.
|
||||||
*
|
*
|
||||||
* @param string $a The dividend.
|
* @param string $a The dividend.
|
||||||
* @param string $b The divisor, must not be zero.
|
* @param string $b The divisor, must not be zero.
|
||||||
* @param int $roundingMode The rounding mode.
|
* @param RoundingMode $roundingMode The rounding mode.
|
||||||
*
|
*
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
|
||||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
final public function divRound(string $a, string $b, int $roundingMode) : string
|
final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string
|
||||||
{
|
{
|
||||||
[$quotient, $remainder] = $this->divQR($a, $b);
|
[$quotient, $remainder] = $this->divQR($a, $b);
|
||||||
|
|
||||||
@ -553,9 +484,6 @@ abstract class Calculator
|
|||||||
$lastDigitIsEven = ($lastDigit % 2 === 0);
|
$lastDigitIsEven = ($lastDigit % 2 === 0);
|
||||||
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
throw new \InvalidArgumentException('Invalid rounding mode.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($increment) {
|
if ($increment) {
|
||||||
@ -571,10 +499,7 @@ abstract class Calculator
|
|||||||
* This method can be overridden by the concrete implementation if the underlying library
|
* This method can be overridden by the concrete implementation if the underlying library
|
||||||
* has built-in support for bitwise operations.
|
* has built-in support for bitwise operations.
|
||||||
*
|
*
|
||||||
* @param string $a
|
* @pure
|
||||||
* @param string $b
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function and(string $a, string $b) : string
|
public function and(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -587,10 +512,7 @@ abstract class Calculator
|
|||||||
* This method can be overridden by the concrete implementation if the underlying library
|
* This method can be overridden by the concrete implementation if the underlying library
|
||||||
* has built-in support for bitwise operations.
|
* has built-in support for bitwise operations.
|
||||||
*
|
*
|
||||||
* @param string $a
|
* @pure
|
||||||
* @param string $b
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function or(string $a, string $b) : string
|
public function or(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -603,10 +525,7 @@ abstract class Calculator
|
|||||||
* This method can be overridden by the concrete implementation if the underlying library
|
* This method can be overridden by the concrete implementation if the underlying library
|
||||||
* has built-in support for bitwise operations.
|
* has built-in support for bitwise operations.
|
||||||
*
|
*
|
||||||
* @param string $a
|
* @pure
|
||||||
* @param string $b
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function xor(string $a, string $b) : string
|
public function xor(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -616,11 +535,11 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* Performs a bitwise operation on a decimal number.
|
* Performs a bitwise operation on a decimal number.
|
||||||
*
|
*
|
||||||
* @param string $operator The operator to use, must be "and", "or" or "xor".
|
* @param 'and'|'or'|'xor' $operator The operator to use.
|
||||||
* @param string $a The left operand.
|
* @param string $a The left operand.
|
||||||
* @param string $b The right operand.
|
* @param string $b The right operand.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function bitwise(string $operator, string $a, string $b) : string
|
private function bitwise(string $operator, string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -645,27 +564,17 @@ abstract class Calculator
|
|||||||
$bBin = $this->twosComplement($bBin);
|
$bBin = $this->twosComplement($bBin);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($operator) {
|
$value = match ($operator) {
|
||||||
case 'and':
|
'and' => $aBin & $bBin,
|
||||||
$value = $aBin & $bBin;
|
'or' => $aBin | $bBin,
|
||||||
$negative = ($aNeg and $bNeg);
|
'xor' => $aBin ^ $bBin,
|
||||||
break;
|
};
|
||||||
|
|
||||||
case 'or':
|
$negative = match ($operator) {
|
||||||
$value = $aBin | $bBin;
|
'and' => $aNeg and $bNeg,
|
||||||
$negative = ($aNeg or $bNeg);
|
'or' => $aNeg or $bNeg,
|
||||||
break;
|
'xor' => $aNeg xor $bNeg,
|
||||||
|
};
|
||||||
case 'xor':
|
|
||||||
$value = $aBin ^ $bBin;
|
|
||||||
$negative = ($aNeg xor $bNeg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
default:
|
|
||||||
throw new \InvalidArgumentException('Invalid bitwise operator.');
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($negative) {
|
if ($negative) {
|
||||||
$value = $this->twosComplement($value);
|
$value = $this->twosComplement($value);
|
||||||
@ -679,7 +588,7 @@ abstract class Calculator
|
|||||||
/**
|
/**
|
||||||
* @param string $number A positive, binary number.
|
* @param string $number A positive, binary number.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function twosComplement(string $number) : string
|
private function twosComplement(string $number) : string
|
||||||
{
|
{
|
||||||
@ -710,7 +619,7 @@ abstract class Calculator
|
|||||||
*
|
*
|
||||||
* @param string $number The number to convert, positive or zero, only digits.
|
* @param string $number The number to convert, positive or zero, only digits.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function toBinary(string $number) : string
|
private function toBinary(string $number) : string
|
||||||
{
|
{
|
||||||
@ -729,7 +638,7 @@ abstract class Calculator
|
|||||||
*
|
*
|
||||||
* @param string $bytes The bytes representing the number.
|
* @param string $bytes The bytes representing the number.
|
||||||
*
|
*
|
||||||
* @return string
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function toDecimal(string $bytes) : string
|
private function toDecimal(string $bytes) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,110 +5,67 @@ declare(strict_types=1);
|
|||||||
namespace Brick\Math\Internal\Calculator;
|
namespace Brick\Math\Internal\Calculator;
|
||||||
|
|
||||||
use Brick\Math\Internal\Calculator;
|
use Brick\Math\Internal\Calculator;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculator implementation built around the bcmath library.
|
* Calculator implementation built around the bcmath library.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
class BcMathCalculator extends Calculator
|
final readonly class BcMathCalculator extends Calculator
|
||||||
{
|
{
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function add(string $a, string $b) : string
|
public function add(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \bcadd($a, $b, 0);
|
return \bcadd($a, $b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function sub(string $a, string $b) : string
|
public function sub(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \bcsub($a, $b, 0);
|
return \bcsub($a, $b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function mul(string $a, string $b) : string
|
public function mul(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \bcmul($a, $b, 0);
|
return \bcmul($a, $b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* @psalm-suppress InvalidNullableReturnType
|
|
||||||
* @psalm-suppress NullableReturnStatement
|
|
||||||
*/
|
|
||||||
public function divQ(string $a, string $b) : string
|
public function divQ(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \bcdiv($a, $b, 0);
|
return \bcdiv($a, $b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* @psalm-suppress InvalidNullableReturnType
|
|
||||||
* @psalm-suppress NullableReturnStatement
|
|
||||||
*/
|
|
||||||
public function divR(string $a, string $b) : string
|
public function divR(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
if (version_compare(PHP_VERSION, '7.2') >= 0) {
|
return \bcmod($a, $b, 0);
|
||||||
return \bcmod($a, $b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return \bcmod($a, $b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divQR(string $a, string $b) : array
|
public function divQR(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
$q = \bcdiv($a, $b, 0);
|
$q = \bcdiv($a, $b, 0);
|
||||||
|
$r = \bcmod($a, $b, 0);
|
||||||
if (version_compare(PHP_VERSION, '7.2') >= 0) {
|
|
||||||
$r = \bcmod($a, $b, 0);
|
|
||||||
} else {
|
|
||||||
$r = \bcmod($a, $b);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert($q !== null);
|
|
||||||
assert($r !== null);
|
|
||||||
|
|
||||||
return [$q, $r];
|
return [$q, $r];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function pow(string $a, int $e) : string
|
public function pow(string $a, int $e) : string
|
||||||
{
|
{
|
||||||
return \bcpow($a, (string) $e, 0);
|
return \bcpow($a, (string) $e, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* @psalm-suppress InvalidNullableReturnType
|
|
||||||
* @psalm-suppress NullableReturnStatement
|
|
||||||
*/
|
|
||||||
public function modPow(string $base, string $exp, string $mod) : string
|
public function modPow(string $base, string $exp, string $mod) : string
|
||||||
{
|
{
|
||||||
return \bcpowmod($base, $exp, $mod, 0);
|
return \bcpowmod($base, $exp, $mod, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
|
||||||
* @psalm-suppress NullableReturnStatement
|
|
||||||
* @psalm-suppress InvalidNullableReturnType
|
|
||||||
*/
|
|
||||||
public function sqrt(string $n) : string
|
public function sqrt(string $n) : string
|
||||||
{
|
{
|
||||||
return \bcsqrt($n, 0);
|
return \bcsqrt($n, 0);
|
||||||
|
|||||||
@ -5,80 +5,68 @@ declare(strict_types=1);
|
|||||||
namespace Brick\Math\Internal\Calculator;
|
namespace Brick\Math\Internal\Calculator;
|
||||||
|
|
||||||
use Brick\Math\Internal\Calculator;
|
use Brick\Math\Internal\Calculator;
|
||||||
|
use GMP;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculator implementation built around the GMP library.
|
* Calculator implementation built around the GMP library.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
class GmpCalculator extends Calculator
|
final readonly class GmpCalculator extends Calculator
|
||||||
{
|
{
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function add(string $a, string $b) : string
|
public function add(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_add($a, $b));
|
return \gmp_strval(\gmp_add($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function sub(string $a, string $b) : string
|
public function sub(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_sub($a, $b));
|
return \gmp_strval(\gmp_sub($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function mul(string $a, string $b) : string
|
public function mul(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_mul($a, $b));
|
return \gmp_strval(\gmp_mul($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divQ(string $a, string $b) : string
|
public function divQ(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_div_q($a, $b));
|
return \gmp_strval(\gmp_div_q($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divR(string $a, string $b) : string
|
public function divR(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_div_r($a, $b));
|
return \gmp_strval(\gmp_div_r($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divQR(string $a, string $b) : array
|
public function divQR(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
[$q, $r] = \gmp_div_qr($a, $b);
|
[$q, $r] = \gmp_div_qr($a, $b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var GMP $q
|
||||||
|
* @var GMP $r
|
||||||
|
*/
|
||||||
return [
|
return [
|
||||||
\gmp_strval($q),
|
\gmp_strval($q),
|
||||||
\gmp_strval($r)
|
\gmp_strval($r)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function pow(string $a, int $e) : string
|
public function pow(string $a, int $e) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_pow($a, $e));
|
return \gmp_strval(\gmp_pow($a, $e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function modInverse(string $x, string $m) : ?string
|
public function modInverse(string $x, string $m) : ?string
|
||||||
{
|
{
|
||||||
$result = \gmp_invert($x, $m);
|
$result = \gmp_invert($x, $m);
|
||||||
@ -90,65 +78,49 @@ class GmpCalculator extends Calculator
|
|||||||
return \gmp_strval($result);
|
return \gmp_strval($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function modPow(string $base, string $exp, string $mod) : string
|
public function modPow(string $base, string $exp, string $mod) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function gcd(string $a, string $b) : string
|
public function gcd(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_gcd($a, $b));
|
return \gmp_strval(\gmp_gcd($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function fromBase(string $number, int $base) : string
|
public function fromBase(string $number, int $base) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_init($number, $base));
|
return \gmp_strval(\gmp_init($number, $base));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function toBase(string $number, int $base) : string
|
public function toBase(string $number, int $base) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval($number, $base);
|
return \gmp_strval($number, $base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function and(string $a, string $b) : string
|
public function and(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_and($a, $b));
|
return \gmp_strval(\gmp_and($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function or(string $a, string $b) : string
|
public function or(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_or($a, $b));
|
return \gmp_strval(\gmp_or($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function xor(string $a, string $b) : string
|
public function xor(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_xor($a, $b));
|
return \gmp_strval(\gmp_xor($a, $b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function sqrt(string $n) : string
|
public function sqrt(string $n) : string
|
||||||
{
|
{
|
||||||
return \gmp_strval(\gmp_sqrt($n));
|
return \gmp_strval(\gmp_sqrt($n));
|
||||||
|
|||||||
@ -5,57 +5,43 @@ declare(strict_types=1);
|
|||||||
namespace Brick\Math\Internal\Calculator;
|
namespace Brick\Math\Internal\Calculator;
|
||||||
|
|
||||||
use Brick\Math\Internal\Calculator;
|
use Brick\Math\Internal\Calculator;
|
||||||
|
use Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculator implementation using only native PHP code.
|
* Calculator implementation using only native PHP code.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*
|
|
||||||
* @psalm-immutable
|
|
||||||
*/
|
*/
|
||||||
class NativeCalculator extends Calculator
|
final readonly class NativeCalculator extends Calculator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
|
* 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.
|
* For multiplication, this represents the max sum of the lengths of both operands.
|
||||||
*
|
*
|
||||||
* For addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
|
* 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)
|
* 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)
|
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
*/
|
||||||
private $maxDigits;
|
private int $maxDigits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* @pure
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
switch (PHP_INT_SIZE) {
|
$this->maxDigits = match (PHP_INT_SIZE) {
|
||||||
case 4:
|
4 => 9,
|
||||||
$this->maxDigits = 9;
|
8 => 18,
|
||||||
break;
|
};
|
||||||
|
|
||||||
case 8:
|
|
||||||
$this->maxDigits = 18;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function add(string $a, string $b) : string
|
public function add(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @psalm-var numeric-string $a
|
* @var numeric-string $a
|
||||||
* @psalm-var numeric-string $b
|
* @var numeric-string $b
|
||||||
*/
|
*/
|
||||||
$result = $a + $b;
|
$result = $a + $b;
|
||||||
|
|
||||||
@ -82,22 +68,18 @@ class NativeCalculator extends Calculator
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function sub(string $a, string $b) : string
|
public function sub(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return $this->add($a, $this->neg($b));
|
return $this->add($a, $this->neg($b));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function mul(string $a, string $b) : string
|
public function mul(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @psalm-var numeric-string $a
|
* @var numeric-string $a
|
||||||
* @psalm-var numeric-string $b
|
* @var numeric-string $b
|
||||||
*/
|
*/
|
||||||
$result = $a * $b;
|
$result = $a * $b;
|
||||||
|
|
||||||
@ -136,25 +118,19 @@ class NativeCalculator extends Calculator
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divQ(string $a, string $b) : string
|
public function divQ(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
return $this->divQR($a, $b)[0];
|
return $this->divQR($a, $b)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divR(string $a, string $b): string
|
public function divR(string $a, string $b): string
|
||||||
{
|
{
|
||||||
return $this->divQR($a, $b)[1];
|
return $this->divQR($a, $b)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function divQR(string $a, string $b) : array
|
public function divQR(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
if ($a === '0') {
|
if ($a === '0') {
|
||||||
@ -173,20 +149,18 @@ class NativeCalculator extends Calculator
|
|||||||
return [$this->neg($a), '0'];
|
return [$this->neg($a), '0'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @psalm-var numeric-string $a */
|
/** @var numeric-string $a */
|
||||||
$na = $a * 1; // cast to number
|
$na = $a * 1; // cast to number
|
||||||
|
|
||||||
if (is_int($na)) {
|
if (is_int($na)) {
|
||||||
/** @psalm-var numeric-string $b */
|
/** @var numeric-string $b */
|
||||||
$nb = $b * 1;
|
$nb = $b * 1;
|
||||||
|
|
||||||
if (is_int($nb)) {
|
if (is_int($nb)) {
|
||||||
// the only division that may overflow is PHP_INT_MIN / -1,
|
// 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.
|
// which cannot happen here as we've already handled a divisor of -1 above.
|
||||||
|
$q = intdiv($na, $nb);
|
||||||
$r = $na % $nb;
|
$r = $na % $nb;
|
||||||
$q = ($na - $r) / $nb;
|
|
||||||
|
|
||||||
assert(is_int($q));
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(string) $q,
|
(string) $q,
|
||||||
@ -210,9 +184,7 @@ class NativeCalculator extends Calculator
|
|||||||
return [$q, $r];
|
return [$q, $r];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Override]
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function pow(string $a, int $e) : string
|
public function pow(string $a, int $e) : string
|
||||||
{
|
{
|
||||||
if ($e === 0) {
|
if ($e === 0) {
|
||||||
@ -228,7 +200,6 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
$aa = $this->mul($a, $a);
|
$aa = $this->mul($a, $a);
|
||||||
|
|
||||||
/** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
|
|
||||||
$result = $this->pow($aa, $e / 2);
|
$result = $this->pow($aa, $e / 2);
|
||||||
|
|
||||||
if ($odd === 1) {
|
if ($odd === 1) {
|
||||||
@ -240,9 +211,8 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
|
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
|
||||||
*
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
*/
|
||||||
|
#[Override]
|
||||||
public function modPow(string $base, string $exp, string $mod) : string
|
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)
|
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
|
||||||
@ -276,9 +246,8 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
|
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
|
||||||
*
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
*/
|
||||||
|
#[Override]
|
||||||
public function sqrt(string $n) : string
|
public function sqrt(string $n) : string
|
||||||
{
|
{
|
||||||
if ($n === '0') {
|
if ($n === '0') {
|
||||||
@ -307,10 +276,7 @@ class NativeCalculator extends Calculator
|
|||||||
/**
|
/**
|
||||||
* Performs the addition of two non-signed large integers.
|
* Performs the addition of two non-signed large integers.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
* @pure
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function doAdd(string $a, string $b) : string
|
private function doAdd(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -324,14 +290,13 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
if ($i < 0) {
|
if ($i < 0) {
|
||||||
$blockLength += $i;
|
$blockLength += $i;
|
||||||
/** @psalm-suppress LoopInvalidation */
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @psalm-var numeric-string $blockA */
|
/** @var numeric-string $blockA */
|
||||||
$blockA = \substr($a, $i, $blockLength);
|
$blockA = \substr($a, $i, $blockLength);
|
||||||
|
|
||||||
/** @psalm-var numeric-string $blockB */
|
/** @var numeric-string $blockB */
|
||||||
$blockB = \substr($b, $i, $blockLength);
|
$blockB = \substr($b, $i, $blockLength);
|
||||||
|
|
||||||
$sum = (string) ($blockA + $blockB + $carry);
|
$sum = (string) ($blockA + $blockB + $carry);
|
||||||
@ -364,10 +329,7 @@ class NativeCalculator extends Calculator
|
|||||||
/**
|
/**
|
||||||
* Performs the subtraction of two non-signed large integers.
|
* Performs the subtraction of two non-signed large integers.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
* @pure
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function doSub(string $a, string $b) : string
|
private function doSub(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -398,14 +360,13 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
if ($i < 0) {
|
if ($i < 0) {
|
||||||
$blockLength += $i;
|
$blockLength += $i;
|
||||||
/** @psalm-suppress LoopInvalidation */
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @psalm-var numeric-string $blockA */
|
/** @var numeric-string $blockA */
|
||||||
$blockA = \substr($a, $i, $blockLength);
|
$blockA = \substr($a, $i, $blockLength);
|
||||||
|
|
||||||
/** @psalm-var numeric-string $blockB */
|
/** @var numeric-string $blockB */
|
||||||
$blockB = \substr($b, $i, $blockLength);
|
$blockB = \substr($b, $i, $blockLength);
|
||||||
|
|
||||||
$sum = $blockA - $blockB - $carry;
|
$sum = $blockA - $blockB - $carry;
|
||||||
@ -446,10 +407,7 @@ class NativeCalculator extends Calculator
|
|||||||
/**
|
/**
|
||||||
* Performs the multiplication of two non-signed large integers.
|
* Performs the multiplication of two non-signed large integers.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
* @pure
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private function doMul(string $a, string $b) : string
|
private function doMul(string $a, string $b) : string
|
||||||
{
|
{
|
||||||
@ -466,7 +424,6 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
if ($i < 0) {
|
if ($i < 0) {
|
||||||
$blockALength += $i;
|
$blockALength += $i;
|
||||||
/** @psalm-suppress LoopInvalidation */
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +437,6 @@ class NativeCalculator extends Calculator
|
|||||||
|
|
||||||
if ($j < 0) {
|
if ($j < 0) {
|
||||||
$blockBLength += $j;
|
$blockBLength += $j;
|
||||||
/** @psalm-suppress LoopInvalidation */
|
|
||||||
$j = 0;
|
$j = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,10 +478,9 @@ class NativeCalculator extends Calculator
|
|||||||
/**
|
/**
|
||||||
* Performs the division of two non-signed large integers.
|
* Performs the division of two non-signed large integers.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return string[] The quotient and remainder.
|
* @return string[] The quotient and remainder.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function doDiv(string $a, string $b) : array
|
private function doDiv(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
@ -544,6 +499,22 @@ class NativeCalculator extends Calculator
|
|||||||
$r = $a; // remainder
|
$r = $a; // remainder
|
||||||
$z = $y; // focus length, always $y or $y+1
|
$z = $y; // focus length, always $y or $y+1
|
||||||
|
|
||||||
|
/** @var numeric-string $b */
|
||||||
|
$nb = $b * 1; // cast to number
|
||||||
|
// performance optimization in cases where the remainder will never cause int overflow
|
||||||
|
if (is_int(($nb - 1) * 10 + 9)) {
|
||||||
|
$r = (int) \substr($a, 0, $z - 1);
|
||||||
|
|
||||||
|
for ($i = $z - 1; $i < $x; $i++) {
|
||||||
|
$n = $r * 10 + (int) $a[$i];
|
||||||
|
/** @var int $nb */
|
||||||
|
$q .= \intdiv($n, $nb);
|
||||||
|
$r = $n % $nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [\ltrim($q, '0') ?: '0', (string) $r];
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
$focus = \substr($a, 0, $z);
|
$focus = \substr($a, 0, $z);
|
||||||
|
|
||||||
@ -583,10 +554,9 @@ class NativeCalculator extends Calculator
|
|||||||
/**
|
/**
|
||||||
* Compares two non-signed large numbers.
|
* Compares two non-signed large numbers.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
* @return -1|0|1
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
*
|
||||||
* @return int [-1, 0, 1]
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function doCmp(string $a, string $b) : int
|
private function doCmp(string $a, string $b) : int
|
||||||
{
|
{
|
||||||
@ -599,7 +569,7 @@ class NativeCalculator extends Calculator
|
|||||||
return $cmp;
|
return $cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
|
return \strcmp($a, $b) <=> 0; // enforce -1|0|1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -607,10 +577,9 @@ class NativeCalculator extends Calculator
|
|||||||
*
|
*
|
||||||
* The numbers must only consist of digits, without leading minus sign.
|
* The numbers must only consist of digits, without leading minus sign.
|
||||||
*
|
*
|
||||||
* @param string $a The first operand.
|
|
||||||
* @param string $b The second operand.
|
|
||||||
*
|
|
||||||
* @return array{string, string, int}
|
* @return array{string, string, int}
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
*/
|
*/
|
||||||
private function pad(string $a, string $b) : array
|
private function pad(string $a, string $b) : array
|
||||||
{
|
{
|
||||||
|
|||||||
73
vendor/brick/math/src/Internal/CalculatorRegistry.php
vendored
Normal file
73
vendor/brick/math/src/Internal/CalculatorRegistry.php
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Brick\Math\Internal;
|
||||||
|
|
||||||
|
use function extension_loaded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the current Calculator instance used by BigNumber classes.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class CalculatorRegistry
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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: 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.
|
||||||
|
*
|
||||||
|
* Note: even though this method is not technically pure, it is considered pure when used in a normal context, when
|
||||||
|
* only relying on autodetect.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
*/
|
||||||
|
final public static function get() : Calculator
|
||||||
|
{
|
||||||
|
/** @phpstan-ignore impure.staticPropertyAccess */
|
||||||
|
if (self::$instance === null) {
|
||||||
|
/** @phpstan-ignore impure.propertyAssign */
|
||||||
|
self::$instance = self::detect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @phpstan-ignore impure.staticPropertyAccess */
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fastest available Calculator implementation.
|
||||||
|
*
|
||||||
|
* @pure
|
||||||
|
* @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();
|
||||||
|
}
|
||||||
|
}
|
||||||
31
vendor/brick/math/src/RoundingMode.php
vendored
31
vendor/brick/math/src/RoundingMode.php
vendored
@ -13,24 +13,15 @@ namespace Brick\Math;
|
|||||||
* regardless the digits' contribution to the value of the number. In other words, considered
|
* 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.
|
* as a numerical value, the discarded fraction could have an absolute value greater than one.
|
||||||
*/
|
*/
|
||||||
final class RoundingMode
|
enum 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.
|
* 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
|
* 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.
|
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
|
||||||
*/
|
*/
|
||||||
public const UNNECESSARY = 0;
|
case UNNECESSARY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds away from zero.
|
* Rounds away from zero.
|
||||||
@ -38,7 +29,7 @@ final class RoundingMode
|
|||||||
* Always increments the digit prior to a nonzero discarded fraction.
|
* Always increments the digit prior to a nonzero discarded fraction.
|
||||||
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
||||||
*/
|
*/
|
||||||
public const UP = 1;
|
case UP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards zero.
|
* Rounds towards zero.
|
||||||
@ -46,7 +37,7 @@ final class RoundingMode
|
|||||||
* Never increments the digit prior to a discarded fraction (i.e., truncates).
|
* 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.
|
* Note that this rounding mode never increases the magnitude of the calculated value.
|
||||||
*/
|
*/
|
||||||
public const DOWN = 2;
|
case DOWN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards positive infinity.
|
* Rounds towards positive infinity.
|
||||||
@ -54,7 +45,7 @@ final class RoundingMode
|
|||||||
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
|
* 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.
|
* Note that this rounding mode never decreases the calculated value.
|
||||||
*/
|
*/
|
||||||
public const CEILING = 3;
|
case CEILING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards negative infinity.
|
* Rounds towards negative infinity.
|
||||||
@ -62,7 +53,7 @@ final class RoundingMode
|
|||||||
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
|
* 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.
|
* Note that this rounding mode never increases the calculated value.
|
||||||
*/
|
*/
|
||||||
public const FLOOR = 4;
|
case FLOOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
||||||
@ -70,28 +61,28 @@ final class RoundingMode
|
|||||||
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
|
* 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.
|
* Note that this is the rounding mode commonly taught at school.
|
||||||
*/
|
*/
|
||||||
public const HALF_UP = 5;
|
case HALF_UP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
|
* 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.
|
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
|
||||||
*/
|
*/
|
||||||
public const HALF_DOWN = 6;
|
case HALF_DOWN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
|
* 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.
|
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
|
||||||
*/
|
*/
|
||||||
public const HALF_CEILING = 7;
|
case HALF_CEILING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
|
* 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.
|
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
|
||||||
*/
|
*/
|
||||||
public const HALF_FLOOR = 8;
|
case HALF_FLOOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
||||||
@ -103,5 +94,5 @@ final class RoundingMode
|
|||||||
* cumulative error when applied repeatedly over a sequence of calculations.
|
* 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.
|
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
|
||||||
*/
|
*/
|
||||||
public const HALF_EVEN = 9;
|
case HALF_EVEN;
|
||||||
}
|
}
|
||||||
|
|||||||
45
vendor/composer/InstalledVersions.php
vendored
45
vendor/composer/InstalledVersions.php
vendored
@ -26,12 +26,23 @@ use Composer\Semver\VersionParser;
|
|||||||
*/
|
*/
|
||||||
class InstalledVersions
|
class InstalledVersions
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
private static $selfDir = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var mixed[]|null
|
* @var mixed[]|null
|
||||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
*/
|
*/
|
||||||
private static $installed;
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $installedIsLocalDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool|null
|
* @var bool|null
|
||||||
*/
|
*/
|
||||||
@ -309,6 +320,24 @@ class InstalledVersions
|
|||||||
{
|
{
|
||||||
self::$installed = $data;
|
self::$installed = $data;
|
||||||
self::$installedByVendor = array();
|
self::$installedByVendor = array();
|
||||||
|
|
||||||
|
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||||
|
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||||
|
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||||
|
// all installed packages for example
|
||||||
|
self::$installedIsLocalDir = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function getSelfDir()
|
||||||
|
{
|
||||||
|
if (self::$selfDir === null) {
|
||||||
|
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$selfDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -322,19 +351,27 @@ class InstalledVersions
|
|||||||
}
|
}
|
||||||
|
|
||||||
$installed = array();
|
$installed = array();
|
||||||
|
$copiedLocalDir = false;
|
||||||
|
|
||||||
if (self::$canGetVendors) {
|
if (self::$canGetVendors) {
|
||||||
|
$selfDir = self::getSelfDir();
|
||||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
$installed[] = self::$installedByVendor[$vendorDir];
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
$required = require $vendorDir.'/composer/installed.php';
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
self::$installedByVendor[$vendorDir] = $required;
|
||||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
$installed[] = $required;
|
||||||
self::$installed = $installed[count($installed) - 1];
|
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
self::$installed = $required;
|
||||||
|
self::$installedIsLocalDir = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
$copiedLocalDir = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +387,7 @@ class InstalledVersions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::$installed !== array()) {
|
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||||
$installed[] = self::$installed;
|
$installed[] = self::$installed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
vendor/composer/autoload_classmap.php
vendored
7
vendor/composer/autoload_classmap.php
vendored
@ -6,11 +6,8 @@ $vendorDir = dirname(__DIR__);
|
|||||||
$baseDir = dirname($vendorDir);
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
|
||||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
|
||||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
|
||||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
|
||||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
|
||||||
'lessc' => $vendorDir . '/wikimedia/less.php/lessc.inc.php',
|
'lessc' => $vendorDir . '/wikimedia/less.php/lessc.inc.php',
|
||||||
);
|
);
|
||||||
|
|||||||
3
vendor/composer/autoload_files.php
vendored
3
vendor/composer/autoload_files.php
vendored
@ -8,9 +8,8 @@ $baseDir = dirname($vendorDir);
|
|||||||
return array(
|
return array(
|
||||||
'a2c78434f64e5f5ed402f42eee19c025' => $vendorDir . '/ipl/stdlib/src/functions_include.php',
|
'a2c78434f64e5f5ed402f42eee19c025' => $vendorDir . '/ipl/stdlib/src/functions_include.php',
|
||||||
'6076de347104821999fcfc82c8f19bc5' => $vendorDir . '/ipl/i18n/src/functions_include.php',
|
'6076de347104821999fcfc82c8f19bc5' => $vendorDir . '/ipl/i18n/src/functions_include.php',
|
||||||
|
'9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
|
||||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
|
||||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
|
||||||
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
||||||
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
|
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
|
||||||
'8e4ccce73649a2b516ec3b4571432da5' => $vendorDir . '/ipl/scheduler/src/register_cron_aliases.php',
|
'8e4ccce73649a2b516ec3b4571432da5' => $vendorDir . '/ipl/scheduler/src/register_cron_aliases.php',
|
||||||
|
|||||||
8
vendor/composer/autoload_psr4.php
vendored
8
vendor/composer/autoload_psr4.php
vendored
@ -14,21 +14,19 @@ return array(
|
|||||||
'ipl\\Orm\\' => array($vendorDir . '/ipl/orm/src'),
|
'ipl\\Orm\\' => array($vendorDir . '/ipl/orm/src'),
|
||||||
'ipl\\I18n\\' => array($vendorDir . '/ipl/i18n/src'),
|
'ipl\\I18n\\' => array($vendorDir . '/ipl/i18n/src'),
|
||||||
'ipl\\Html\\' => array($vendorDir . '/ipl/html/src'),
|
'ipl\\Html\\' => array($vendorDir . '/ipl/html/src'),
|
||||||
'cweagans\\Composer\\' => array($vendorDir . '/cweagans/composer-patches/src'),
|
|
||||||
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
|
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
|
||||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
|
||||||
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
|
||||||
'Recurr\\' => array($vendorDir . '/simshaun/recurr/src/Recurr'),
|
'Recurr\\' => array($vendorDir . '/simshaun/recurr/src/Recurr'),
|
||||||
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
|
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
|
||||||
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
|
'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
|
||||||
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
||||||
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
||||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
|
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||||
'Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
|
'Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
|
||||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
|
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
|
||||||
'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'),
|
'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/src'),
|
||||||
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
|
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
|
||||||
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
||||||
);
|
);
|
||||||
|
|||||||
10
vendor/composer/autoload_real.php
vendored
10
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// autoload_real.php @generated by Composer
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
|
class ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa
|
||||||
{
|
{
|
||||||
private static $loader;
|
private static $loader;
|
||||||
|
|
||||||
@ -24,16 +24,16 @@ class ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474
|
|||||||
|
|
||||||
require __DIR__ . '/platform_check.php';
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
spl_autoload_register(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'), true, true);
|
spl_autoload_register(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'), true, true);
|
||||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
spl_autoload_unregister(array('ComposerAutoloaderInit20d4022bc196691807f55d4a47c06474', 'loadClassLoader'));
|
spl_autoload_unregister(array('ComposerAutoloaderInit7a1692c86b6fc70eaaf43c4bee3673aa', 'loadClassLoader'));
|
||||||
|
|
||||||
require __DIR__ . '/autoload_static.php';
|
require __DIR__ . '/autoload_static.php';
|
||||||
call_user_func(\Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::getInitializer($loader));
|
call_user_func(\Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::getInitializer($loader));
|
||||||
|
|
||||||
$loader->register(true);
|
$loader->register(true);
|
||||||
|
|
||||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit20d4022bc196691807f55d4a47c06474::$files;
|
$filesToLoad = \Composer\Autoload\ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$files;
|
||||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
|||||||
45
vendor/composer/autoload_static.php
vendored
45
vendor/composer/autoload_static.php
vendored
@ -4,14 +4,13 @@
|
|||||||
|
|
||||||
namespace Composer\Autoload;
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
class ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa
|
||||||
{
|
{
|
||||||
public static $files = array (
|
public static $files = array (
|
||||||
'a2c78434f64e5f5ed402f42eee19c025' => __DIR__ . '/..' . '/ipl/stdlib/src/functions_include.php',
|
'a2c78434f64e5f5ed402f42eee19c025' => __DIR__ . '/..' . '/ipl/stdlib/src/functions_include.php',
|
||||||
'6076de347104821999fcfc82c8f19bc5' => __DIR__ . '/..' . '/ipl/i18n/src/functions_include.php',
|
'6076de347104821999fcfc82c8f19bc5' => __DIR__ . '/..' . '/ipl/i18n/src/functions_include.php',
|
||||||
|
'9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
|
||||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
|
||||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
|
||||||
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
||||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||||
'8e4ccce73649a2b516ec3b4571432da5' => __DIR__ . '/..' . '/ipl/scheduler/src/register_cron_aliases.php',
|
'8e4ccce73649a2b516ec3b4571432da5' => __DIR__ . '/..' . '/ipl/scheduler/src/register_cron_aliases.php',
|
||||||
@ -29,18 +28,13 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
|||||||
'ipl\\I18n\\' => 9,
|
'ipl\\I18n\\' => 9,
|
||||||
'ipl\\Html\\' => 9,
|
'ipl\\Html\\' => 9,
|
||||||
),
|
),
|
||||||
'c' =>
|
|
||||||
array (
|
|
||||||
'cweagans\\Composer\\' => 18,
|
|
||||||
),
|
|
||||||
'W' =>
|
'W' =>
|
||||||
array (
|
array (
|
||||||
'Webmozart\\Assert\\' => 17,
|
'Webmozart\\Assert\\' => 17,
|
||||||
),
|
),
|
||||||
'S' =>
|
'S' =>
|
||||||
array (
|
array (
|
||||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
'Symfony\\Polyfill\\Php84\\' => 23,
|
||||||
'Symfony\\Polyfill\\Ctype\\' => 23,
|
|
||||||
),
|
),
|
||||||
'R' =>
|
'R' =>
|
||||||
array (
|
array (
|
||||||
@ -111,21 +105,13 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
|||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/ipl/html/src',
|
0 => __DIR__ . '/..' . '/ipl/html/src',
|
||||||
),
|
),
|
||||||
'cweagans\\Composer\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/cweagans/composer-patches/src',
|
|
||||||
),
|
|
||||||
'Webmozart\\Assert\\' =>
|
'Webmozart\\Assert\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/webmozart/assert/src',
|
0 => __DIR__ . '/..' . '/webmozart/assert/src',
|
||||||
),
|
),
|
||||||
'Symfony\\Polyfill\\Php80\\' =>
|
'Symfony\\Polyfill\\Php84\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
|
||||||
),
|
|
||||||
'Symfony\\Polyfill\\Ctype\\' =>
|
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
|
||||||
),
|
),
|
||||||
'Recurr\\' =>
|
'Recurr\\' =>
|
||||||
array (
|
array (
|
||||||
@ -153,8 +139,8 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
|||||||
),
|
),
|
||||||
'Psr\\Http\\Message\\' =>
|
'Psr\\Http\\Message\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||||
1 => __DIR__ . '/..' . '/psr/http-factory/src',
|
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||||
),
|
),
|
||||||
'GuzzleHttp\\Psr7\\' =>
|
'GuzzleHttp\\Psr7\\' =>
|
||||||
array (
|
array (
|
||||||
@ -170,7 +156,7 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
|||||||
),
|
),
|
||||||
'Doctrine\\Common\\Collections\\' =>
|
'Doctrine\\Common\\Collections\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/doctrine/collections/lib/Doctrine/Common/Collections',
|
0 => __DIR__ . '/..' . '/doctrine/collections/src',
|
||||||
),
|
),
|
||||||
'Cron\\' =>
|
'Cron\\' =>
|
||||||
array (
|
array (
|
||||||
@ -200,22 +186,19 @@ class ComposerStaticInit20d4022bc196691807f55d4a47c06474
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static $classMap = array (
|
public static $classMap = array (
|
||||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
|
||||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
|
||||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
|
||||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
|
||||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
|
||||||
'lessc' => __DIR__ . '/..' . '/wikimedia/less.php/lessc.inc.php',
|
'lessc' => __DIR__ . '/..' . '/wikimedia/less.php/lessc.inc.php',
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function getInitializer(ClassLoader $loader)
|
public static function getInitializer(ClassLoader $loader)
|
||||||
{
|
{
|
||||||
return \Closure::bind(function () use ($loader) {
|
return \Closure::bind(function () use ($loader) {
|
||||||
$loader->prefixLengthsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixLengthsPsr4;
|
$loader->prefixLengthsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixLengthsPsr4;
|
||||||
$loader->prefixDirsPsr4 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixDirsPsr4;
|
$loader->prefixDirsPsr4 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixDirsPsr4;
|
||||||
$loader->prefixesPsr0 = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$prefixesPsr0;
|
$loader->prefixesPsr0 = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$prefixesPsr0;
|
||||||
$loader->classMap = ComposerStaticInit20d4022bc196691807f55d4a47c06474::$classMap;
|
$loader->classMap = ComposerStaticInit7a1692c86b6fc70eaaf43c4bee3673aa::$classMap;
|
||||||
|
|
||||||
}, null, ClassLoader::class);
|
}, null, ClassLoader::class);
|
||||||
}
|
}
|
||||||
|
|||||||
536
vendor/composer/installed.json
vendored
536
vendor/composer/installed.json
vendored
@ -2,29 +2,28 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.9.3",
|
"version": "0.14.0",
|
||||||
"version_normalized": "0.9.3.0",
|
"version_normalized": "0.14.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/brick/math.git",
|
"url": "https://github.com/brick/math.git",
|
||||||
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
|
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
|
"url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
|
||||||
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
|
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"php": "^8.2"
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"php-coveralls/php-coveralls": "^2.2",
|
"php-coveralls/php-coveralls": "^2.2",
|
||||||
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
|
"phpstan/phpstan": "2.1.22",
|
||||||
"vimeo/psalm": "4.9.2"
|
"phpunit/phpunit": "^11.5"
|
||||||
},
|
},
|
||||||
"time": "2021-08-15T20:50:18+00:00",
|
"time": "2025-08-29T12:40:03+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -44,107 +43,59 @@
|
|||||||
"arithmetic",
|
"arithmetic",
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"bignum",
|
"bignum",
|
||||||
|
"bignumber",
|
||||||
"brick",
|
"brick",
|
||||||
"math"
|
"decimal",
|
||||||
|
"integer",
|
||||||
|
"math",
|
||||||
|
"mathematics",
|
||||||
|
"rational"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/brick/math/issues",
|
"issues": "https://github.com/brick/math/issues",
|
||||||
"source": "https://github.com/brick/math/tree/0.9.3"
|
"source": "https://github.com/brick/math/tree/0.14.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/BenMorel",
|
"url": "https://github.com/BenMorel",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/brick/math",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"install-path": "../brick/math"
|
"install-path": "../brick/math"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "cweagans/composer-patches",
|
|
||||||
"version": "1.7.3",
|
|
||||||
"version_normalized": "1.7.3.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/cweagans/composer-patches.git",
|
|
||||||
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
|
|
||||||
"reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"composer-plugin-api": "^1.0 || ^2.0",
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"composer/composer": "~1.0 || ~2.0",
|
|
||||||
"phpunit/phpunit": "~4.6"
|
|
||||||
},
|
|
||||||
"time": "2022-12-20T22:53:13+00:00",
|
|
||||||
"type": "composer-plugin",
|
|
||||||
"extra": {
|
|
||||||
"class": "cweagans\\Composer\\Patches"
|
|
||||||
},
|
|
||||||
"installation-source": "dist",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"cweagans\\Composer\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"BSD-3-Clause"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Cameron Eagans",
|
|
||||||
"email": "me@cweagans.net"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Provides a way to patch Composer packages.",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/cweagans/composer-patches/issues",
|
|
||||||
"source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
|
|
||||||
},
|
|
||||||
"install-path": "../cweagans/composer-patches"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "doctrine/collections",
|
"name": "doctrine/collections",
|
||||||
"version": "1.8.0",
|
"version": "2.3.0",
|
||||||
"version_normalized": "1.8.0.0",
|
"version_normalized": "2.3.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/collections.git",
|
"url": "https://github.com/doctrine/collections.git",
|
||||||
"reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e"
|
"reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/collections/zipball/2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
|
"url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d",
|
||||||
"reference": "2b44dd4cbca8b5744327de78bafef5945c7e7b5e",
|
"reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/deprecations": "^0.5.3 || ^1",
|
"doctrine/deprecations": "^1",
|
||||||
"php": "^7.1.3 || ^8.0"
|
"php": "^8.1",
|
||||||
|
"symfony/polyfill-php84": "^1.30"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9.0 || ^10.0",
|
"doctrine/coding-standard": "^12",
|
||||||
"phpstan/phpstan": "^1.4.8",
|
"ext-json": "*",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
|
"phpstan/phpstan": "^1.8",
|
||||||
"vimeo/psalm": "^4.22"
|
"phpstan/phpstan-phpunit": "^1.0",
|
||||||
|
"phpunit/phpunit": "^10.5"
|
||||||
},
|
},
|
||||||
"time": "2022-09-01T20:12:10+00:00",
|
"time": "2025-03-22T10:17:19+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
|
"Doctrine\\Common\\Collections\\": "src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@ -183,8 +134,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/collections/issues",
|
"issues": "https://github.com/doctrine/collections/issues",
|
||||||
"source": "https://github.com/doctrine/collections/tree/1.8.0"
|
"source": "https://github.com/doctrine/collections/tree/2.3.0"
|
||||||
},
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/phpdoctrine",
|
||||||
|
"type": "patreon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
"install-path": "../doctrine/collections"
|
"install-path": "../doctrine/collections"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -525,17 +490,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/html",
|
"name": "ipl/html",
|
||||||
"version": "v0.8.2",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.8.2.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-html.git",
|
"url": "https://github.com/Icinga/ipl-html.git",
|
||||||
"reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98"
|
"reference": "0cc98fb660f6c55ed5638d3cbbd8a848c82fd143"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-html/zipball/e18bdf11abca5e477100e2c7d190ef5f424d0d98",
|
"url": "https://api.github.com/repos/Icinga/ipl-html/zipball/0cc98fb660f6c55ed5638d3cbbd8a848c82fd143",
|
||||||
"reference": "e18bdf11abca5e477100e2c7d190ef5f424d0d98",
|
"reference": "0cc98fb660f6c55ed5638d3cbbd8a848c82fd143",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -543,14 +508,16 @@
|
|||||||
"guzzlehttp/psr7": "^2.5",
|
"guzzlehttp/psr7": "^2.5",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"ipl/validator": ">=0.5.0",
|
"ipl/validator": ">=0.5.0",
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"psr/http-message": "^1.1"
|
"psr/http-message": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"ext-dom": "*",
|
||||||
"ipl/stdlib": "dev-main",
|
"ipl/stdlib": "dev-main",
|
||||||
"ipl/validator": "dev-main"
|
"ipl/validator": "dev-main"
|
||||||
},
|
},
|
||||||
"time": "2025-05-21T09:00:03+00:00",
|
"time": "2025-10-20T10:28:40+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -569,23 +536,23 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-html/issues",
|
"issues": "https://github.com/Icinga/ipl-html/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-html/tree/v0.8.2"
|
"source": "https://github.com/Icinga/ipl-html/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/html"
|
"install-path": "../ipl/html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/i18n",
|
"name": "ipl/i18n",
|
||||||
"version": "v0.2.2",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.2.2.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-i18n.git",
|
"url": "https://github.com/Icinga/ipl-i18n.git",
|
||||||
"reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c"
|
"reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
|
"url": "https://api.github.com/repos/Icinga/ipl-i18n/zipball/692c33cf46fb8a4511da613dbf97c6216c345cc5",
|
||||||
"reference": "a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c",
|
"reference": "692c33cf46fb8a4511da613dbf97c6216c345cc5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -597,7 +564,8 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
"time": "2024-04-08T12:28:47+00:00",
|
"time": "2025-06-12T11:57:41+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -623,37 +591,38 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-i18n/issues",
|
"issues": "https://github.com/Icinga/ipl-i18n/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-i18n/tree/v0.2.2"
|
"source": "https://github.com/Icinga/ipl-i18n/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/i18n"
|
"install-path": "../ipl/i18n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/orm",
|
"name": "ipl/orm",
|
||||||
"version": "v0.6.3",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.6.3.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-orm.git",
|
"url": "https://github.com/Icinga/ipl-orm.git",
|
||||||
"reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915"
|
"reference": "2a0b72d21e2444501a940975f869297998c6cdfe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/a775a2745764a8dc7f28618cce69dcd7bbfd7915",
|
"url": "https://api.github.com/repos/Icinga/ipl-orm/zipball/2a0b72d21e2444501a940975f869297998c6cdfe",
|
||||||
"reference": "a775a2745764a8dc7f28618cce69dcd7bbfd7915",
|
"reference": "2a0b72d21e2444501a940975f869297998c6cdfe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ipl/sql": ">=0.7.0",
|
"ipl/sql": ">=0.7.0",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"php": ">=7.2"
|
"php": ">=8.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ext-pdo_sqlite": "*",
|
"ext-pdo_sqlite": "*",
|
||||||
"ipl/sql": "dev-main",
|
"ipl/sql": "dev-main",
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
"time": "2025-06-12T11:57:55+00:00",
|
"time": "2025-10-15T11:46:22+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -674,23 +643,23 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-orm/issues",
|
"issues": "https://github.com/Icinga/ipl-orm/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-orm/tree/v0.6.3"
|
"source": "https://github.com/Icinga/ipl-orm/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/orm"
|
"install-path": "../ipl/orm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/scheduler",
|
"name": "ipl/scheduler",
|
||||||
"version": "v0.1.2",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.1.2.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-scheduler.git",
|
"url": "https://github.com/Icinga/ipl-scheduler.git",
|
||||||
"reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba"
|
"reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/6119afdea07b1390bd728e350e0d80b26ec8d6ba",
|
"url": "https://api.github.com/repos/Icinga/ipl-scheduler/zipball/3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
|
||||||
"reference": "6119afdea07b1390bd728e350e0d80b26ec8d6ba",
|
"reference": "3e4e8db870239d213b1dfd5d79d59fc7784b4c34",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -710,7 +679,8 @@
|
|||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
|
"ext-ev": "Improves performance, efficiency and avoids system limitations. Highly recommended! (See https://www.php.net/manual/en/intro.ev.php for details)"
|
||||||
},
|
},
|
||||||
"time": "2023-08-30T14:14:23+00:00",
|
"time": "2025-06-12T11:58:09+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -735,23 +705,23 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
|
"issues": "https://github.com/Icinga/ipl-scheduler/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-scheduler/tree/v0.1.2"
|
"source": "https://github.com/Icinga/ipl-scheduler/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/scheduler"
|
"install-path": "../ipl/scheduler"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/sql",
|
"name": "ipl/sql",
|
||||||
"version": "v0.7.1",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.7.1.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-sql.git",
|
"url": "https://github.com/Icinga/ipl-sql.git",
|
||||||
"reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b"
|
"reference": "6f4258c4e3b20655db57d248e26edf7b54c04729"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/e80f1b712c4b96099b0bf9096e6efe317a165e3b",
|
"url": "https://api.github.com/repos/Icinga/ipl-sql/zipball/6f4258c4e3b20655db57d248e26edf7b54c04729",
|
||||||
"reference": "e80f1b712c4b96099b0bf9096e6efe317a165e3b",
|
"reference": "6f4258c4e3b20655db57d248e26edf7b54c04729",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -762,7 +732,8 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ipl/stdlib": "dev-main"
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
"time": "2024-06-25T09:55:43+00:00",
|
"time": "2025-10-08T07:03:38+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -782,23 +753,23 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-sql/issues",
|
"issues": "https://github.com/Icinga/ipl-sql/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-sql/tree/v0.7.1"
|
"source": "https://github.com/Icinga/ipl-sql/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/sql"
|
"install-path": "../ipl/sql"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/stdlib",
|
"name": "ipl/stdlib",
|
||||||
"version": "v0.14.0",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.14.0.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-stdlib.git",
|
"url": "https://github.com/Icinga/ipl-stdlib.git",
|
||||||
"reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a"
|
"reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
|
"url": "https://api.github.com/repos/Icinga/ipl-stdlib/zipball/9b7a903fbfc341da59f242149ac333594e4a6fa3",
|
||||||
"reference": "bf5fc8f40b86bd90337db6f3be389be2a93fa64a",
|
"reference": "9b7a903fbfc341da59f242149ac333594e4a6fa3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -806,7 +777,8 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"php": ">=7.2"
|
"php": ">=7.2"
|
||||||
},
|
},
|
||||||
"time": "2024-04-22T08:47:08+00:00",
|
"time": "2025-09-05T12:07:21+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -824,23 +796,23 @@
|
|||||||
"description": "ipl Standard Library",
|
"description": "ipl Standard Library",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
|
"issues": "https://github.com/Icinga/ipl-stdlib/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-stdlib/tree/v0.14.0"
|
"source": "https://github.com/Icinga/ipl-stdlib/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/stdlib"
|
"install-path": "../ipl/stdlib"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/validator",
|
"name": "ipl/validator",
|
||||||
"version": "v0.5.0",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.5.0.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-validator.git",
|
"url": "https://github.com/Icinga/ipl-validator.git",
|
||||||
"reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde"
|
"reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
|
"url": "https://api.github.com/repos/Icinga/ipl-validator/zipball/eac5c6c114d8007db5c24ae159fe6f55e89a946b",
|
||||||
"reference": "a601fae0ed330e63cea50e4a2a6659ca1ad97bde",
|
"reference": "eac5c6c114d8007db5c24ae159fe6f55e89a946b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -849,12 +821,15 @@
|
|||||||
"ipl/i18n": ">=0.2.0",
|
"ipl/i18n": ">=0.2.0",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"php": ">=7.2",
|
"php": ">=7.2",
|
||||||
"psr/http-message": "~1.0"
|
"psr/http-message": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"guzzlehttp/psr7": "^1"
|
"guzzlehttp/psr7": "^1",
|
||||||
|
"ipl/i18n": "dev-main",
|
||||||
|
"ipl/stdlib": "dev-main"
|
||||||
},
|
},
|
||||||
"time": "2023-03-21T15:59:00+00:00",
|
"time": "2025-06-12T11:59:27+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -870,34 +845,34 @@
|
|||||||
"homepage": "https://github.com/Icinga/ipl-validator",
|
"homepage": "https://github.com/Icinga/ipl-validator",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-validator/issues",
|
"issues": "https://github.com/Icinga/ipl-validator/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-validator/tree/v0.5.0"
|
"source": "https://github.com/Icinga/ipl-validator/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/validator"
|
"install-path": "../ipl/validator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ipl/web",
|
"name": "ipl/web",
|
||||||
"version": "v0.10.2",
|
"version": "dev-main",
|
||||||
"version_normalized": "0.10.2.0",
|
"version_normalized": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Icinga/ipl-web.git",
|
"url": "https://github.com/Icinga/ipl-web.git",
|
||||||
"reference": "a3d134c0d67aa51a9b186519c76e718603fda835"
|
"reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Icinga/ipl-web/zipball/a3d134c0d67aa51a9b186519c76e718603fda835",
|
"url": "https://api.github.com/repos/Icinga/ipl-web/zipball/1fdd7aa977f8da19e17cc4535b023c0760aa442a",
|
||||||
"reference": "a3d134c0d67aa51a9b186519c76e718603fda835",
|
"reference": "1fdd7aa977f8da19e17cc4535b023c0760aa442a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"fortawesome/font-awesome": "^6",
|
"fortawesome/font-awesome": "^6",
|
||||||
"ipl/html": ">=0.8.0",
|
"ipl/html": ">=0.9.0",
|
||||||
"ipl/i18n": ">=0.2.0",
|
"ipl/i18n": ">=0.2.0",
|
||||||
"ipl/orm": ">=0.5.2",
|
"ipl/orm": ">=0.5.2",
|
||||||
"ipl/scheduler": ">=0.1.0",
|
"ipl/scheduler": ">=0.1.0",
|
||||||
"ipl/stdlib": ">=0.13.0",
|
"ipl/stdlib": ">=0.13.0",
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"psr/http-message": "^1.1",
|
"psr/http-message": "^1.1",
|
||||||
"wikimedia/less.php": "^3.2.1"
|
"wikimedia/less.php": "^3.2.1"
|
||||||
},
|
},
|
||||||
@ -909,7 +884,8 @@
|
|||||||
"ipl/stdlib": "dev-main",
|
"ipl/stdlib": "dev-main",
|
||||||
"shardj/zf1-future": "^1.22"
|
"shardj/zf1-future": "^1.22"
|
||||||
},
|
},
|
||||||
"time": "2025-03-26T07:49:58+00:00",
|
"time": "2025-10-17T12:11:07+00:00",
|
||||||
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -928,7 +904,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/Icinga/ipl-web/issues",
|
"issues": "https://github.com/Icinga/ipl-web/issues",
|
||||||
"source": "https://github.com/Icinga/ipl-web/tree/v0.10.2"
|
"source": "https://github.com/Icinga/ipl-web/tree/main"
|
||||||
},
|
},
|
||||||
"install-path": "../ipl/web"
|
"install-path": "../ipl/web"
|
||||||
},
|
},
|
||||||
@ -1148,45 +1124,49 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/collection",
|
"name": "ramsey/collection",
|
||||||
"version": "1.1.4",
|
"version": "2.1.1",
|
||||||
"version_normalized": "1.1.4.0",
|
"version_normalized": "2.1.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/collection.git",
|
"url": "https://github.com/ramsey/collection.git",
|
||||||
"reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
|
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
|
"url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||||
"reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
|
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2 || ^8"
|
"php": "^8.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"captainhook/captainhook": "^5.3",
|
"captainhook/plugin-composer": "^5.3",
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
"ergebnis/composer-normalize": "^2.45",
|
||||||
"ergebnis/composer-normalize": "^2.6",
|
"fakerphp/faker": "^1.24",
|
||||||
"fakerphp/faker": "^1.5",
|
"hamcrest/hamcrest-php": "^2.0",
|
||||||
"hamcrest/hamcrest-php": "^2",
|
"jangregor/phpstan-prophecy": "^2.1",
|
||||||
"jangregor/phpstan-prophecy": "^0.8",
|
"mockery/mockery": "^1.6",
|
||||||
"mockery/mockery": "^1.3",
|
"php-parallel-lint/php-console-highlighter": "^1.0",
|
||||||
"phpstan/extension-installer": "^1",
|
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||||
"phpstan/phpstan": "^0.12.32",
|
"phpspec/prophecy-phpunit": "^2.3",
|
||||||
"phpstan/phpstan-mockery": "^0.12.5",
|
"phpstan/extension-installer": "^1.4",
|
||||||
"phpstan/phpstan-phpunit": "^0.12.11",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpunit/phpunit": "^8.5 || ^9",
|
"phpstan/phpstan-mockery": "^2.0",
|
||||||
"psy/psysh": "^0.10.4",
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
"slevomat/coding-standard": "^6.3",
|
"phpunit/phpunit": "^10.5",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"ramsey/coding-standard": "^2.3",
|
||||||
"vimeo/psalm": "^4.4"
|
"ramsey/conventional-commits": "^1.6",
|
||||||
|
"roave/security-advisories": "dev-latest"
|
||||||
},
|
},
|
||||||
"time": "2021-07-30T00:58:27+00:00",
|
"time": "2025-03-22T05:38:12+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"patches_applied": {
|
"captainhook": {
|
||||||
"Collection: Add PHP 8.1 support": "patches/ramsey-collection.patch"
|
"force-install": true
|
||||||
|
},
|
||||||
|
"ramsey/conventional-commits": {
|
||||||
|
"configFile": "conventional-commits.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
@ -1206,7 +1186,7 @@
|
|||||||
"homepage": "https://benramsey.com"
|
"homepage": "https://benramsey.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A PHP 7.2+ library for representing and manipulating collections.",
|
"description": "A PHP library for representing and manipulating collections.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"array",
|
"array",
|
||||||
"collection",
|
"collection",
|
||||||
@ -1217,84 +1197,64 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ramsey/collection/issues",
|
"issues": "https://github.com/ramsey/collection/issues",
|
||||||
"source": "https://github.com/ramsey/collection/tree/1.1.4"
|
"source": "https://github.com/ramsey/collection/tree/2.1.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/ramsey",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"install-path": "../ramsey/collection"
|
"install-path": "../ramsey/collection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/uuid",
|
"name": "ramsey/uuid",
|
||||||
"version": "4.2.3",
|
"version": "4.9.1",
|
||||||
"version_normalized": "4.2.3.0",
|
"version_normalized": "4.9.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/uuid.git",
|
"url": "https://github.com/ramsey/uuid.git",
|
||||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
|
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
"url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
|
||||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"brick/math": "^0.8 || ^0.9",
|
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
|
||||||
"ext-json": "*",
|
"php": "^8.0",
|
||||||
"php": "^7.2 || ^8.0",
|
"ramsey/collection": "^1.2 || ^2.0"
|
||||||
"ramsey/collection": "^1.0",
|
|
||||||
"symfony/polyfill-ctype": "^1.8",
|
|
||||||
"symfony/polyfill-php80": "^1.14"
|
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"rhumsaa/uuid": "self.version"
|
"rhumsaa/uuid": "self.version"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"captainhook/captainhook": "^5.10",
|
"captainhook/captainhook": "^5.25",
|
||||||
"captainhook/plugin-composer": "^5.3",
|
"captainhook/plugin-composer": "^5.3",
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||||
"doctrine/annotations": "^1.8",
|
"ergebnis/composer-normalize": "^2.47",
|
||||||
"ergebnis/composer-normalize": "^2.15",
|
"mockery/mockery": "^1.6",
|
||||||
"mockery/mockery": "^1.3",
|
|
||||||
"moontoast/math": "^1.1",
|
|
||||||
"paragonie/random-lib": "^2",
|
"paragonie/random-lib": "^2",
|
||||||
"php-mock/php-mock": "^2.2",
|
"php-mock/php-mock": "^2.6",
|
||||||
"php-mock/php-mock-mockery": "^1.3",
|
"php-mock/php-mock-mockery": "^1.5",
|
||||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
"php-parallel-lint/php-parallel-lint": "^1.4.0",
|
||||||
"phpbench/phpbench": "^1.0",
|
"phpbench/phpbench": "^1.2.14",
|
||||||
"phpstan/extension-installer": "^1.0",
|
"phpstan/extension-installer": "^1.4",
|
||||||
"phpstan/phpstan": "^0.12",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpstan/phpstan-mockery": "^0.12",
|
"phpstan/phpstan-mockery": "^2.0",
|
||||||
"phpstan/phpstan-phpunit": "^0.12",
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
"phpunit/phpunit": "^8.5 || ^9",
|
"phpunit/phpunit": "^9.6",
|
||||||
"slevomat/coding-standard": "^7.0",
|
"slevomat/coding-standard": "^8.18",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"squizlabs/php_codesniffer": "^3.13"
|
||||||
"vimeo/psalm": "^4.9"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||||
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
|
|
||||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
||||||
},
|
},
|
||||||
"time": "2021-09-25T23:10:38+00:00",
|
"time": "2025-09-04T20:59:21+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"captainhook": {
|
"captainhook": {
|
||||||
"force-install": true
|
"force-install": true
|
||||||
},
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "4.x-dev"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
@ -1318,18 +1278,8 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ramsey/uuid/issues",
|
"issues": "https://github.com/ramsey/uuid/issues",
|
||||||
"source": "https://github.com/ramsey/uuid/tree/4.2.3"
|
"source": "https://github.com/ramsey/uuid/tree/4.9.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/ramsey",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"install-path": "../ramsey/uuid"
|
"install-path": "../ramsey/uuid"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1545,30 +1495,24 @@
|
|||||||
"install-path": "../simshaun/recurr"
|
"install-path": "../simshaun/recurr"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-php84",
|
||||||
"version": "v1.33.0",
|
"version": "v1.33.0",
|
||||||
"version_normalized": "1.33.0.0",
|
"version_normalized": "1.33.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-php84.git",
|
||||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
|
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
|
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
|
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2"
|
"php": ">=7.2"
|
||||||
},
|
},
|
||||||
"provide": {
|
"time": "2025-06-24T13:30:11+00:00",
|
||||||
"ext-ctype": "*"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-ctype": "For best performance"
|
|
||||||
},
|
|
||||||
"time": "2024-09-09T11:45:10+00:00",
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"thanks": {
|
"thanks": {
|
||||||
@ -1582,87 +1526,7 @@
|
|||||||
"bootstrap.php"
|
"bootstrap.php"
|
||||||
],
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Polyfill\\Ctype\\": ""
|
"Symfony\\Polyfill\\Php84\\": ""
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Gert de Pagter",
|
|
||||||
"email": "BackEndTea@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "https://symfony.com/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Symfony polyfill for ctype functions",
|
|
||||||
"homepage": "https://symfony.com",
|
|
||||||
"keywords": [
|
|
||||||
"compatibility",
|
|
||||||
"ctype",
|
|
||||||
"polyfill",
|
|
||||||
"portable"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/nicolas-grekas",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"install-path": "../symfony/polyfill-ctype"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "symfony/polyfill-php80",
|
|
||||||
"version": "v1.33.0",
|
|
||||||
"version_normalized": "1.33.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
|
||||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
|
||||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.2"
|
|
||||||
},
|
|
||||||
"time": "2025-01-02T08:10:11+00:00",
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"thanks": {
|
|
||||||
"url": "https://github.com/symfony/polyfill",
|
|
||||||
"name": "symfony/polyfill"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"installation-source": "dist",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"bootstrap.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Php80\\": ""
|
|
||||||
},
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"Resources/stubs"
|
"Resources/stubs"
|
||||||
@ -1673,10 +1537,6 @@
|
|||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Ion Bazan",
|
|
||||||
"email": "ion.bazan@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Nicolas Grekas",
|
"name": "Nicolas Grekas",
|
||||||
"email": "p@tchwork.com"
|
"email": "p@tchwork.com"
|
||||||
@ -1686,7 +1546,7 @@
|
|||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"compatibility",
|
"compatibility",
|
||||||
@ -1695,7 +1555,7 @@
|
|||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
|
"source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1715,35 +1575,35 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"install-path": "../symfony/polyfill-php80"
|
"install-path": "../symfony/polyfill-php84"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "1.11.0",
|
"version": "1.12.0",
|
||||||
"version_normalized": "1.11.0.0",
|
"version_normalized": "1.12.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webmozarts/assert.git",
|
"url": "https://github.com/webmozarts/assert.git",
|
||||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
|
"reference": "541057574806f942c94662b817a50f63f7345360"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
"url": "https://api.github.com/repos/webmozarts/assert/zipball/541057574806f942c94662b817a50f63f7345360",
|
||||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
"reference": "541057574806f942c94662b817a50f63f7345360",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
|
"ext-date": "*",
|
||||||
|
"ext-filter": "*",
|
||||||
"php": "^7.2 || ^8.0"
|
"php": "^7.2 || ^8.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"suggest": {
|
||||||
"phpstan/phpstan": "<0.12.20",
|
"ext-intl": "",
|
||||||
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
"ext-simplexml": "",
|
||||||
|
"ext-spl": ""
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"time": "2025-10-20T12:43:39+00:00",
|
||||||
"phpunit/phpunit": "^8.5.13"
|
|
||||||
},
|
|
||||||
"time": "2022-06-03T18:03:27+00:00",
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
@ -1774,7 +1634,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/webmozarts/assert/issues",
|
"issues": "https://github.com/webmozarts/assert/issues",
|
||||||
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
|
"source": "https://github.com/webmozarts/assert/tree/1.12.0"
|
||||||
},
|
},
|
||||||
"install-path": "../webmozart/assert"
|
"install-path": "../webmozart/assert"
|
||||||
},
|
},
|
||||||
|
|||||||
148
vendor/composer/installed.php
vendored
148
vendor/composer/installed.php
vendored
@ -3,7 +3,7 @@
|
|||||||
'name' => 'icinga/icinga-php-library',
|
'name' => 'icinga/icinga-php-library',
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
|
'reference' => 'fc173db4b1af1cf0184caafb0e8c5da619513037',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@ -11,27 +11,18 @@
|
|||||||
),
|
),
|
||||||
'versions' => array(
|
'versions' => array(
|
||||||
'brick/math' => array(
|
'brick/math' => array(
|
||||||
'pretty_version' => '0.9.3',
|
'pretty_version' => '0.14.0',
|
||||||
'version' => '0.9.3.0',
|
'version' => '0.14.0.0',
|
||||||
'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae',
|
'reference' => '113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../brick/math',
|
'install_path' => __DIR__ . '/../brick/math',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'cweagans/composer-patches' => array(
|
|
||||||
'pretty_version' => '1.7.3',
|
|
||||||
'version' => '1.7.3.0',
|
|
||||||
'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db',
|
|
||||||
'type' => 'composer-plugin',
|
|
||||||
'install_path' => __DIR__ . '/../cweagans/composer-patches',
|
|
||||||
'aliases' => array(),
|
|
||||||
'dev_requirement' => false,
|
|
||||||
),
|
|
||||||
'doctrine/collections' => array(
|
'doctrine/collections' => array(
|
||||||
'pretty_version' => '1.8.0',
|
'pretty_version' => '2.3.0',
|
||||||
'version' => '1.8.0.0',
|
'version' => '2.3.0.0',
|
||||||
'reference' => '2b44dd4cbca8b5744327de78bafef5945c7e7b5e',
|
'reference' => '2eb07e5953eed811ce1b309a7478a3b236f2273d',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../doctrine/collections',
|
'install_path' => __DIR__ . '/../doctrine/collections',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@ -85,82 +76,106 @@
|
|||||||
'icinga/icinga-php-library' => array(
|
'icinga/icinga-php-library' => array(
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a7944e40e1b1c5f88dcb04c253e07001cb9ddb4b',
|
'reference' => 'fc173db4b1af1cf0184caafb0e8c5da619513037',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/html' => array(
|
'ipl/html' => array(
|
||||||
'pretty_version' => 'v0.8.2',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.8.2.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'e18bdf11abca5e477100e2c7d190ef5f424d0d98',
|
'reference' => '0cc98fb660f6c55ed5638d3cbbd8a848c82fd143',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/html',
|
'install_path' => __DIR__ . '/../ipl/html',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/i18n' => array(
|
'ipl/i18n' => array(
|
||||||
'pretty_version' => 'v0.2.2',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.2.2.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a2b6109c5a93f86ce46d5dc351dbe75e8502cf8c',
|
'reference' => '692c33cf46fb8a4511da613dbf97c6216c345cc5',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/i18n',
|
'install_path' => __DIR__ . '/../ipl/i18n',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/orm' => array(
|
'ipl/orm' => array(
|
||||||
'pretty_version' => 'v0.6.3',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.6.3.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a775a2745764a8dc7f28618cce69dcd7bbfd7915',
|
'reference' => '2a0b72d21e2444501a940975f869297998c6cdfe',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/orm',
|
'install_path' => __DIR__ . '/../ipl/orm',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/scheduler' => array(
|
'ipl/scheduler' => array(
|
||||||
'pretty_version' => 'v0.1.2',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.1.2.0',
|
'version' => 'dev-main',
|
||||||
'reference' => '6119afdea07b1390bd728e350e0d80b26ec8d6ba',
|
'reference' => '3e4e8db870239d213b1dfd5d79d59fc7784b4c34',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/scheduler',
|
'install_path' => __DIR__ . '/../ipl/scheduler',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/sql' => array(
|
'ipl/sql' => array(
|
||||||
'pretty_version' => 'v0.7.1',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.7.1.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'e80f1b712c4b96099b0bf9096e6efe317a165e3b',
|
'reference' => '6f4258c4e3b20655db57d248e26edf7b54c04729',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/sql',
|
'install_path' => __DIR__ . '/../ipl/sql',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/stdlib' => array(
|
'ipl/stdlib' => array(
|
||||||
'pretty_version' => 'v0.14.0',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.14.0.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'bf5fc8f40b86bd90337db6f3be389be2a93fa64a',
|
'reference' => '9b7a903fbfc341da59f242149ac333594e4a6fa3',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/stdlib',
|
'install_path' => __DIR__ . '/../ipl/stdlib',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/validator' => array(
|
'ipl/validator' => array(
|
||||||
'pretty_version' => 'v0.5.0',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.5.0.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a601fae0ed330e63cea50e4a2a6659ca1ad97bde',
|
'reference' => 'eac5c6c114d8007db5c24ae159fe6f55e89a946b',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/validator',
|
'install_path' => __DIR__ . '/../ipl/validator',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ipl/web' => array(
|
'ipl/web' => array(
|
||||||
'pretty_version' => 'v0.10.2',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '0.10.2.0',
|
'version' => 'dev-main',
|
||||||
'reference' => 'a3d134c0d67aa51a9b186519c76e718603fda835',
|
'reference' => '1fdd7aa977f8da19e17cc4535b023c0760aa442a',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ipl/web',
|
'install_path' => __DIR__ . '/../ipl/web',
|
||||||
'aliases' => array(),
|
'aliases' => array(
|
||||||
|
0 => '99.x-dev',
|
||||||
|
1 => '9999999-dev',
|
||||||
|
),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'mtdowling/cron-expression' => array(
|
'mtdowling/cron-expression' => array(
|
||||||
@ -218,18 +233,18 @@
|
|||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ramsey/collection' => array(
|
'ramsey/collection' => array(
|
||||||
'pretty_version' => '1.1.4',
|
'pretty_version' => '2.1.1',
|
||||||
'version' => '1.1.4.0',
|
'version' => '2.1.1.0',
|
||||||
'reference' => 'ab2237657ad99667a5143e32ba2683c8029563d4',
|
'reference' => '344572933ad0181accbf4ba763e85a0306a8c5e2',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ramsey/collection',
|
'install_path' => __DIR__ . '/../ramsey/collection',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'ramsey/uuid' => array(
|
'ramsey/uuid' => array(
|
||||||
'pretty_version' => '4.2.3',
|
'pretty_version' => '4.9.1',
|
||||||
'version' => '4.2.3.0',
|
'version' => '4.9.1.0',
|
||||||
'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
|
'reference' => '81f941f6f729b1e3ceea61d9d014f8b6c6800440',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../ramsey/uuid',
|
'install_path' => __DIR__ . '/../ramsey/uuid',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@ -256,7 +271,7 @@
|
|||||||
'rhumsaa/uuid' => array(
|
'rhumsaa/uuid' => array(
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
'replaced' => array(
|
'replaced' => array(
|
||||||
0 => '4.2.3',
|
0 => '4.9.1',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'simshaun/recurr' => array(
|
'simshaun/recurr' => array(
|
||||||
@ -268,28 +283,19 @@
|
|||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'symfony/polyfill-ctype' => array(
|
'symfony/polyfill-php84' => array(
|
||||||
'pretty_version' => 'v1.33.0',
|
'pretty_version' => 'v1.33.0',
|
||||||
'version' => '1.33.0.0',
|
'version' => '1.33.0.0',
|
||||||
'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
|
'reference' => 'd8ced4d875142b6a7426000426b8abc631d6b191',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
'install_path' => __DIR__ . '/../symfony/polyfill-php84',
|
||||||
'aliases' => array(),
|
|
||||||
'dev_requirement' => false,
|
|
||||||
),
|
|
||||||
'symfony/polyfill-php80' => array(
|
|
||||||
'pretty_version' => 'v1.33.0',
|
|
||||||
'version' => '1.33.0.0',
|
|
||||||
'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608',
|
|
||||||
'type' => 'library',
|
|
||||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'webmozart/assert' => array(
|
'webmozart/assert' => array(
|
||||||
'pretty_version' => '1.11.0',
|
'pretty_version' => '1.12.0',
|
||||||
'version' => '1.11.0.0',
|
'version' => '1.12.0.0',
|
||||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
'reference' => '541057574806f942c94662b817a50f63f7345360',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../webmozart/assert',
|
'install_path' => __DIR__ . '/../webmozart/assert',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|||||||
9
vendor/composer/platform_check.php
vendored
9
vendor/composer/platform_check.php
vendored
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
$issues = array();
|
$issues = array();
|
||||||
|
|
||||||
if (!(PHP_VERSION_ID >= 70209)) {
|
if (!(PHP_VERSION_ID >= 80200)) {
|
||||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.9". You are running ' . PHP_VERSION . '.';
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($issues) {
|
if ($issues) {
|
||||||
@ -19,8 +19,7 @@ if ($issues) {
|
|||||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trigger_error(
|
throw new \RuntimeException(
|
||||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
'Composer detected issues in your platform: ' . implode(' ', $issues)
|
||||||
E_USER_ERROR
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
30
vendor/cweagans/composer-patches/composer.json
vendored
30
vendor/cweagans/composer-patches/composer.json
vendored
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cweagans/composer-patches",
|
|
||||||
"description": "Provides a way to patch Composer packages.",
|
|
||||||
"minimum-stability": "dev",
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"type": "composer-plugin",
|
|
||||||
"extra": {
|
|
||||||
"class": "cweagans\\Composer\\Patches"
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Cameron Eagans",
|
|
||||||
"email": "me@cweagans.net"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.0",
|
|
||||||
"composer-plugin-api": "^1.0 || ^2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"composer/composer": "~1.0 || ~2.0",
|
|
||||||
"phpunit/phpunit": "~4.6"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {"cweagans\\Composer\\": "src"}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {"cweagans\\Composer\\Tests\\": "tests"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Dispatch events when patches are applied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace cweagans\Composer;
|
|
||||||
|
|
||||||
use Composer\EventDispatcher\Event;
|
|
||||||
use Composer\Package\PackageInterface;
|
|
||||||
|
|
||||||
class PatchEvent extends Event {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var PackageInterface $package
|
|
||||||
*/
|
|
||||||
protected $package;
|
|
||||||
/**
|
|
||||||
* @var string $url
|
|
||||||
*/
|
|
||||||
protected $url;
|
|
||||||
/**
|
|
||||||
* @var string $description
|
|
||||||
*/
|
|
||||||
protected $description;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a PatchEvent object.
|
|
||||||
*
|
|
||||||
* @param string $eventName
|
|
||||||
* @param PackageInterface $package
|
|
||||||
* @param string $url
|
|
||||||
* @param string $description
|
|
||||||
*/
|
|
||||||
public function __construct($eventName, PackageInterface $package, $url, $description) {
|
|
||||||
parent::__construct($eventName);
|
|
||||||
$this->package = $package;
|
|
||||||
$this->url = $url;
|
|
||||||
$this->description = $description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the package that is patched.
|
|
||||||
*
|
|
||||||
* @return PackageInterface
|
|
||||||
*/
|
|
||||||
public function getPackage() {
|
|
||||||
return $this->package;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the url of the patch.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getUrl() {
|
|
||||||
return $this->url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the description of the patch.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription() {
|
|
||||||
return $this->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Dispatch events when patches are applied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace cweagans\Composer;
|
|
||||||
|
|
||||||
class PatchEvents {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The PRE_PATCH_APPLY event occurs before a patch is applied.
|
|
||||||
*
|
|
||||||
* The event listener method receives a cweagans\Composer\PatchEvent instance.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const PRE_PATCH_APPLY = 'pre-patch-apply';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The POST_PATCH_APPLY event occurs after a patch is applied.
|
|
||||||
*
|
|
||||||
* The event listener method receives a cweagans\Composer\PatchEvent instance.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const POST_PATCH_APPLY = 'post-patch-apply';
|
|
||||||
|
|
||||||
}
|
|
||||||
599
vendor/cweagans/composer-patches/src/Patches.php
vendored
599
vendor/cweagans/composer-patches/src/Patches.php
vendored
@ -1,599 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Provides a way to patch Composer packages after installation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace cweagans\Composer;
|
|
||||||
|
|
||||||
use Composer\Composer;
|
|
||||||
use Composer\DependencyResolver\Operation\InstallOperation;
|
|
||||||
use Composer\DependencyResolver\Operation\UninstallOperation;
|
|
||||||
use Composer\DependencyResolver\Operation\UpdateOperation;
|
|
||||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
|
||||||
use Composer\EventDispatcher\EventSubscriberInterface;
|
|
||||||
use Composer\IO\IOInterface;
|
|
||||||
use Composer\Package\AliasPackage;
|
|
||||||
use Composer\Package\PackageInterface;
|
|
||||||
use Composer\Plugin\PluginInterface;
|
|
||||||
use Composer\Installer\PackageEvents;
|
|
||||||
use Composer\Script\Event;
|
|
||||||
use Composer\Script\ScriptEvents;
|
|
||||||
use Composer\Installer\PackageEvent;
|
|
||||||
use Composer\Util\ProcessExecutor;
|
|
||||||
use Composer\Util\RemoteFilesystem;
|
|
||||||
use Symfony\Component\Process\Process;
|
|
||||||
|
|
||||||
class Patches implements PluginInterface, EventSubscriberInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Composer $composer
|
|
||||||
*/
|
|
||||||
protected $composer;
|
|
||||||
/**
|
|
||||||
* @var IOInterface $io
|
|
||||||
*/
|
|
||||||
protected $io;
|
|
||||||
/**
|
|
||||||
* @var EventDispatcher $eventDispatcher
|
|
||||||
*/
|
|
||||||
protected $eventDispatcher;
|
|
||||||
/**
|
|
||||||
* @var ProcessExecutor $executor
|
|
||||||
*/
|
|
||||||
protected $executor;
|
|
||||||
/**
|
|
||||||
* @var array $patches
|
|
||||||
*/
|
|
||||||
protected $patches;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array $installedPatches
|
|
||||||
*/
|
|
||||||
protected $installedPatches;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply plugin modifications to composer
|
|
||||||
*
|
|
||||||
* @param Composer $composer
|
|
||||||
* @param IOInterface $io
|
|
||||||
*/
|
|
||||||
public function activate(Composer $composer, IOInterface $io) {
|
|
||||||
$this->composer = $composer;
|
|
||||||
$this->io = $io;
|
|
||||||
$this->eventDispatcher = $composer->getEventDispatcher();
|
|
||||||
$this->executor = new ProcessExecutor($this->io);
|
|
||||||
$this->patches = array();
|
|
||||||
$this->installedPatches = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of event names this subscriber wants to listen to.
|
|
||||||
*/
|
|
||||||
public static function getSubscribedEvents() {
|
|
||||||
return array(
|
|
||||||
ScriptEvents::PRE_INSTALL_CMD => array('checkPatches'),
|
|
||||||
ScriptEvents::PRE_UPDATE_CMD => array('checkPatches'),
|
|
||||||
PackageEvents::PRE_PACKAGE_INSTALL => array('gatherPatches'),
|
|
||||||
PackageEvents::PRE_PACKAGE_UPDATE => array('gatherPatches'),
|
|
||||||
// The following is a higher weight for compatibility with
|
|
||||||
// https://github.com/AydinHassan/magento-core-composer-installer and more generally for compatibility with
|
|
||||||
// every Composer plugin which deploys downloaded packages to other locations.
|
|
||||||
// In such cases you want that those plugins deploy patched files so they have to run after
|
|
||||||
// the "composer-patches" plugin.
|
|
||||||
// @see: https://github.com/cweagans/composer-patches/pull/153
|
|
||||||
PackageEvents::POST_PACKAGE_INSTALL => array('postInstall', 10),
|
|
||||||
PackageEvents::POST_PACKAGE_UPDATE => array('postInstall', 10),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Before running composer install,
|
|
||||||
* @param Event $event
|
|
||||||
*/
|
|
||||||
public function checkPatches(Event $event) {
|
|
||||||
if (!$this->isPatchingEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$repositoryManager = $this->composer->getRepositoryManager();
|
|
||||||
$localRepository = $repositoryManager->getLocalRepository();
|
|
||||||
$installationManager = $this->composer->getInstallationManager();
|
|
||||||
$packages = $localRepository->getPackages();
|
|
||||||
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
$patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
|
|
||||||
|
|
||||||
$tmp_patches = $this->grabPatches();
|
|
||||||
foreach ($packages as $package) {
|
|
||||||
$extra = $package->getExtra();
|
|
||||||
if (isset($extra['patches'])) {
|
|
||||||
if (isset($patches_ignore[$package->getName()])) {
|
|
||||||
foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
|
|
||||||
if (isset($extra['patches'][$package_name])) {
|
|
||||||
$extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->installedPatches[$package->getName()] = $extra['patches'];
|
|
||||||
}
|
|
||||||
$patches = isset($extra['patches']) ? $extra['patches'] : array();
|
|
||||||
$tmp_patches = $this->arrayMergeRecursiveDistinct($tmp_patches, $patches);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($tmp_patches == FALSE) {
|
|
||||||
$this->io->write('<info>No patches supplied.</info>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove packages for which the patch set has changed.
|
|
||||||
$promises = array();
|
|
||||||
foreach ($packages as $package) {
|
|
||||||
if (!($package instanceof AliasPackage)) {
|
|
||||||
$package_name = $package->getName();
|
|
||||||
$extra = $package->getExtra();
|
|
||||||
$has_patches = isset($tmp_patches[$package_name]);
|
|
||||||
$has_applied_patches = isset($extra['patches_applied']) && count($extra['patches_applied']) > 0;
|
|
||||||
if (($has_patches && !$has_applied_patches)
|
|
||||||
|| (!$has_patches && $has_applied_patches)
|
|
||||||
|| ($has_patches && $has_applied_patches && $tmp_patches[$package_name] !== $extra['patches_applied'])) {
|
|
||||||
$uninstallOperation = new UninstallOperation($package, 'Removing package so it can be re-installed and re-patched.');
|
|
||||||
$this->io->write('<info>Removing package ' . $package_name . ' so that it can be re-installed and re-patched.</info>');
|
|
||||||
$promises[] = $installationManager->uninstall($localRepository, $uninstallOperation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$promises = array_filter($promises);
|
|
||||||
if ($promises) {
|
|
||||||
$this->composer->getLoop()->wait($promises);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the Locker isn't available, then we don't need to do this.
|
|
||||||
// It's the first time packages have been installed.
|
|
||||||
catch (\LogicException $e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gather patches from dependencies and store them for later use.
|
|
||||||
*
|
|
||||||
* @param PackageEvent $event
|
|
||||||
*/
|
|
||||||
public function gatherPatches(PackageEvent $event) {
|
|
||||||
// If we've already done this, then don't do it again.
|
|
||||||
if (isset($this->patches['_patchesGathered'])) {
|
|
||||||
$this->io->write('<info>Patches already gathered. Skipping</info>', TRUE, IOInterface::VERBOSE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If patching has been disabled, bail out here.
|
|
||||||
elseif (!$this->isPatchingEnabled()) {
|
|
||||||
$this->io->write('<info>Patching is disabled. Skipping.</info>', TRUE, IOInterface::VERBOSE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->patches = $this->grabPatches();
|
|
||||||
if (empty($this->patches)) {
|
|
||||||
$this->io->write('<info>No patches supplied.</info>');
|
|
||||||
}
|
|
||||||
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
$patches_ignore = isset($extra['patches-ignore']) ? $extra['patches-ignore'] : array();
|
|
||||||
|
|
||||||
// Now add all the patches from dependencies that will be installed.
|
|
||||||
$operations = $event->getOperations();
|
|
||||||
$this->io->write('<info>Gathering patches for dependencies. This might take a minute.</info>');
|
|
||||||
foreach ($operations as $operation) {
|
|
||||||
if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) {
|
|
||||||
$package = $this->getPackageFromOperation($operation);
|
|
||||||
$extra = $package->getExtra();
|
|
||||||
if (isset($extra['patches'])) {
|
|
||||||
if (isset($patches_ignore[$package->getName()])) {
|
|
||||||
foreach ($patches_ignore[$package->getName()] as $package_name => $patches) {
|
|
||||||
if (isset($extra['patches'][$package_name])) {
|
|
||||||
$extra['patches'][$package_name] = array_diff($extra['patches'][$package_name], $patches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $extra['patches']);
|
|
||||||
}
|
|
||||||
// Unset installed patches for this package
|
|
||||||
if(isset($this->installedPatches[$package->getName()])) {
|
|
||||||
unset($this->installedPatches[$package->getName()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge installed patches from dependencies that did not receive an update.
|
|
||||||
foreach ($this->installedPatches as $patches) {
|
|
||||||
$this->patches = $this->arrayMergeRecursiveDistinct($this->patches, $patches);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're in verbose mode, list the projects we're going to patch.
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
foreach ($this->patches as $package => $patches) {
|
|
||||||
$number = count($patches);
|
|
||||||
$this->io->write('<info>Found ' . $number . ' patches for ' . $package . '.</info>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we don't gather patches again. Extra keys in $this->patches
|
|
||||||
// won't hurt anything, so we'll just stash it there.
|
|
||||||
$this->patches['_patchesGathered'] = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the patches from root composer or external file
|
|
||||||
* @return Patches
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function grabPatches() {
|
|
||||||
// First, try to get the patches from the root composer.json.
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
if (isset($extra['patches'])) {
|
|
||||||
$this->io->write('<info>Gathering patches for root package.</info>');
|
|
||||||
$patches = $extra['patches'];
|
|
||||||
return $patches;
|
|
||||||
}
|
|
||||||
// If it's not specified there, look for a patches-file definition.
|
|
||||||
elseif (isset($extra['patches-file'])) {
|
|
||||||
$this->io->write('<info>Gathering patches from patch file.</info>');
|
|
||||||
$patches = file_get_contents($extra['patches-file']);
|
|
||||||
$patches = json_decode($patches, TRUE);
|
|
||||||
$error = json_last_error();
|
|
||||||
if ($error != 0) {
|
|
||||||
switch ($error) {
|
|
||||||
case JSON_ERROR_DEPTH:
|
|
||||||
$msg = ' - Maximum stack depth exceeded';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_STATE_MISMATCH:
|
|
||||||
$msg = ' - Underflow or the modes mismatch';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_CTRL_CHAR:
|
|
||||||
$msg = ' - Unexpected control character found';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_SYNTAX:
|
|
||||||
$msg = ' - Syntax error, malformed JSON';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_UTF8:
|
|
||||||
$msg = ' - Malformed UTF-8 characters, possibly incorrectly encoded';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$msg = ' - Unknown error';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
throw new \Exception('There was an error in the supplied patches file:' . $msg);
|
|
||||||
}
|
|
||||||
if (isset($patches['patches'])) {
|
|
||||||
$patches = $patches['patches'];
|
|
||||||
return $patches;
|
|
||||||
}
|
|
||||||
elseif(!$patches) {
|
|
||||||
throw new \Exception('There was an error in the supplied patch file');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param PackageEvent $event
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function postInstall(PackageEvent $event) {
|
|
||||||
|
|
||||||
// Check if we should exit in failure.
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
$exitOnFailure = getenv('COMPOSER_EXIT_ON_PATCH_FAILURE') || !empty($extra['composer-exit-on-patch-failure']);
|
|
||||||
$skipReporting = getenv('COMPOSER_PATCHES_SKIP_REPORTING') || !empty($extra['composer-patches-skip-reporting']);
|
|
||||||
|
|
||||||
// Get the package object for the current operation.
|
|
||||||
$operation = $event->getOperation();
|
|
||||||
/** @var PackageInterface $package */
|
|
||||||
$package = $this->getPackageFromOperation($operation);
|
|
||||||
$package_name = $package->getName();
|
|
||||||
|
|
||||||
if (!isset($this->patches[$package_name])) {
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
$this->io->write('<info>No patches found for ' . $package_name . '.</info>');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->io->write(' - Applying patches for <info>' . $package_name . '</info>');
|
|
||||||
|
|
||||||
// Get the install path from the package object.
|
|
||||||
$manager = $event->getComposer()->getInstallationManager();
|
|
||||||
$install_path = $manager->getInstaller($package->getType())->getInstallPath($package);
|
|
||||||
|
|
||||||
// Set up a downloader.
|
|
||||||
$downloader = new RemoteFilesystem($this->io, $this->composer->getConfig());
|
|
||||||
|
|
||||||
// Track applied patches in the package info in installed.json
|
|
||||||
$localRepository = $this->composer->getRepositoryManager()->getLocalRepository();
|
|
||||||
$localPackage = $localRepository->findPackage($package_name, $package->getVersion());
|
|
||||||
$extra = $localPackage->getExtra();
|
|
||||||
$extra['patches_applied'] = array();
|
|
||||||
|
|
||||||
foreach ($this->patches[$package_name] as $description => $url) {
|
|
||||||
$this->io->write(' <info>' . $url . '</info> (<comment>' . $description. '</comment>)');
|
|
||||||
try {
|
|
||||||
$this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::PRE_PATCH_APPLY, $package, $url, $description));
|
|
||||||
$this->getAndApplyPatch($downloader, $install_path, $url, $package);
|
|
||||||
$this->eventDispatcher->dispatch(NULL, new PatchEvent(PatchEvents::POST_PATCH_APPLY, $package, $url, $description));
|
|
||||||
$extra['patches_applied'][$description] = $url;
|
|
||||||
}
|
|
||||||
catch (\Exception $e) {
|
|
||||||
$this->io->write(' <error>Could not apply patch! Skipping. The error was: ' . $e->getMessage() . '</error>');
|
|
||||||
if ($exitOnFailure) {
|
|
||||||
throw new \Exception("Cannot apply patch $description ($url)!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$localPackage->setExtra($extra);
|
|
||||||
|
|
||||||
$this->io->write('');
|
|
||||||
|
|
||||||
if (true !== $skipReporting) {
|
|
||||||
$this->writePatchReport($this->patches[$package_name], $install_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a Package object from an OperationInterface object.
|
|
||||||
*
|
|
||||||
* @param OperationInterface $operation
|
|
||||||
* @return PackageInterface
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected function getPackageFromOperation(OperationInterface $operation) {
|
|
||||||
if ($operation instanceof InstallOperation) {
|
|
||||||
$package = $operation->getPackage();
|
|
||||||
}
|
|
||||||
elseif ($operation instanceof UpdateOperation) {
|
|
||||||
$package = $operation->getTargetPackage();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new \Exception('Unknown operation: ' . get_class($operation));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $package;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply a patch on code in the specified directory.
|
|
||||||
*
|
|
||||||
* @param RemoteFilesystem $downloader
|
|
||||||
* @param $install_path
|
|
||||||
* @param $patch_url
|
|
||||||
* @param PackageInterface $package
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected function getAndApplyPatch(RemoteFilesystem $downloader, $install_path, $patch_url, PackageInterface $package) {
|
|
||||||
|
|
||||||
// Local patch file.
|
|
||||||
if (file_exists($patch_url)) {
|
|
||||||
$filename = realpath($patch_url);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Generate random (but not cryptographically so) filename.
|
|
||||||
$filename = uniqid(sys_get_temp_dir().'/') . ".patch";
|
|
||||||
|
|
||||||
// Download file from remote filesystem to this location.
|
|
||||||
$hostname = parse_url($patch_url, PHP_URL_HOST);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$downloader->copy($hostname, $patch_url, $filename, false);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// In case of an exception, retry once as the download might
|
|
||||||
// have failed due to intermittent network issues.
|
|
||||||
$downloader->copy($hostname, $patch_url, $filename, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The order here is intentional. p1 is most likely to apply with git apply.
|
|
||||||
// p0 is next likely. p2 is extremely unlikely, but for some special cases,
|
|
||||||
// it might be useful. p4 is useful for Magento 2 patches
|
|
||||||
$patch_levels = array('-p1', '-p0', '-p2', '-p4');
|
|
||||||
|
|
||||||
// Check for specified patch level for this package.
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
if (!empty($extra['patchLevel'][$package->getName()])){
|
|
||||||
$patch_levels = array($extra['patchLevel'][$package->getName()]);
|
|
||||||
}
|
|
||||||
// Attempt to apply with git apply.
|
|
||||||
$patched = $this->applyPatchWithGit($install_path, $patch_levels, $filename);
|
|
||||||
|
|
||||||
// In some rare cases, git will fail to apply a patch, fallback to using
|
|
||||||
// the 'patch' command.
|
|
||||||
if (!$patched) {
|
|
||||||
foreach ($patch_levels as $patch_level) {
|
|
||||||
// --no-backup-if-mismatch here is a hack that fixes some
|
|
||||||
// differences between how patch works on windows and unix.
|
|
||||||
if ($patched = $this->executeCommand("patch %s --no-backup-if-mismatch -d %s < %s", $patch_level, $install_path, $filename)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the temporary patch file.
|
|
||||||
if (isset($hostname)) {
|
|
||||||
unlink($filename);
|
|
||||||
}
|
|
||||||
// If the patch *still* isn't applied, then give up and throw an Exception.
|
|
||||||
// Otherwise, let the user know it worked.
|
|
||||||
if (!$patched) {
|
|
||||||
throw new \Exception("Cannot apply patch $patch_url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the root package enables patching.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* Whether patching is enabled. Defaults to TRUE.
|
|
||||||
*/
|
|
||||||
protected function isPatchingEnabled() {
|
|
||||||
$extra = $this->composer->getPackage()->getExtra();
|
|
||||||
|
|
||||||
if (empty($extra['patches']) && empty($extra['patches-ignore']) && !isset($extra['patches-file'])) {
|
|
||||||
// The root package has no patches of its own, so only allow patching if
|
|
||||||
// it has specifically opted in.
|
|
||||||
return isset($extra['enable-patching']) ? $extra['enable-patching'] : FALSE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a patch report to the target directory.
|
|
||||||
*
|
|
||||||
* @param array $patches
|
|
||||||
* @param string $directory
|
|
||||||
*/
|
|
||||||
protected function writePatchReport($patches, $directory) {
|
|
||||||
$output = "This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches)\n";
|
|
||||||
$output .= "Patches applied to this directory:\n\n";
|
|
||||||
foreach ($patches as $description => $url) {
|
|
||||||
$output .= $description . "\n";
|
|
||||||
$output .= 'Source: ' . $url . "\n\n\n";
|
|
||||||
}
|
|
||||||
file_put_contents($directory . "/PATCHES.txt", $output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a shell command with escaping.
|
|
||||||
*
|
|
||||||
* @param string $cmd
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function executeCommand($cmd) {
|
|
||||||
// Shell-escape all arguments except the command.
|
|
||||||
$args = func_get_args();
|
|
||||||
foreach ($args as $index => $arg) {
|
|
||||||
if ($index !== 0) {
|
|
||||||
$args[$index] = escapeshellarg($arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// And replace the arguments.
|
|
||||||
$command = call_user_func_array('sprintf', $args);
|
|
||||||
$output = '';
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
$this->io->write('<comment>' . $command . '</comment>');
|
|
||||||
$io = $this->io;
|
|
||||||
$output = function ($type, $data) use ($io) {
|
|
||||||
if ($type == Process::ERR) {
|
|
||||||
$io->write('<error>' . $data . '</error>');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$io->write('<comment>' . $data . '</comment>');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return ($this->executor->execute($command, $output) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively merge arrays without changing data types of values.
|
|
||||||
*
|
|
||||||
* Does not change the data types of the values in the arrays. Matching keys'
|
|
||||||
* values in the second array overwrite those in the first array, as is the
|
|
||||||
* case with array_merge.
|
|
||||||
*
|
|
||||||
* @param array $array1
|
|
||||||
* The first array.
|
|
||||||
* @param array $array2
|
|
||||||
* The second array.
|
|
||||||
* @return array
|
|
||||||
* The merged array.
|
|
||||||
*
|
|
||||||
* @see http://php.net/manual/en/function.array-merge-recursive.php#92195
|
|
||||||
*/
|
|
||||||
protected function arrayMergeRecursiveDistinct(array $array1, array $array2) {
|
|
||||||
$merged = $array1;
|
|
||||||
|
|
||||||
foreach ($array2 as $key => &$value) {
|
|
||||||
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
|
|
||||||
$merged[$key] = $this->arrayMergeRecursiveDistinct($merged[$key], $value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$merged[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to apply a patch with git apply.
|
|
||||||
*
|
|
||||||
* @param $install_path
|
|
||||||
* @param $patch_levels
|
|
||||||
* @param $filename
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* TRUE if patch was applied, FALSE otherwise.
|
|
||||||
*/
|
|
||||||
protected function applyPatchWithGit($install_path, $patch_levels, $filename) {
|
|
||||||
// Do not use git apply unless the install path is itself a git repo
|
|
||||||
// @see https://stackoverflow.com/a/27283285
|
|
||||||
if (!is_dir($install_path . '/.git')) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
$patched = FALSE;
|
|
||||||
foreach ($patch_levels as $patch_level) {
|
|
||||||
if ($this->io->isVerbose()) {
|
|
||||||
$comment = 'Testing ability to patch with git apply.';
|
|
||||||
$comment .= ' This command may produce errors that can be safely ignored.';
|
|
||||||
$this->io->write('<comment>' . $comment . '</comment>');
|
|
||||||
}
|
|
||||||
$checked = $this->executeCommand('git -C %s apply --check -v %s %s', $install_path, $patch_level, $filename);
|
|
||||||
$output = $this->executor->getErrorOutput();
|
|
||||||
if (substr($output, 0, 7) == 'Skipped') {
|
|
||||||
// Git will indicate success but silently skip patches in some scenarios.
|
|
||||||
//
|
|
||||||
// @see https://github.com/cweagans/composer-patches/pull/165
|
|
||||||
$checked = FALSE;
|
|
||||||
}
|
|
||||||
if ($checked) {
|
|
||||||
// Apply the first successful style.
|
|
||||||
$patched = $this->executeCommand('git -C %s apply %s %s', $install_path, $patch_level, $filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $patched;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if a package has been patched.
|
|
||||||
*
|
|
||||||
* @param \Composer\Package\PackageInterface $package
|
|
||||||
* The package to check.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* TRUE if the package has been patched.
|
|
||||||
*/
|
|
||||||
public static function isPackagePatched(PackageInterface $package) {
|
|
||||||
return array_key_exists('patches_applied', $package->getExtra());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function deactivate(Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function uninstall(Composer $composer, IOInterface $io)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"active": true,
|
|
||||||
"name": "Collections",
|
|
||||||
"slug": "collections",
|
|
||||||
"docsSlug": "doctrine-collections",
|
|
||||||
"versions": [
|
|
||||||
{
|
|
||||||
"name": "2.0",
|
|
||||||
"branchName": "2.0.x",
|
|
||||||
"slug": "latest",
|
|
||||||
"upcoming": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1.8",
|
|
||||||
"branchName": "1.8.x",
|
|
||||||
"slug": "1.8",
|
|
||||||
"upcoming": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1.7",
|
|
||||||
"branchName": "1.7.x",
|
|
||||||
"slug": "1.7",
|
|
||||||
"current": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1.6",
|
|
||||||
"branchName": "1.6.x",
|
|
||||||
"slug": "1.6",
|
|
||||||
"maintained": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
18
vendor/doctrine/collections/composer.json
vendored
18
vendor/doctrine/collections/composer.json
vendored
@ -33,23 +33,25 @@
|
|||||||
],
|
],
|
||||||
"homepage": "https://www.doctrine-project.org/projects/collections.html",
|
"homepage": "https://www.doctrine-project.org/projects/collections.html",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3 || ^8.0",
|
"php": "^8.1",
|
||||||
"doctrine/deprecations": "^0.5.3 || ^1"
|
"doctrine/deprecations": "^1",
|
||||||
|
"symfony/polyfill-php84": "^1.30"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9.0 || ^10.0",
|
"ext-json": "*",
|
||||||
"phpstan/phpstan": "^1.4.8",
|
"doctrine/coding-standard": "^12",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
|
"phpstan/phpstan": "^1.8",
|
||||||
"vimeo/psalm": "^4.22"
|
"phpstan/phpstan-phpunit": "^1.0",
|
||||||
|
"phpunit/phpunit": "^10.5"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
|
"Doctrine\\Common\\Collections\\": "src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Doctrine\\Tests\\": "tests/Doctrine/Tests"
|
"Doctrine\\Tests\\Common\\Collections\\": "tests"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
|
|||||||
@ -1,269 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
|
||||||
|
|
||||||
use ArrayAccess;
|
|
||||||
use Closure;
|
|
||||||
use RuntimeException;
|
|
||||||
|
|
||||||
use function explode;
|
|
||||||
use function in_array;
|
|
||||||
use function is_array;
|
|
||||||
use function is_scalar;
|
|
||||||
use function iterator_to_array;
|
|
||||||
use function method_exists;
|
|
||||||
use function preg_match;
|
|
||||||
use function preg_replace_callback;
|
|
||||||
use function strlen;
|
|
||||||
use function strpos;
|
|
||||||
use function strtoupper;
|
|
||||||
use function substr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Walks an expression graph and turns it into a PHP closure.
|
|
||||||
*
|
|
||||||
* This closure can be used with {@Collection#filter()} and is used internally
|
|
||||||
* by {@ArrayCollection#select()}.
|
|
||||||
*/
|
|
||||||
class ClosureExpressionVisitor extends ExpressionVisitor
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Accesses the field of a given object. This field has to be public
|
|
||||||
* directly or indirectly (through an accessor get*, is*, or a magic
|
|
||||||
* method, __get, __call).
|
|
||||||
*
|
|
||||||
* @param object|mixed[] $object
|
|
||||||
* @param string $field
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function getObjectFieldValue($object, $field)
|
|
||||||
{
|
|
||||||
if (strpos($field, '.') !== false) {
|
|
||||||
[$field, $subField] = explode('.', $field, 2);
|
|
||||||
$object = self::getObjectFieldValue($object, $field);
|
|
||||||
|
|
||||||
return self::getObjectFieldValue($object, $subField);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($object)) {
|
|
||||||
return $object[$field];
|
|
||||||
}
|
|
||||||
|
|
||||||
$accessors = ['get', 'is', ''];
|
|
||||||
|
|
||||||
foreach ($accessors as $accessor) {
|
|
||||||
$accessor .= $field;
|
|
||||||
|
|
||||||
if (method_exists($object, $accessor)) {
|
|
||||||
return $object->$accessor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
|
|
||||||
return $object->$field();
|
|
||||||
}
|
|
||||||
|
|
||||||
// __call should be triggered for get.
|
|
||||||
$accessor = $accessors[0] . $field;
|
|
||||||
|
|
||||||
if (method_exists($object, '__call')) {
|
|
||||||
return $object->$accessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($object instanceof ArrayAccess) {
|
|
||||||
return $object[$field];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($object->$field)) {
|
|
||||||
return $object->$field;
|
|
||||||
}
|
|
||||||
|
|
||||||
// camelcase field name to support different variable naming conventions
|
|
||||||
$ccField = preg_replace_callback('/_(.?)/', static function ($matches) {
|
|
||||||
return strtoupper($matches[1]);
|
|
||||||
}, $field);
|
|
||||||
|
|
||||||
foreach ($accessors as $accessor) {
|
|
||||||
$accessor .= $ccField;
|
|
||||||
|
|
||||||
if (method_exists($object, $accessor)) {
|
|
||||||
return $object->$accessor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $object->$field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for sorting arrays of objects based on multiple fields + orientations.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param int $orientation
|
|
||||||
*
|
|
||||||
* @return Closure
|
|
||||||
*/
|
|
||||||
public static function sortByField($name, $orientation = 1, ?Closure $next = null)
|
|
||||||
{
|
|
||||||
if (! $next) {
|
|
||||||
$next = static function (): int {
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return static function ($a, $b) use ($name, $next, $orientation): int {
|
|
||||||
$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
|
|
||||||
|
|
||||||
$bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
|
|
||||||
|
|
||||||
if ($aValue === $bValue) {
|
|
||||||
return $next($a, $b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($aValue > $bValue ? 1 : -1) * $orientation;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function walkComparison(Comparison $comparison)
|
|
||||||
{
|
|
||||||
$field = $comparison->getField();
|
|
||||||
$value = $comparison->getValue()->getValue(); // shortcut for walkValue()
|
|
||||||
|
|
||||||
switch ($comparison->getOperator()) {
|
|
||||||
case Comparison::EQ:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::NEQ:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::LT:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::LTE:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::GT:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::GTE:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::IN:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
|
||||||
|
|
||||||
return in_array($fieldValue, $value, is_scalar($fieldValue));
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::NIN:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
|
||||||
|
|
||||||
return ! in_array($fieldValue, $value, is_scalar($fieldValue));
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::CONTAINS:
|
|
||||||
return static function ($object) use ($field, $value) {
|
|
||||||
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::MEMBER_OF:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
$fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
|
||||||
|
|
||||||
if (! is_array($fieldValues)) {
|
|
||||||
$fieldValues = iterator_to_array($fieldValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
return in_array($value, $fieldValues, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::STARTS_WITH:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
case Comparison::ENDS_WITH:
|
|
||||||
return static function ($object) use ($field, $value): bool {
|
|
||||||
return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value));
|
|
||||||
};
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function walkValue(Value $value)
|
|
||||||
{
|
|
||||||
return $value->getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function walkCompositeExpression(CompositeExpression $expr)
|
|
||||||
{
|
|
||||||
$expressionList = [];
|
|
||||||
|
|
||||||
foreach ($expr->getExpressionList() as $child) {
|
|
||||||
$expressionList[] = $this->dispatch($child);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($expr->getType()) {
|
|
||||||
case CompositeExpression::TYPE_AND:
|
|
||||||
return $this->andExpressions($expressionList);
|
|
||||||
|
|
||||||
case CompositeExpression::TYPE_OR:
|
|
||||||
return $this->orExpressions($expressionList);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new RuntimeException('Unknown composite ' . $expr->getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param callable[] $expressions */
|
|
||||||
private function andExpressions(array $expressions): callable
|
|
||||||
{
|
|
||||||
return static function ($object) use ($expressions): bool {
|
|
||||||
foreach ($expressions as $expression) {
|
|
||||||
if (! $expression($object)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param callable[] $expressions */
|
|
||||||
private function orExpressions(array $expressions): callable
|
|
||||||
{
|
|
||||||
return static function ($object) use ($expressions): bool {
|
|
||||||
foreach ($expressions as $expression) {
|
|
||||||
if ($expression($object)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comparison of a field with a value by the given operator.
|
|
||||||
*/
|
|
||||||
class Comparison implements Expression
|
|
||||||
{
|
|
||||||
public const EQ = '=';
|
|
||||||
public const NEQ = '<>';
|
|
||||||
public const LT = '<';
|
|
||||||
public const LTE = '<=';
|
|
||||||
public const GT = '>';
|
|
||||||
public const GTE = '>=';
|
|
||||||
public const IS = '='; // no difference with EQ
|
|
||||||
public const IN = 'IN';
|
|
||||||
public const NIN = 'NIN';
|
|
||||||
public const CONTAINS = 'CONTAINS';
|
|
||||||
public const MEMBER_OF = 'MEMBER_OF';
|
|
||||||
public const STARTS_WITH = 'STARTS_WITH';
|
|
||||||
public const ENDS_WITH = 'ENDS_WITH';
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $field;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $op;
|
|
||||||
|
|
||||||
/** @var Value */
|
|
||||||
private $value;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param string $operator
|
|
||||||
* @param mixed $value
|
|
||||||
*/
|
|
||||||
public function __construct($field, $operator, $value)
|
|
||||||
{
|
|
||||||
if (! ($value instanceof Value)) {
|
|
||||||
$value = new Value($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->field = $field;
|
|
||||||
$this->op = $operator;
|
|
||||||
$this->value = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return string */
|
|
||||||
public function getField()
|
|
||||||
{
|
|
||||||
return $this->field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return Value */
|
|
||||||
public function getValue()
|
|
||||||
{
|
|
||||||
return $this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return string */
|
|
||||||
public function getOperator()
|
|
||||||
{
|
|
||||||
return $this->op;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function visit(ExpressionVisitor $visitor)
|
|
||||||
{
|
|
||||||
return $visitor->walkComparison($this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
|
||||||
|
|
||||||
use Doctrine\Common\Collections\Expr\Comparison;
|
|
||||||
use Doctrine\Common\Collections\Expr\CompositeExpression;
|
|
||||||
use Doctrine\Common\Collections\Expr\Value;
|
|
||||||
|
|
||||||
use function func_get_args;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for Expressions in the {@link Selectable} interface.
|
|
||||||
*
|
|
||||||
* Important Notice for interoperable code: You have to use scalar
|
|
||||||
* values only for comparisons, otherwise the behavior of the comparison
|
|
||||||
* may be different between implementations (Array vs ORM vs ODM).
|
|
||||||
*/
|
|
||||||
class ExpressionBuilder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param mixed ...$x
|
|
||||||
*
|
|
||||||
* @return CompositeExpression
|
|
||||||
*/
|
|
||||||
public function andX($x = null)
|
|
||||||
{
|
|
||||||
return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed ...$x
|
|
||||||
*
|
|
||||||
* @return CompositeExpression
|
|
||||||
*/
|
|
||||||
public function orX($x = null)
|
|
||||||
{
|
|
||||||
return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function eq($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::EQ, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function gt($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::GT, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function lt($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::LT, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function gte($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::GTE, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function lte($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::LTE, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function neq($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::NEQ, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function isNull($field)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::EQ, new Value(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed[] $values
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function in($field, array $values)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::IN, new Value($values));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed[] $values
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function notIn($field, array $values)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::NIN, new Value($values));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function contains($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::CONTAINS, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function memberOf($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::MEMBER_OF, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function startsWith($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::STARTS_WITH, new Value($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $field
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return Comparison
|
|
||||||
*/
|
|
||||||
public function endsWith($field, $value)
|
|
||||||
{
|
|
||||||
return new Comparison($field, Comparison::ENDS_WITH, new Value($value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
@ -10,8 +12,8 @@ use Traversable;
|
|||||||
/**
|
/**
|
||||||
* Lazy collection that is backed by a concrete collection
|
* Lazy collection that is backed by a concrete collection
|
||||||
*
|
*
|
||||||
* @psalm-template TKey of array-key
|
* @phpstan-template TKey of array-key
|
||||||
* @psalm-template T
|
* @phpstan-template T
|
||||||
* @template-implements Collection<TKey,T>
|
* @template-implements Collection<TKey,T>
|
||||||
*/
|
*/
|
||||||
abstract class AbstractLazyCollection implements Collection
|
abstract class AbstractLazyCollection implements Collection
|
||||||
@ -19,13 +21,12 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* The backed collection to use
|
* The backed collection to use
|
||||||
*
|
*
|
||||||
* @psalm-var Collection<TKey,T>|null
|
* @phpstan-var Collection<TKey,T>|null
|
||||||
* @var Collection<mixed>|null
|
* @var Collection<mixed>|null
|
||||||
*/
|
*/
|
||||||
protected $collection;
|
protected Collection|null $collection;
|
||||||
|
|
||||||
/** @var bool */
|
protected bool $initialized = false;
|
||||||
protected $initialized = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -43,11 +44,11 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function add($element)
|
public function add(mixed $element)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
return $this->collection->add($element);
|
$this->collection->add($element);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,10 +62,8 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @template TMaybeContained
|
|
||||||
*/
|
*/
|
||||||
public function contains($element)
|
public function contains(mixed $element)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -84,7 +83,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function remove($key)
|
public function remove(string|int $key)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -94,7 +93,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function removeElement($element)
|
public function removeElement(mixed $element)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function containsKey($key)
|
public function containsKey(string|int $key)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -114,7 +113,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function get($key)
|
public function get(string|int $key)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -144,7 +143,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function set($key, $value)
|
public function set(string|int $key, mixed $value)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
$this->collection->set($key, $value);
|
$this->collection->set($key, $value);
|
||||||
@ -220,6 +219,16 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
return $this->collection->exists($p);
|
return $this->collection->exists($p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function findFirst(Closure $p)
|
||||||
|
{
|
||||||
|
$this->initialize();
|
||||||
|
|
||||||
|
return $this->collection->findFirst($p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@ -250,6 +259,16 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
return $this->collection->map($func);
|
return $this->collection->map($func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function reduce(Closure $func, mixed $initial = null)
|
||||||
|
{
|
||||||
|
$this->initialize();
|
||||||
|
|
||||||
|
return $this->collection->reduce($func, $initial);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@ -265,7 +284,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
*
|
*
|
||||||
* @template TMaybeContained
|
* @template TMaybeContained
|
||||||
*/
|
*/
|
||||||
public function indexOf($element)
|
public function indexOf(mixed $element)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -275,7 +294,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function slice($offset, $length = null)
|
public function slice(int $offset, int|null $length = null)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -286,7 +305,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @return Traversable<int|string, mixed>
|
* @return Traversable<int|string, mixed>
|
||||||
* @psalm-return Traversable<TKey,T>
|
* @phpstan-return Traversable<TKey,T>
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function getIterator()
|
public function getIterator()
|
||||||
@ -297,12 +316,14 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
* @param TKey $offset
|
* @param TKey $offset
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetExists($offset)
|
public function offsetExists(mixed $offset)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -310,12 +331,14 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
* @param TKey $offset
|
* @param TKey $offset
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return T|null
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetGet($offset)
|
public function offsetGet(mixed $offset)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
|
||||||
@ -323,13 +346,15 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
* @param TKey|null $offset
|
* @param TKey|null $offset
|
||||||
* @param T $value
|
* @param T $value
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetSet($offset, $value)
|
public function offsetSet(mixed $offset, mixed $value)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
$this->collection->offsetSet($offset, $value);
|
$this->collection->offsetSet($offset, $value);
|
||||||
@ -341,7 +366,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetUnset($offset)
|
public function offsetUnset(mixed $offset)
|
||||||
{
|
{
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
$this->collection->offsetUnset($offset);
|
$this->collection->offsetUnset($offset);
|
||||||
@ -352,7 +377,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
*
|
||||||
* @psalm-assert-if-true Collection<TKey,T> $this->collection
|
* @phpstan-assert-if-true Collection<TKey,T> $this->collection
|
||||||
*/
|
*/
|
||||||
public function isInitialized()
|
public function isInitialized()
|
||||||
{
|
{
|
||||||
@ -364,7 +389,7 @@ abstract class AbstractLazyCollection implements Collection
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @psalm-assert Collection<TKey,T> $this->collection
|
* @phpstan-assert Collection<TKey,T> $this->collection
|
||||||
*/
|
*/
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
{
|
{
|
||||||
@ -1,17 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
use ArrayIterator;
|
use ArrayIterator;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
|
use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
|
||||||
use ReturnTypeWillChange;
|
use ReturnTypeWillChange;
|
||||||
|
use Stringable;
|
||||||
use Traversable;
|
use Traversable;
|
||||||
|
|
||||||
|
use function array_all;
|
||||||
|
use function array_any;
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
|
use function array_find;
|
||||||
use function array_key_exists;
|
use function array_key_exists;
|
||||||
use function array_keys;
|
use function array_keys;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
|
use function array_reduce;
|
||||||
use function array_reverse;
|
use function array_reverse;
|
||||||
use function array_search;
|
use function array_search;
|
||||||
use function array_slice;
|
use function array_slice;
|
||||||
@ -36,27 +43,26 @@ use const ARRAY_FILTER_USE_BOTH;
|
|||||||
* serialize a collection use {@link toArray()} and reconstruct the collection
|
* serialize a collection use {@link toArray()} and reconstruct the collection
|
||||||
* manually.
|
* manually.
|
||||||
*
|
*
|
||||||
* @psalm-template TKey of array-key
|
* @phpstan-template TKey of array-key
|
||||||
* @psalm-template T
|
* @phpstan-template T
|
||||||
* @template-implements Collection<TKey,T>
|
* @template-implements Collection<TKey,T>
|
||||||
* @template-implements Selectable<TKey,T>
|
* @template-implements Selectable<TKey,T>
|
||||||
* @psalm-consistent-constructor
|
* @phpstan-consistent-constructor
|
||||||
*/
|
*/
|
||||||
class ArrayCollection implements Collection, Selectable
|
class ArrayCollection implements Collection, Selectable, Stringable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* An array containing the entries of this collection.
|
* An array containing the entries of this collection.
|
||||||
*
|
*
|
||||||
* @psalm-var array<TKey,T>
|
* @phpstan-var array<TKey,T>
|
||||||
* @var mixed[]
|
* @var mixed[]
|
||||||
*/
|
*/
|
||||||
private $elements;
|
private array $elements = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new ArrayCollection.
|
* Initializes a new ArrayCollection.
|
||||||
*
|
*
|
||||||
* @param array $elements
|
* @phpstan-param array<TKey,T> $elements
|
||||||
* @psalm-param array<TKey,T> $elements
|
|
||||||
*/
|
*/
|
||||||
public function __construct(array $elements = [])
|
public function __construct(array $elements = [])
|
||||||
{
|
{
|
||||||
@ -86,13 +92,13 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
* instance should be created when constructor semantics have changed.
|
* instance should be created when constructor semantics have changed.
|
||||||
*
|
*
|
||||||
* @param array $elements Elements.
|
* @param array $elements Elements.
|
||||||
* @psalm-param array<K,V> $elements
|
* @phpstan-param array<K,V> $elements
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
* @psalm-return static<K,V>
|
* @phpstan-return static<K,V>
|
||||||
*
|
*
|
||||||
* @psalm-template K of array-key
|
* @phpstan-template K of array-key
|
||||||
* @psalm-template V
|
* @phpstan-template V
|
||||||
*/
|
*/
|
||||||
protected function createFrom(array $elements)
|
protected function createFrom(array $elements)
|
||||||
{
|
{
|
||||||
@ -134,7 +140,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function remove($key)
|
public function remove(string|int $key)
|
||||||
{
|
{
|
||||||
if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
|
if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
|
||||||
return null;
|
return null;
|
||||||
@ -149,7 +155,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function removeElement($element)
|
public function removeElement(mixed $element)
|
||||||
{
|
{
|
||||||
$key = array_search($element, $this->elements, true);
|
$key = array_search($element, $this->elements, true);
|
||||||
|
|
||||||
@ -170,7 +176,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetExists($offset)
|
public function offsetExists(mixed $offset)
|
||||||
{
|
{
|
||||||
return $this->containsKey($offset);
|
return $this->containsKey($offset);
|
||||||
}
|
}
|
||||||
@ -180,10 +186,10 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
*
|
*
|
||||||
* @param TKey $offset
|
* @param TKey $offset
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return T|null
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetGet($offset)
|
public function offsetGet(mixed $offset)
|
||||||
{
|
{
|
||||||
return $this->get($offset);
|
return $this->get($offset);
|
||||||
}
|
}
|
||||||
@ -197,9 +203,9 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetSet($offset, $value)
|
public function offsetSet(mixed $offset, mixed $value)
|
||||||
{
|
{
|
||||||
if (! isset($offset)) {
|
if ($offset === null) {
|
||||||
$this->add($value);
|
$this->add($value);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -216,7 +222,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function offsetUnset($offset)
|
public function offsetUnset(mixed $offset)
|
||||||
{
|
{
|
||||||
$this->remove($offset);
|
$this->remove($offset);
|
||||||
}
|
}
|
||||||
@ -224,17 +230,15 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function containsKey($key)
|
public function containsKey(string|int $key)
|
||||||
{
|
{
|
||||||
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
|
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @template TMaybeContained
|
|
||||||
*/
|
*/
|
||||||
public function contains($element)
|
public function contains(mixed $element)
|
||||||
{
|
{
|
||||||
return in_array($element, $this->elements, true);
|
return in_array($element, $this->elements, true);
|
||||||
}
|
}
|
||||||
@ -244,21 +248,19 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
*/
|
*/
|
||||||
public function exists(Closure $p)
|
public function exists(Closure $p)
|
||||||
{
|
{
|
||||||
foreach ($this->elements as $key => $element) {
|
return array_any(
|
||||||
if ($p($key, $element)) {
|
$this->elements,
|
||||||
return true;
|
static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @psalm-param TMaybeContained $element
|
* @phpstan-param TMaybeContained $element
|
||||||
*
|
*
|
||||||
* @psalm-return (TMaybeContained is T ? TKey|false : false)
|
* @return int|string|false
|
||||||
|
* @phpstan-return (TMaybeContained is T ? TKey|false : false)
|
||||||
*
|
*
|
||||||
* @template TMaybeContained
|
* @template TMaybeContained
|
||||||
*/
|
*/
|
||||||
@ -270,7 +272,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function get($key)
|
public function get(string|int $key)
|
||||||
{
|
{
|
||||||
return $this->elements[$key] ?? null;
|
return $this->elements[$key] ?? null;
|
||||||
}
|
}
|
||||||
@ -294,7 +296,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int<0, max>
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function count()
|
public function count()
|
||||||
@ -305,7 +307,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function set($key, $value)
|
public function set(string|int $key, mixed $value)
|
||||||
{
|
{
|
||||||
$this->elements[$key] = $value;
|
$this->elements[$key] = $value;
|
||||||
}
|
}
|
||||||
@ -313,16 +315,12 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @psalm-suppress InvalidPropertyAssignmentValue
|
|
||||||
*
|
|
||||||
* This breaks assumptions about the template type, but it would
|
* This breaks assumptions about the template type, but it would
|
||||||
* be a backwards-incompatible change to remove this method
|
* be a backwards-incompatible change to remove this method
|
||||||
*/
|
*/
|
||||||
public function add($element)
|
public function add(mixed $element)
|
||||||
{
|
{
|
||||||
$this->elements[] = $element;
|
$this->elements[] = $element;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -337,7 +335,7 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @return Traversable<int|string, mixed>
|
* @return Traversable<int|string, mixed>
|
||||||
* @psalm-return Traversable<TKey,T>
|
* @phpstan-return Traversable<TKey, T>
|
||||||
*/
|
*/
|
||||||
#[ReturnTypeWillChange]
|
#[ReturnTypeWillChange]
|
||||||
public function getIterator()
|
public function getIterator()
|
||||||
@ -348,12 +346,12 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @psalm-param Closure(T):U $func
|
* @phpstan-param Closure(T):U $func
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
* @psalm-return static<TKey, U>
|
* @phpstan-return static<TKey, U>
|
||||||
*
|
*
|
||||||
* @psalm-template U
|
* @phpstan-template U
|
||||||
*/
|
*/
|
||||||
public function map(Closure $func)
|
public function map(Closure $func)
|
||||||
{
|
{
|
||||||
@ -362,27 +360,45 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function reduce(Closure $func, $initial = null)
|
||||||
|
{
|
||||||
|
return array_reduce($this->elements, $func, $initial);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @phpstan-param Closure(T, TKey):bool $p
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
* @psalm-return static<TKey,T>
|
* @phpstan-return static<TKey,T>
|
||||||
*/
|
*/
|
||||||
public function filter(Closure $p)
|
public function filter(Closure $p)
|
||||||
{
|
{
|
||||||
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
|
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function findFirst(Closure $p)
|
||||||
|
{
|
||||||
|
return array_find(
|
||||||
|
$this->elements,
|
||||||
|
static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function forAll(Closure $p)
|
public function forAll(Closure $p)
|
||||||
{
|
{
|
||||||
foreach ($this->elements as $key => $element) {
|
return array_all(
|
||||||
if (! $p($key, $element)) {
|
$this->elements,
|
||||||
return false;
|
static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -405,9 +421,11 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of this object.
|
* Returns a string representation of this object.
|
||||||
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
#[ReturnTypeWillChange]
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return self::class . '@' . spl_object_hash($this);
|
return self::class . '@' . spl_object_hash($this);
|
||||||
@ -424,14 +442,12 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function slice($offset, $length = null)
|
public function slice(int $offset, int|null $length = null)
|
||||||
{
|
{
|
||||||
return array_slice($this->elements, $offset, $length, true);
|
return array_slice($this->elements, $offset, $length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @phpstan-return Collection<TKey, T>&Selectable<TKey,T> */
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function matching(Criteria $criteria)
|
public function matching(Criteria $criteria)
|
||||||
{
|
{
|
||||||
$expr = $criteria->getWhereExpression();
|
$expr = $criteria->getWhereExpression();
|
||||||
@ -443,12 +459,12 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
$filtered = array_filter($filtered, $filter);
|
$filtered = array_filter($filtered, $filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
$orderings = $criteria->getOrderings();
|
$orderings = $criteria->orderings();
|
||||||
|
|
||||||
if ($orderings) {
|
if ($orderings) {
|
||||||
$next = null;
|
$next = null;
|
||||||
foreach (array_reverse($orderings) as $field => $ordering) {
|
foreach (array_reverse($orderings) as $field => $ordering) {
|
||||||
$next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
|
$next = ClosureExpressionVisitor::sortByField($field, $ordering === Order::Descending ? -1 : 1, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
uasort($filtered, $next);
|
uasort($filtered, $next);
|
||||||
@ -457,8 +473,8 @@ class ArrayCollection implements Collection, Selectable
|
|||||||
$offset = $criteria->getFirstResult();
|
$offset = $criteria->getFirstResult();
|
||||||
$length = $criteria->getMaxResults();
|
$length = $criteria->getMaxResults();
|
||||||
|
|
||||||
if ($offset || $length) {
|
if ($offset !== null && $offset > 0 || $length !== null && $length > 0) {
|
||||||
$filtered = array_slice($filtered, (int) $offset, $length);
|
$filtered = array_slice($filtered, (int) $offset, $length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->createFrom($filtered);
|
return $this->createFrom($filtered);
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
use ArrayAccess;
|
use ArrayAccess;
|
||||||
@ -22,8 +24,8 @@ use Closure;
|
|||||||
* position unless you explicitly positioned it before. Prefer iteration with
|
* position unless you explicitly positioned it before. Prefer iteration with
|
||||||
* external iterators.
|
* external iterators.
|
||||||
*
|
*
|
||||||
* @psalm-template TKey of array-key
|
* @phpstan-template TKey of array-key
|
||||||
* @psalm-template T
|
* @phpstan-template T
|
||||||
* @template-extends ReadableCollection<TKey, T>
|
* @template-extends ReadableCollection<TKey, T>
|
||||||
* @template-extends ArrayAccess<TKey, T>
|
* @template-extends ArrayAccess<TKey, T>
|
||||||
*/
|
*/
|
||||||
@ -33,11 +35,11 @@ interface Collection extends ReadableCollection, ArrayAccess
|
|||||||
* Adds an element at the end of the collection.
|
* Adds an element at the end of the collection.
|
||||||
*
|
*
|
||||||
* @param mixed $element The element to add.
|
* @param mixed $element The element to add.
|
||||||
* @psalm-param T $element
|
* @phpstan-param T $element
|
||||||
*
|
*
|
||||||
* @return true Always TRUE.
|
* @return void we will require a native return type declaration in 3.0
|
||||||
*/
|
*/
|
||||||
public function add($element);
|
public function add(mixed $element);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the collection, removing all elements.
|
* Clears the collection, removing all elements.
|
||||||
@ -50,50 +52,66 @@ interface Collection extends ReadableCollection, ArrayAccess
|
|||||||
* Removes the element at the specified index from the collection.
|
* Removes the element at the specified index from the collection.
|
||||||
*
|
*
|
||||||
* @param string|int $key The key/index of the element to remove.
|
* @param string|int $key The key/index of the element to remove.
|
||||||
* @psalm-param TKey $key
|
* @phpstan-param TKey $key
|
||||||
*
|
*
|
||||||
* @return mixed The removed element or NULL, if the collection did not contain the element.
|
* @return mixed The removed element or NULL, if the collection did not contain the element.
|
||||||
* @psalm-return T|null
|
* @phpstan-return T|null
|
||||||
*/
|
*/
|
||||||
public function remove($key);
|
public function remove(string|int $key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified element from the collection, if it is found.
|
* Removes the specified element from the collection, if it is found.
|
||||||
*
|
*
|
||||||
* @param mixed $element The element to remove.
|
* @param mixed $element The element to remove.
|
||||||
* @psalm-param T $element
|
* @phpstan-param T $element
|
||||||
*
|
*
|
||||||
* @return bool TRUE if this collection contained the specified element, FALSE otherwise.
|
* @return bool TRUE if this collection contained the specified element, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
public function removeElement($element);
|
public function removeElement(mixed $element);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an element in the collection at the specified key/index.
|
* Sets an element in the collection at the specified key/index.
|
||||||
*
|
*
|
||||||
* @param string|int $key The key/index of the element to set.
|
* @param string|int $key The key/index of the element to set.
|
||||||
* @param mixed $value The element to set.
|
* @param mixed $value The element to set.
|
||||||
* @psalm-param TKey $key
|
* @phpstan-param TKey $key
|
||||||
* @psalm-param T $value
|
* @phpstan-param T $value
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function set($key, $value);
|
public function set(string|int $key, mixed $value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @phpstan-param Closure(T):U $func
|
||||||
|
*
|
||||||
|
* @return Collection<mixed>
|
||||||
|
* @phpstan-return Collection<TKey, U>
|
||||||
|
*
|
||||||
|
* @phpstan-template U
|
||||||
|
*/
|
||||||
|
public function map(Closure $func);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @phpstan-param Closure(T, TKey):bool $p
|
||||||
*
|
*
|
||||||
* @return Collection<mixed> A collection with the results of the filter operation.
|
* @return Collection<mixed> A collection with the results of the filter operation.
|
||||||
* @psalm-return Collection<TKey, T>
|
* @phpstan-return Collection<TKey, T>
|
||||||
*/
|
*/
|
||||||
public function filter(Closure $p);
|
public function filter(Closure $p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @phpstan-param Closure(TKey, T):bool $p
|
||||||
*
|
*
|
||||||
* @return Collection<mixed>[] An array with two elements. The first element contains the collection
|
* @return Collection<mixed>[] An array with two elements. The first element contains the collection
|
||||||
* of elements where the predicate returned TRUE, the second element
|
* of elements where the predicate returned TRUE, the second element
|
||||||
* contains the collection of elements where the predicate returned FALSE.
|
* contains the collection of elements where the predicate returned FALSE.
|
||||||
* @psalm-return array{0: Collection<TKey, T>, 1: Collection<TKey, T>}
|
* @phpstan-return array{0: Collection<TKey, T>, 1: Collection<TKey, T>}
|
||||||
*/
|
*/
|
||||||
public function partition(Closure $p);
|
public function partition(Closure $p);
|
||||||
}
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\Expr\CompositeExpression;
|
use Doctrine\Common\Collections\Expr\CompositeExpression;
|
||||||
@ -13,33 +15,28 @@ use function strtoupper;
|
|||||||
/**
|
/**
|
||||||
* Criteria for filtering Selectable collections.
|
* Criteria for filtering Selectable collections.
|
||||||
*
|
*
|
||||||
* @psalm-consistent-constructor
|
* @phpstan-consistent-constructor
|
||||||
*/
|
*/
|
||||||
class Criteria
|
class Criteria
|
||||||
{
|
{
|
||||||
public const ASC = 'ASC';
|
/** @deprecated use Order::Ascending instead */
|
||||||
|
final public const ASC = 'ASC';
|
||||||
|
|
||||||
public const DESC = 'DESC';
|
/** @deprecated use Order::Descending instead */
|
||||||
|
final public const DESC = 'DESC';
|
||||||
|
|
||||||
/** @var ExpressionBuilder|null */
|
private static ExpressionBuilder|null $expressionBuilder = null;
|
||||||
private static $expressionBuilder;
|
|
||||||
|
|
||||||
/** @var Expression|null */
|
/** @var array<string, Order> */
|
||||||
private $expression;
|
private array $orderings = [];
|
||||||
|
|
||||||
/** @var string[] */
|
private int|null $firstResult = null;
|
||||||
private $orderings = [];
|
private int|null $maxResults = null;
|
||||||
|
|
||||||
/** @var int|null */
|
|
||||||
private $firstResult;
|
|
||||||
|
|
||||||
/** @var int|null */
|
|
||||||
private $maxResults;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the class.
|
* Creates an instance of the class.
|
||||||
*
|
*
|
||||||
* @return Criteria
|
* @return static
|
||||||
*/
|
*/
|
||||||
public static function create()
|
public static function create()
|
||||||
{
|
{
|
||||||
@ -63,12 +60,14 @@ class Criteria
|
|||||||
/**
|
/**
|
||||||
* Construct a new Criteria.
|
* Construct a new Criteria.
|
||||||
*
|
*
|
||||||
* @param string[]|null $orderings
|
* @param array<string, string|Order>|null $orderings
|
||||||
* @param int|null $firstResult
|
|
||||||
* @param int|null $maxResults
|
|
||||||
*/
|
*/
|
||||||
public function __construct(?Expression $expression = null, ?array $orderings = null, $firstResult = null, $maxResults = null)
|
public function __construct(
|
||||||
{
|
private Expression|null $expression = null,
|
||||||
|
array|null $orderings = null,
|
||||||
|
int|null $firstResult = null,
|
||||||
|
int|null $maxResults = null,
|
||||||
|
) {
|
||||||
$this->expression = $expression;
|
$this->expression = $expression;
|
||||||
|
|
||||||
if ($firstResult === null && func_num_args() > 2) {
|
if ($firstResult === null && func_num_args() > 2) {
|
||||||
@ -76,7 +75,7 @@ class Criteria
|
|||||||
'doctrine/collections',
|
'doctrine/collections',
|
||||||
'https://github.com/doctrine/collections/pull/311',
|
'https://github.com/doctrine/collections/pull/311',
|
||||||
'Passing null as $firstResult to the constructor of %s is deprecated. Pass 0 instead or omit the argument.',
|
'Passing null as $firstResult to the constructor of %s is deprecated. Pass 0 instead or omit the argument.',
|
||||||
self::class
|
self::class,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ class Criteria
|
|||||||
|
|
||||||
$this->expression = new CompositeExpression(
|
$this->expression = new CompositeExpression(
|
||||||
CompositeExpression::TYPE_AND,
|
CompositeExpression::TYPE_AND,
|
||||||
[$this->expression, $expression]
|
[$this->expression, $expression],
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -136,7 +135,7 @@ class Criteria
|
|||||||
|
|
||||||
$this->expression = new CompositeExpression(
|
$this->expression = new CompositeExpression(
|
||||||
CompositeExpression::TYPE_OR,
|
CompositeExpression::TYPE_OR,
|
||||||
[$this->expression, $expression]
|
[$this->expression, $expression],
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -155,9 +154,32 @@ class Criteria
|
|||||||
/**
|
/**
|
||||||
* Gets the current orderings of this Criteria.
|
* Gets the current orderings of this Criteria.
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @deprecated use orderings() instead
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
*/
|
*/
|
||||||
public function getOrderings()
|
public function getOrderings()
|
||||||
|
{
|
||||||
|
Deprecation::trigger(
|
||||||
|
'doctrine/collections',
|
||||||
|
'https://github.com/doctrine/collections/pull/389',
|
||||||
|
'Calling %s() is deprecated. Use %s::orderings() instead.',
|
||||||
|
__METHOD__,
|
||||||
|
self::class,
|
||||||
|
);
|
||||||
|
|
||||||
|
return array_map(
|
||||||
|
static fn (Order $ordering): string => $ordering->value,
|
||||||
|
$this->orderings,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current orderings of this Criteria.
|
||||||
|
*
|
||||||
|
* @return array<string, Order>
|
||||||
|
*/
|
||||||
|
public function orderings(): array
|
||||||
{
|
{
|
||||||
return $this->orderings;
|
return $this->orderings;
|
||||||
}
|
}
|
||||||
@ -165,22 +187,40 @@ class Criteria
|
|||||||
/**
|
/**
|
||||||
* Sets the ordering of the result of this Criteria.
|
* Sets the ordering of the result of this Criteria.
|
||||||
*
|
*
|
||||||
* Keys are field and values are the order, being either ASC or DESC.
|
* Keys are field and values are the order, being a valid Order enum case.
|
||||||
*
|
*
|
||||||
* @see Criteria::ASC
|
* @see Order::Ascending
|
||||||
* @see Criteria::DESC
|
* @see Order::Descending
|
||||||
*
|
*
|
||||||
* @param string[] $orderings
|
* @param array<string, string|Order> $orderings
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function orderBy(array $orderings)
|
public function orderBy(array $orderings)
|
||||||
{
|
{
|
||||||
|
$method = __METHOD__;
|
||||||
$this->orderings = array_map(
|
$this->orderings = array_map(
|
||||||
static function (string $ordering): string {
|
static function (string|Order $ordering) use ($method): Order {
|
||||||
return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC;
|
if ($ordering instanceof Order) {
|
||||||
|
return $ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $triggered = false;
|
||||||
|
|
||||||
|
if (! $triggered) {
|
||||||
|
Deprecation::trigger(
|
||||||
|
'doctrine/collections',
|
||||||
|
'https://github.com/doctrine/collections/pull/389',
|
||||||
|
'Passing non-Order enum values to %s() is deprecated. Pass Order enum values instead.',
|
||||||
|
$method,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$triggered = true;
|
||||||
|
|
||||||
|
return strtoupper($ordering) === Order::Ascending->value ? Order::Ascending : Order::Descending;
|
||||||
},
|
},
|
||||||
$orderings
|
$orderings,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -203,14 +243,14 @@ class Criteria
|
|||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setFirstResult($firstResult)
|
public function setFirstResult(int|null $firstResult)
|
||||||
{
|
{
|
||||||
if ($firstResult === null) {
|
if ($firstResult === null) {
|
||||||
Deprecation::triggerIfCalledFromOutside(
|
Deprecation::triggerIfCalledFromOutside(
|
||||||
'doctrine/collections',
|
'doctrine/collections',
|
||||||
'https://github.com/doctrine/collections/pull/311',
|
'https://github.com/doctrine/collections/pull/311',
|
||||||
'Passing null to %s() is deprecated, pass 0 instead.',
|
'Passing null to %s() is deprecated, pass 0 instead.',
|
||||||
__METHOD__
|
__METHOD__,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +276,7 @@ class Criteria
|
|||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setMaxResults($maxResults)
|
public function setMaxResults(int|null $maxResults)
|
||||||
{
|
{
|
||||||
$this->maxResults = $maxResults;
|
$this->maxResults = $maxResults;
|
||||||
|
|
||||||
214
vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
vendored
Normal file
214
vendor/doctrine/collections/src/Expr/ClosureExpressionVisitor.php
vendored
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use Closure;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
use function array_all;
|
||||||
|
use function array_any;
|
||||||
|
use function explode;
|
||||||
|
use function in_array;
|
||||||
|
use function is_array;
|
||||||
|
use function is_scalar;
|
||||||
|
use function iterator_to_array;
|
||||||
|
use function method_exists;
|
||||||
|
use function preg_match;
|
||||||
|
use function preg_replace_callback;
|
||||||
|
use function str_contains;
|
||||||
|
use function str_ends_with;
|
||||||
|
use function str_starts_with;
|
||||||
|
use function strtoupper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walks an expression graph and turns it into a PHP closure.
|
||||||
|
*
|
||||||
|
* This closure can be used with {@Collection#filter()} and is used internally
|
||||||
|
* by {@ArrayCollection#select()}.
|
||||||
|
*/
|
||||||
|
class ClosureExpressionVisitor extends ExpressionVisitor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Accesses the field of a given object. This field has to be public
|
||||||
|
* directly or indirectly (through an accessor get*, is*, or a magic
|
||||||
|
* method, __get, __call).
|
||||||
|
*
|
||||||
|
* @param object|mixed[] $object
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getObjectFieldValue(object|array $object, string $field)
|
||||||
|
{
|
||||||
|
if (str_contains($field, '.')) {
|
||||||
|
[$field, $subField] = explode('.', $field, 2);
|
||||||
|
$object = self::getObjectFieldValue($object, $field);
|
||||||
|
|
||||||
|
return self::getObjectFieldValue($object, $subField);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($object)) {
|
||||||
|
return $object[$field];
|
||||||
|
}
|
||||||
|
|
||||||
|
$accessors = ['get', 'is', ''];
|
||||||
|
|
||||||
|
foreach ($accessors as $accessor) {
|
||||||
|
$accessor .= $field;
|
||||||
|
|
||||||
|
if (method_exists($object, $accessor)) {
|
||||||
|
return $object->$accessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) {
|
||||||
|
return $object->$field();
|
||||||
|
}
|
||||||
|
|
||||||
|
// __call should be triggered for get.
|
||||||
|
$accessor = $accessors[0] . $field;
|
||||||
|
|
||||||
|
if (method_exists($object, '__call')) {
|
||||||
|
return $object->$accessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object instanceof ArrayAccess) {
|
||||||
|
return $object[$field];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($object->$field)) {
|
||||||
|
return $object->$field;
|
||||||
|
}
|
||||||
|
|
||||||
|
// camelcase field name to support different variable naming conventions
|
||||||
|
$ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper((string) $matches[1]), $field);
|
||||||
|
|
||||||
|
foreach ($accessors as $accessor) {
|
||||||
|
$accessor .= $ccField;
|
||||||
|
|
||||||
|
if (method_exists($object, $accessor)) {
|
||||||
|
return $object->$accessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $object->$field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for sorting arrays of objects based on multiple fields + orientations.
|
||||||
|
*
|
||||||
|
* @return Closure
|
||||||
|
*/
|
||||||
|
public static function sortByField(string $name, int $orientation = 1, Closure|null $next = null)
|
||||||
|
{
|
||||||
|
if (! $next) {
|
||||||
|
$next = static fn (): int => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static function ($a, $b) use ($name, $next, $orientation): int {
|
||||||
|
$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
|
||||||
|
|
||||||
|
$bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
|
||||||
|
|
||||||
|
if ($aValue === $bValue) {
|
||||||
|
return $next($a, $b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($aValue > $bValue ? 1 : -1) * $orientation;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function walkComparison(Comparison $comparison)
|
||||||
|
{
|
||||||
|
$field = $comparison->getField();
|
||||||
|
$value = $comparison->getValue()->getValue();
|
||||||
|
|
||||||
|
return match ($comparison->getOperator()) {
|
||||||
|
Comparison::EQ => static fn ($object): bool => self::getObjectFieldValue($object, $field) === $value,
|
||||||
|
Comparison::NEQ => static fn ($object): bool => self::getObjectFieldValue($object, $field) !== $value,
|
||||||
|
Comparison::LT => static fn ($object): bool => self::getObjectFieldValue($object, $field) < $value,
|
||||||
|
Comparison::LTE => static fn ($object): bool => self::getObjectFieldValue($object, $field) <= $value,
|
||||||
|
Comparison::GT => static fn ($object): bool => self::getObjectFieldValue($object, $field) > $value,
|
||||||
|
Comparison::GTE => static fn ($object): bool => self::getObjectFieldValue($object, $field) >= $value,
|
||||||
|
Comparison::IN => static function ($object) use ($field, $value): bool {
|
||||||
|
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
||||||
|
|
||||||
|
return in_array($fieldValue, $value, is_scalar($fieldValue));
|
||||||
|
},
|
||||||
|
Comparison::NIN => static function ($object) use ($field, $value): bool {
|
||||||
|
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
||||||
|
|
||||||
|
return ! in_array($fieldValue, $value, is_scalar($fieldValue));
|
||||||
|
},
|
||||||
|
Comparison::CONTAINS => static fn ($object): bool => str_contains((string) self::getObjectFieldValue($object, $field), (string) $value),
|
||||||
|
Comparison::MEMBER_OF => static function ($object) use ($field, $value): bool {
|
||||||
|
$fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
|
||||||
|
|
||||||
|
if (! is_array($fieldValues)) {
|
||||||
|
$fieldValues = iterator_to_array($fieldValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($value, $fieldValues, true);
|
||||||
|
},
|
||||||
|
Comparison::STARTS_WITH => static fn ($object): bool => str_starts_with((string) self::getObjectFieldValue($object, $field), (string) $value),
|
||||||
|
Comparison::ENDS_WITH => static fn ($object): bool => str_ends_with((string) self::getObjectFieldValue($object, $field), (string) $value),
|
||||||
|
default => throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function walkValue(Value $value)
|
||||||
|
{
|
||||||
|
return $value->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function walkCompositeExpression(CompositeExpression $expr)
|
||||||
|
{
|
||||||
|
$expressionList = [];
|
||||||
|
|
||||||
|
foreach ($expr->getExpressionList() as $child) {
|
||||||
|
$expressionList[] = $this->dispatch($child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($expr->getType()) {
|
||||||
|
CompositeExpression::TYPE_AND => $this->andExpressions($expressionList),
|
||||||
|
CompositeExpression::TYPE_OR => $this->orExpressions($expressionList),
|
||||||
|
CompositeExpression::TYPE_NOT => $this->notExpression($expressionList),
|
||||||
|
default => throw new RuntimeException('Unknown composite ' . $expr->getType()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param callable[] $expressions */
|
||||||
|
private function andExpressions(array $expressions): Closure
|
||||||
|
{
|
||||||
|
return static fn ($object): bool => array_all(
|
||||||
|
$expressions,
|
||||||
|
static fn (callable $expression): bool => (bool) $expression($object),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param callable[] $expressions */
|
||||||
|
private function orExpressions(array $expressions): Closure
|
||||||
|
{
|
||||||
|
return static fn ($object): bool => array_any(
|
||||||
|
$expressions,
|
||||||
|
static fn (callable $expression): bool => (bool) $expression($object),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param callable[] $expressions */
|
||||||
|
private function notExpression(array $expressions): Closure
|
||||||
|
{
|
||||||
|
return static fn ($object) => ! $expressions[0]($object);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
vendor/doctrine/collections/src/Expr/Comparison.php
vendored
Normal file
62
vendor/doctrine/collections/src/Expr/Comparison.php
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison of a field with a value by the given operator.
|
||||||
|
*/
|
||||||
|
class Comparison implements Expression
|
||||||
|
{
|
||||||
|
final public const EQ = '=';
|
||||||
|
final public const NEQ = '<>';
|
||||||
|
final public const LT = '<';
|
||||||
|
final public const LTE = '<=';
|
||||||
|
final public const GT = '>';
|
||||||
|
final public const GTE = '>=';
|
||||||
|
final public const IS = '='; // no difference with EQ
|
||||||
|
final public const IN = 'IN';
|
||||||
|
final public const NIN = 'NIN';
|
||||||
|
final public const CONTAINS = 'CONTAINS';
|
||||||
|
final public const MEMBER_OF = 'MEMBER_OF';
|
||||||
|
final public const STARTS_WITH = 'STARTS_WITH';
|
||||||
|
final public const ENDS_WITH = 'ENDS_WITH';
|
||||||
|
|
||||||
|
private readonly Value $value;
|
||||||
|
|
||||||
|
public function __construct(private readonly string $field, private readonly string $op, mixed $value)
|
||||||
|
{
|
||||||
|
if (! ($value instanceof Value)) {
|
||||||
|
$value = new Value($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return string */
|
||||||
|
public function getField()
|
||||||
|
{
|
||||||
|
return $this->field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Value */
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return string */
|
||||||
|
public function getOperator()
|
||||||
|
{
|
||||||
|
return $this->op;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function visit(ExpressionVisitor $visitor)
|
||||||
|
{
|
||||||
|
return $visitor->walkComparison($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,33 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
|
use function count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression of Expressions combined by AND or OR operation.
|
* Expression of Expressions combined by AND or OR operation.
|
||||||
*/
|
*/
|
||||||
class CompositeExpression implements Expression
|
class CompositeExpression implements Expression
|
||||||
{
|
{
|
||||||
public const TYPE_AND = 'AND';
|
final public const TYPE_AND = 'AND';
|
||||||
public const TYPE_OR = 'OR';
|
final public const TYPE_OR = 'OR';
|
||||||
|
final public const TYPE_NOT = 'NOT';
|
||||||
|
|
||||||
/** @var string */
|
/** @var list<Expression> */
|
||||||
private $type;
|
private array $expressions = [];
|
||||||
|
|
||||||
/** @var Expression[] */
|
|
||||||
private $expressions = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param Expression[] $expressions
|
||||||
* @param mixed[] $expressions
|
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public function __construct($type, array $expressions)
|
public function __construct(private readonly string $type, array $expressions)
|
||||||
{
|
{
|
||||||
$this->type = $type;
|
|
||||||
|
|
||||||
foreach ($expressions as $expr) {
|
foreach ($expressions as $expr) {
|
||||||
if ($expr instanceof Value) {
|
if ($expr instanceof Value) {
|
||||||
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
|
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
|
||||||
@ -39,12 +38,16 @@ class CompositeExpression implements Expression
|
|||||||
|
|
||||||
$this->expressions[] = $expr;
|
$this->expressions[] = $expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($type === self::TYPE_NOT && count($this->expressions) !== 1) {
|
||||||
|
throw new RuntimeException('Not expression only allows one expression as child.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of expressions nested in this composite.
|
* Returns the list of expressions nested in this composite.
|
||||||
*
|
*
|
||||||
* @return Expression[]
|
* @return list<Expression>
|
||||||
*/
|
*/
|
||||||
public function getExpressionList()
|
public function getExpressionList()
|
||||||
{
|
{
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
use function get_class;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Expression visitor walks a graph of expressions and turns them into a
|
* An Expression visitor walks a graph of expressions and turns them into a
|
||||||
* query for the underlying implementation.
|
* query for the underlying implementation.
|
||||||
@ -42,18 +42,11 @@ abstract class ExpressionVisitor
|
|||||||
*/
|
*/
|
||||||
public function dispatch(Expression $expr)
|
public function dispatch(Expression $expr)
|
||||||
{
|
{
|
||||||
switch (true) {
|
return match (true) {
|
||||||
case $expr instanceof Comparison:
|
$expr instanceof Comparison => $this->walkComparison($expr),
|
||||||
return $this->walkComparison($expr);
|
$expr instanceof Value => $this->walkValue($expr),
|
||||||
|
$expr instanceof CompositeExpression => $this->walkCompositeExpression($expr),
|
||||||
case $expr instanceof Value:
|
default => throw new RuntimeException('Unknown Expression ' . $expr::class),
|
||||||
return $this->walkValue($expr);
|
};
|
||||||
|
|
||||||
case $expr instanceof CompositeExpression:
|
|
||||||
return $this->walkCompositeExpression($expr);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new RuntimeException('Unknown Expression ' . get_class($expr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,16 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections\Expr;
|
namespace Doctrine\Common\Collections\Expr;
|
||||||
|
|
||||||
class Value implements Expression
|
class Value implements Expression
|
||||||
{
|
{
|
||||||
/** @var mixed */
|
public function __construct(private readonly mixed $value)
|
||||||
private $value;
|
|
||||||
|
|
||||||
/** @param mixed $value */
|
|
||||||
public function __construct($value)
|
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return mixed */
|
/** @return mixed */
|
||||||
128
vendor/doctrine/collections/src/ExpressionBuilder.php
vendored
Normal file
128
vendor/doctrine/collections/src/ExpressionBuilder.php
vendored
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\Expr\Comparison;
|
||||||
|
use Doctrine\Common\Collections\Expr\CompositeExpression;
|
||||||
|
use Doctrine\Common\Collections\Expr\Expression;
|
||||||
|
use Doctrine\Common\Collections\Expr\Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for Expressions in the {@link Selectable} interface.
|
||||||
|
*
|
||||||
|
* Important Notice for interoperable code: You have to use scalar
|
||||||
|
* values only for comparisons, otherwise the behavior of the comparison
|
||||||
|
* may be different between implementations (Array vs ORM vs ODM).
|
||||||
|
*/
|
||||||
|
class ExpressionBuilder
|
||||||
|
{
|
||||||
|
/** @return CompositeExpression */
|
||||||
|
public function andX(Expression ...$expressions)
|
||||||
|
{
|
||||||
|
return new CompositeExpression(CompositeExpression::TYPE_AND, $expressions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return CompositeExpression */
|
||||||
|
public function orX(Expression ...$expressions)
|
||||||
|
{
|
||||||
|
return new CompositeExpression(CompositeExpression::TYPE_OR, $expressions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function not(Expression $expression): CompositeExpression
|
||||||
|
{
|
||||||
|
return new CompositeExpression(CompositeExpression::TYPE_NOT, [$expression]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function eq(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::EQ, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function gt(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::GT, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function lt(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::LT, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function gte(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::GTE, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function lte(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::LTE, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function neq(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::NEQ, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function isNull(string $field)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::EQ, new Value(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isNotNull(string $field): Comparison
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::NEQ, new Value(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $values
|
||||||
|
*
|
||||||
|
* @return Comparison
|
||||||
|
*/
|
||||||
|
public function in(string $field, array $values)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::IN, new Value($values));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $values
|
||||||
|
*
|
||||||
|
* @return Comparison
|
||||||
|
*/
|
||||||
|
public function notIn(string $field, array $values)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::NIN, new Value($values));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function contains(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::CONTAINS, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function memberOf(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::MEMBER_OF, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function startsWith(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::STARTS_WITH, new Value($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Comparison */
|
||||||
|
public function endsWith(string $field, mixed $value)
|
||||||
|
{
|
||||||
|
return new Comparison($field, Comparison::ENDS_WITH, new Value($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
11
vendor/doctrine/collections/src/Order.php
vendored
Normal file
11
vendor/doctrine/collections/src/Order.php
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
|
enum Order: string
|
||||||
|
{
|
||||||
|
case Ascending = 'ASC';
|
||||||
|
case Descending = 'DESC';
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
@ -7,7 +9,7 @@ use Countable;
|
|||||||
use IteratorAggregate;
|
use IteratorAggregate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-template TKey of array-key
|
* @phpstan-template TKey of array-key
|
||||||
* @template-covariant T
|
* @template-covariant T
|
||||||
* @template-extends IteratorAggregate<TKey, T>
|
* @template-extends IteratorAggregate<TKey, T>
|
||||||
*/
|
*/
|
||||||
@ -18,14 +20,14 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* This is an O(n) operation, where n is the size of the collection.
|
* This is an O(n) operation, where n is the size of the collection.
|
||||||
*
|
*
|
||||||
* @param mixed $element The element to search for.
|
* @param mixed $element The element to search for.
|
||||||
* @psalm-param TMaybeContained $element
|
* @phpstan-param TMaybeContained $element
|
||||||
*
|
*
|
||||||
* @return bool TRUE if the collection contains the element, FALSE otherwise.
|
* @return bool TRUE if the collection contains the element, FALSE otherwise.
|
||||||
* @psalm-return (TMaybeContained is T ? bool : false)
|
* @phpstan-return (TMaybeContained is T ? bool : false)
|
||||||
*
|
*
|
||||||
* @template TMaybeContained
|
* @template TMaybeContained
|
||||||
*/
|
*/
|
||||||
public function contains($element);
|
public function contains(mixed $element);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the collection is empty (contains no elements).
|
* Checks whether the collection is empty (contains no elements).
|
||||||
@ -38,30 +40,30 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Checks whether the collection contains an element with the specified key/index.
|
* Checks whether the collection contains an element with the specified key/index.
|
||||||
*
|
*
|
||||||
* @param string|int $key The key/index to check for.
|
* @param string|int $key The key/index to check for.
|
||||||
* @psalm-param TKey $key
|
* @phpstan-param TKey $key
|
||||||
*
|
*
|
||||||
* @return bool TRUE if the collection contains an element with the specified key/index,
|
* @return bool TRUE if the collection contains an element with the specified key/index,
|
||||||
* FALSE otherwise.
|
* FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
public function containsKey($key);
|
public function containsKey(string|int $key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the element at the specified key/index.
|
* Gets the element at the specified key/index.
|
||||||
*
|
*
|
||||||
* @param string|int $key The key/index of the element to retrieve.
|
* @param string|int $key The key/index of the element to retrieve.
|
||||||
* @psalm-param TKey $key
|
* @phpstan-param TKey $key
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @psalm-return T|null
|
* @phpstan-return T|null
|
||||||
*/
|
*/
|
||||||
public function get($key);
|
public function get(string|int $key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all keys/indices of the collection.
|
* Gets all keys/indices of the collection.
|
||||||
*
|
*
|
||||||
* @return int[]|string[] The keys/indices of the collection, in the order of the corresponding
|
* @return int[]|string[] The keys/indices of the collection, in the order of the corresponding
|
||||||
* elements in the collection.
|
* elements in the collection.
|
||||||
* @psalm-return list<TKey>
|
* @phpstan-return list<TKey>
|
||||||
*/
|
*/
|
||||||
public function getKeys();
|
public function getKeys();
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
*
|
*
|
||||||
* @return mixed[] The values of all elements in the collection, in the
|
* @return mixed[] The values of all elements in the collection, in the
|
||||||
* order they appear in the collection.
|
* order they appear in the collection.
|
||||||
* @psalm-return list<T>
|
* @phpstan-return list<T>
|
||||||
*/
|
*/
|
||||||
public function getValues();
|
public function getValues();
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Gets a native PHP array representation of the collection.
|
* Gets a native PHP array representation of the collection.
|
||||||
*
|
*
|
||||||
* @return mixed[]
|
* @return mixed[]
|
||||||
* @psalm-return array<TKey,T>
|
* @phpstan-return array<TKey,T>
|
||||||
*/
|
*/
|
||||||
public function toArray();
|
public function toArray();
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Sets the internal iterator to the first element in the collection and returns this element.
|
* Sets the internal iterator to the first element in the collection and returns this element.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @psalm-return T|false
|
* @phpstan-return T|false
|
||||||
*/
|
*/
|
||||||
public function first();
|
public function first();
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Sets the internal iterator to the last element in the collection and returns this element.
|
* Sets the internal iterator to the last element in the collection and returns this element.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @psalm-return T|false
|
* @phpstan-return T|false
|
||||||
*/
|
*/
|
||||||
public function last();
|
public function last();
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Gets the key/index of the element at the current iterator position.
|
* Gets the key/index of the element at the current iterator position.
|
||||||
*
|
*
|
||||||
* @return int|string|null
|
* @return int|string|null
|
||||||
* @psalm-return TKey|null
|
* @phpstan-return TKey|null
|
||||||
*/
|
*/
|
||||||
public function key();
|
public function key();
|
||||||
|
|
||||||
@ -110,7 +112,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Gets the element of the collection at the current iterator position.
|
* Gets the element of the collection at the current iterator position.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @psalm-return T|false
|
* @phpstan-return T|false
|
||||||
*/
|
*/
|
||||||
public function current();
|
public function current();
|
||||||
|
|
||||||
@ -118,7 +120,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Moves the internal iterator position to the next element and returns this element.
|
* Moves the internal iterator position to the next element and returns this element.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @psalm-return T|false
|
* @phpstan-return T|false
|
||||||
*/
|
*/
|
||||||
public function next();
|
public function next();
|
||||||
|
|
||||||
@ -133,15 +135,15 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* @param int|null $length The maximum number of elements to return, or null for no limit.
|
* @param int|null $length The maximum number of elements to return, or null for no limit.
|
||||||
*
|
*
|
||||||
* @return mixed[]
|
* @return mixed[]
|
||||||
* @psalm-return array<TKey,T>
|
* @phpstan-return array<TKey,T>
|
||||||
*/
|
*/
|
||||||
public function slice($offset, $length = null);
|
public function slice(int $offset, int|null $length = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the existence of an element that satisfies the given predicate.
|
* Tests for the existence of an element that satisfies the given predicate.
|
||||||
*
|
*
|
||||||
* @param Closure $p The predicate.
|
* @param Closure $p The predicate.
|
||||||
* @psalm-param Closure(TKey, T):bool $p
|
* @phpstan-param Closure(TKey, T):bool $p
|
||||||
*
|
*
|
||||||
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
|
* @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
@ -152,10 +154,10 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* The order of the elements is preserved.
|
* The order of the elements is preserved.
|
||||||
*
|
*
|
||||||
* @param Closure $p The predicate used for filtering.
|
* @param Closure $p The predicate used for filtering.
|
||||||
* @psalm-param Closure(T):bool $p
|
* @phpstan-param Closure(T, TKey):bool $p
|
||||||
*
|
*
|
||||||
* @return ReadableCollection<mixed> A collection with the results of the filter operation.
|
* @return ReadableCollection<mixed> A collection with the results of the filter operation.
|
||||||
* @psalm-return ReadableCollection<TKey, T>
|
* @phpstan-return ReadableCollection<TKey, T>
|
||||||
*/
|
*/
|
||||||
public function filter(Closure $p);
|
public function filter(Closure $p);
|
||||||
|
|
||||||
@ -163,12 +165,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Applies the given function to each element in the collection and returns
|
* Applies the given function to each element in the collection and returns
|
||||||
* a new collection with the elements returned by the function.
|
* a new collection with the elements returned by the function.
|
||||||
*
|
*
|
||||||
* @psalm-param Closure(T):U $func
|
* @phpstan-param Closure(T):U $func
|
||||||
*
|
*
|
||||||
* @return Collection<mixed>
|
* @return ReadableCollection<mixed>
|
||||||
* @psalm-return Collection<TKey, U>
|
* @phpstan-return ReadableCollection<TKey, U>
|
||||||
*
|
*
|
||||||
* @psalm-template U
|
* @phpstan-template U
|
||||||
*/
|
*/
|
||||||
public function map(Closure $func);
|
public function map(Closure $func);
|
||||||
|
|
||||||
@ -177,12 +179,12 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Keys are preserved in the resulting collections.
|
* Keys are preserved in the resulting collections.
|
||||||
*
|
*
|
||||||
* @param Closure $p The predicate on which to partition.
|
* @param Closure $p The predicate on which to partition.
|
||||||
* @psalm-param Closure(TKey, T):bool $p
|
* @phpstan-param Closure(TKey, T):bool $p
|
||||||
*
|
*
|
||||||
* @return ReadableCollection<mixed>[] An array with two elements. The first element contains the collection
|
* @return ReadableCollection<mixed>[] An array with two elements. The first element contains the collection
|
||||||
* of elements where the predicate returned TRUE, the second element
|
* of elements where the predicate returned TRUE, the second element
|
||||||
* contains the collection of elements where the predicate returned FALSE.
|
* contains the collection of elements where the predicate returned FALSE.
|
||||||
* @psalm-return array{0: ReadableCollection<TKey, T>, 1: ReadableCollection<TKey, T>}
|
* @phpstan-return array{0: ReadableCollection<TKey, T>, 1: ReadableCollection<TKey, T>}
|
||||||
*/
|
*/
|
||||||
public function partition(Closure $p);
|
public function partition(Closure $p);
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* Tests whether the given predicate p holds for all elements of this collection.
|
* Tests whether the given predicate p holds for all elements of this collection.
|
||||||
*
|
*
|
||||||
* @param Closure $p The predicate.
|
* @param Closure $p The predicate.
|
||||||
* @psalm-param Closure(TKey, T):bool $p
|
* @phpstan-param Closure(TKey, T):bool $p
|
||||||
*
|
*
|
||||||
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
|
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
@ -202,12 +204,39 @@ interface ReadableCollection extends Countable, IteratorAggregate
|
|||||||
* For objects this means reference equality.
|
* For objects this means reference equality.
|
||||||
*
|
*
|
||||||
* @param mixed $element The element to search for.
|
* @param mixed $element The element to search for.
|
||||||
* @psalm-param TMaybeContained $element
|
* @phpstan-param TMaybeContained $element
|
||||||
*
|
*
|
||||||
* @return int|string|bool The key/index of the element or FALSE if the element was not found.
|
* @return int|string|bool The key/index of the element or FALSE if the element was not found.
|
||||||
* @psalm-return (TMaybeContained is T ? TKey|false : false)
|
* @phpstan-return (TMaybeContained is T ? TKey|false : false)
|
||||||
*
|
*
|
||||||
* @template TMaybeContained
|
* @template TMaybeContained
|
||||||
*/
|
*/
|
||||||
public function indexOf($element);
|
public function indexOf(mixed $element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first element of this collection that satisfies the predicate p.
|
||||||
|
*
|
||||||
|
* @param Closure $p The predicate.
|
||||||
|
* @phpstan-param Closure(TKey, T):bool $p
|
||||||
|
*
|
||||||
|
* @return mixed The first element respecting the predicate,
|
||||||
|
* null if no element respects the predicate.
|
||||||
|
* @phpstan-return T|null
|
||||||
|
*/
|
||||||
|
public function findFirst(Closure $p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies iteratively the given function to each element in the collection,
|
||||||
|
* so as to reduce the collection to a single value.
|
||||||
|
*
|
||||||
|
* @phpstan-param Closure(TReturn|TInitial, T):TReturn $func
|
||||||
|
* @phpstan-param TInitial $initial
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @phpstan-return TReturn|TInitial
|
||||||
|
*
|
||||||
|
* @phpstan-template TReturn
|
||||||
|
* @phpstan-template TInitial
|
||||||
|
*/
|
||||||
|
public function reduce(Closure $func, mixed $initial = null);
|
||||||
}
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Doctrine\Common\Collections;
|
namespace Doctrine\Common\Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,17 +16,17 @@ namespace Doctrine\Common\Collections;
|
|||||||
* this API can implement efficient database access without having to ask the
|
* this API can implement efficient database access without having to ask the
|
||||||
* EntityManager or Repositories.
|
* EntityManager or Repositories.
|
||||||
*
|
*
|
||||||
* @psalm-template TKey as array-key
|
* @phpstan-template TKey as array-key
|
||||||
* @psalm-template T
|
* @phpstan-template-covariant T
|
||||||
*/
|
*/
|
||||||
interface Selectable
|
interface Selectable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Selects all elements from a selectable that match the expression and
|
* Selects all elements from a selectable that match the expression and
|
||||||
* returns a new collection containing these elements.
|
* returns a new collection containing these elements and preserved keys.
|
||||||
*
|
*
|
||||||
* @return Collection<mixed>&Selectable<mixed>
|
* @return ReadableCollection<mixed>&Selectable<mixed>
|
||||||
* @psalm-return Collection<TKey,T>&Selectable<TKey,T>
|
* @phpstan-return ReadableCollection<TKey,T>&Selectable<TKey,T>
|
||||||
*/
|
*/
|
||||||
public function matching(Criteria $criteria);
|
public function matching(Criteria $criteria);
|
||||||
}
|
}
|
||||||
3
vendor/ipl/html/composer.json
vendored
3
vendor/ipl/html/composer.json
vendored
@ -9,7 +9,7 @@
|
|||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"ipl/stdlib": ">=0.12.0",
|
"ipl/stdlib": ">=0.12.0",
|
||||||
"ipl/validator": ">=0.5.0",
|
"ipl/validator": ">=0.5.0",
|
||||||
@ -17,6 +17,7 @@
|
|||||||
"guzzlehttp/psr7": "^2.5"
|
"guzzlehttp/psr7": "^2.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"ext-dom": "*",
|
||||||
"ipl/stdlib": "dev-main",
|
"ipl/stdlib": "dev-main",
|
||||||
"ipl/validator": "dev-main"
|
"ipl/validator": "dev-main"
|
||||||
},
|
},
|
||||||
|
|||||||
47
vendor/ipl/html/src/Attribute.php
vendored
47
vendor/ipl/html/src/Attribute.php
vendored
@ -12,6 +12,9 @@ use InvalidArgumentException;
|
|||||||
*
|
*
|
||||||
* Usually attributes are not instantiated directly, but created through an HTML
|
* Usually attributes are not instantiated directly, but created through an HTML
|
||||||
* element's exposed methods.
|
* element's exposed methods.
|
||||||
|
*
|
||||||
|
* @phpstan-type _AttributeScalar string|bool|null
|
||||||
|
* @phpstan-type AttributeValue _AttributeScalar|array<_AttributeScalar>
|
||||||
*/
|
*/
|
||||||
class Attribute
|
class Attribute
|
||||||
{
|
{
|
||||||
@ -21,14 +24,14 @@ class Attribute
|
|||||||
/** @var string The separator used if value is an array */
|
/** @var string The separator used if value is an array */
|
||||||
protected $separator = ' ';
|
protected $separator = ' ';
|
||||||
|
|
||||||
/** @var string|array|bool|null */
|
/** @var AttributeValue */
|
||||||
protected $value;
|
protected $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new HTML attribute from the given name and value
|
* Create a new HTML attribute from the given name and value
|
||||||
*
|
*
|
||||||
* @param string $name The name of the attribute
|
* @param string $name The name of the attribute
|
||||||
* @param string|bool|array|null $value The value of the attribute
|
* @param AttributeValue $value The value of the attribute
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException If the name of the attribute contains special characters
|
* @throws InvalidArgumentException If the name of the attribute contains special characters
|
||||||
*/
|
*/
|
||||||
@ -40,8 +43,8 @@ class Attribute
|
|||||||
/**
|
/**
|
||||||
* Create a new HTML attribute from the given name and value
|
* Create a new HTML attribute from the given name and value
|
||||||
*
|
*
|
||||||
* @param string $name The name of the attribute
|
* @param string $name The name of the attribute
|
||||||
* @param string|bool|array|null $value The value of the attribute
|
* @param AttributeValue $value The value of the attribute
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
*
|
*
|
||||||
@ -68,6 +71,28 @@ class Attribute
|
|||||||
return new static($name, null);
|
return new static($name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize the given ID
|
||||||
|
*
|
||||||
|
* Removes all characters that are not alphanumeric, underscore or hyphen. Additionally,
|
||||||
|
* the result is enforced to not start with a number by prepending the letter 'a'.
|
||||||
|
* Use it if you need to ensure that an ID is safe to use in CSS selectors.
|
||||||
|
*
|
||||||
|
* @param non-empty-string $id
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the ID is an empty string
|
||||||
|
*/
|
||||||
|
public static function sanitizeId(string $id): string
|
||||||
|
{
|
||||||
|
if (empty($id)) {
|
||||||
|
throw new InvalidArgumentException('ID must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'a' . preg_replace('/[^a-z0-9_\-]/i', '', $id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape the name of an attribute
|
* Escape the name of an attribute
|
||||||
*
|
*
|
||||||
@ -91,8 +116,8 @@ class Attribute
|
|||||||
* Values are escaped according to the HTML5 double-quoted attribute value syntax:
|
* Values are escaped according to the HTML5 double-quoted attribute value syntax:
|
||||||
* {@link https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 }.
|
* {@link https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 }.
|
||||||
*
|
*
|
||||||
* @param string|array $value
|
* @param string|string[] $value
|
||||||
* @param string $glue Glue string to join elements if value is an array
|
* @param string $glue Glue string to join elements if value is an array
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -184,7 +209,7 @@ class Attribute
|
|||||||
/**
|
/**
|
||||||
* Get the value of the attribute
|
* Get the value of the attribute
|
||||||
*
|
*
|
||||||
* @return string|bool|array|null
|
* @return AttributeValue
|
||||||
*/
|
*/
|
||||||
public function getValue()
|
public function getValue()
|
||||||
{
|
{
|
||||||
@ -194,7 +219,7 @@ class Attribute
|
|||||||
/**
|
/**
|
||||||
* Set the value of the attribute
|
* Set the value of the attribute
|
||||||
*
|
*
|
||||||
* @param string|bool|array|null $value
|
* @param AttributeValue $value
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -208,7 +233,7 @@ class Attribute
|
|||||||
/**
|
/**
|
||||||
* Add the given value(s) to the attribute
|
* Add the given value(s) to the attribute
|
||||||
*
|
*
|
||||||
* @param string|array $value The value(s) to add
|
* @param AttributeValue $value The value(s) to add
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -230,7 +255,7 @@ class Attribute
|
|||||||
*
|
*
|
||||||
* Does nothing if there is no such value to remove.
|
* Does nothing if there is no such value to remove.
|
||||||
*
|
*
|
||||||
* @param string|array $value The value(s) to remove
|
* @param AttributeValue $value The value(s) to remove
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
|
|||||||
24
vendor/ipl/html/src/Attributes.php
vendored
24
vendor/ipl/html/src/Attributes.php
vendored
@ -17,6 +17,9 @@ use function ipl\Stdlib\get_php_type;
|
|||||||
* behavior in various ways.
|
* behavior in various ways.
|
||||||
*
|
*
|
||||||
* Attributes usually come in name-value pairs and are rendered as name="value".
|
* Attributes usually come in name-value pairs and are rendered as name="value".
|
||||||
|
*
|
||||||
|
* @phpstan-import-type AttributeValue from Attribute
|
||||||
|
* @phpstan-type AttributesType array<string, AttributeValue>
|
||||||
*/
|
*/
|
||||||
class Attributes implements ArrayAccess, IteratorAggregate
|
class Attributes implements ArrayAccess, IteratorAggregate
|
||||||
{
|
{
|
||||||
@ -35,7 +38,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
/**
|
/**
|
||||||
* Create new HTML attributes
|
* Create new HTML attributes
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param AttributesType $attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $attributes = null)
|
public function __construct(array $attributes = null)
|
||||||
{
|
{
|
||||||
@ -57,7 +60,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
/**
|
/**
|
||||||
* Create new HTML attributes
|
* Create new HTML attributes
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param AttributesType $attributes
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
@ -76,7 +79,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
* construct and return a new Attributes instance.
|
* construct and return a new Attributes instance.
|
||||||
* If the attributes are null, an empty new instance of Attributes is returned.
|
* If the attributes are null, an empty new instance of Attributes is returned.
|
||||||
*
|
*
|
||||||
* @param array|static|null $attributes
|
* @param AttributesType|static|null $attributes
|
||||||
*
|
*
|
||||||
* @return static
|
* @return static
|
||||||
*
|
*
|
||||||
@ -174,8 +177,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
*
|
*
|
||||||
* If the attribute with the given name already exists, it gets overridden.
|
* If the attribute with the given name already exists, it gets overridden.
|
||||||
*
|
*
|
||||||
* @param string|array|Attribute|self $attribute The attribute(s) to add
|
* @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
|
||||||
* @param string|bool|array $value The value of the attribute
|
* @param AttributeValue $value The value of the attribute
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*
|
*
|
||||||
@ -224,8 +227,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
* If an attribute with the same name already exists, the attribute's value will be added to the current value of
|
* If an attribute with the same name already exists, the attribute's value will be added to the current value of
|
||||||
* the attribute.
|
* the attribute.
|
||||||
*
|
*
|
||||||
* @param string|array|Attribute|self $attribute The attribute(s) to add
|
* @param string|AttributesType|Attribute|self $attribute The attribute(s) to add
|
||||||
* @param string|bool|array $value The value of the attribute
|
* @param AttributeValue $value The value of the attribute
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*
|
*
|
||||||
@ -246,6 +249,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($attribute)) {
|
if (is_array($attribute)) {
|
||||||
|
// TODO: Handle if $attribute = [new Attribute('class', 'bar')]
|
||||||
foreach ($attribute as $name => $value) {
|
foreach ($attribute as $name => $value) {
|
||||||
$this->add($name, $value);
|
$this->add($name, $value);
|
||||||
}
|
}
|
||||||
@ -280,7 +284,7 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
* Remove the attribute with the given name or remove the given value from the attribute
|
* Remove the attribute with the given name or remove the given value from the attribute
|
||||||
*
|
*
|
||||||
* @param string $name The name of the attribute
|
* @param string $name The name of the attribute
|
||||||
* @param null|string|array $value The value to remove if specified
|
* @param AttributeValue $value The value to remove if specified
|
||||||
*
|
*
|
||||||
* @return ?Attribute The removed or changed attribute, if any, otherwise null
|
* @return ?Attribute The removed or changed attribute, if any, otherwise null
|
||||||
*/
|
*/
|
||||||
@ -479,8 +483,8 @@ class Attributes implements ArrayAccess, IteratorAggregate
|
|||||||
*
|
*
|
||||||
* If the attribute with the given name already exists, it gets overridden.
|
* If the attribute with the given name already exists, it gets overridden.
|
||||||
*
|
*
|
||||||
* @param string $name Name of the attribute
|
* @param string $name Name of the attribute
|
||||||
* @param mixed $value Value of the attribute
|
* @param AttributeValue $value Value of the attribute
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException If the attribute name contains special characters
|
* @throws InvalidArgumentException If the attribute name contains special characters
|
||||||
*/
|
*/
|
||||||
|
|||||||
66
vendor/ipl/html/src/BaseHtmlElement.php
vendored
66
vendor/ipl/html/src/BaseHtmlElement.php
vendored
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace ipl\Html;
|
namespace ipl\Html;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use ipl\Html\Contract\HtmlElementInterface;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +32,7 @@ use RuntimeException;
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
abstract class BaseHtmlElement extends HtmlDocument
|
abstract class BaseHtmlElement extends HtmlDocument implements HtmlElementInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List of void elements which must not contain end tags or content
|
* List of void elements which must not contain end tags or content
|
||||||
@ -76,11 +76,6 @@ abstract class BaseHtmlElement extends HtmlDocument
|
|||||||
/** @var string Tag of element. Set this property in order to provide the element's tag when extending this class */
|
/** @var string Tag of element. Set this property in order to provide the element's tag when extending this class */
|
||||||
protected $tag;
|
protected $tag;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the attributes of the element
|
|
||||||
*
|
|
||||||
* @return Attributes
|
|
||||||
*/
|
|
||||||
public function getAttributes()
|
public function getAttributes()
|
||||||
{
|
{
|
||||||
if ($this->attributes === null) {
|
if ($this->attributes === null) {
|
||||||
@ -97,6 +92,13 @@ abstract class BaseHtmlElement extends HtmlDocument
|
|||||||
return $this->attributes;
|
return $this->attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addAttributes($attributes)
|
||||||
|
{
|
||||||
|
$this->getAttributes()->add($attributes);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the attributes of the element
|
* Set the attributes of the element
|
||||||
*
|
*
|
||||||
@ -114,44 +116,16 @@ abstract class BaseHtmlElement extends HtmlDocument
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the attribute with the given name exists, false otherwise
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasAttribute(string $name): bool
|
public function hasAttribute(string $name): bool
|
||||||
{
|
{
|
||||||
return $this->getAttributes()->has($name);
|
return $this->getAttributes()->has($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the attribute with the given name
|
|
||||||
*
|
|
||||||
* If the attribute does not already exist, an empty one is automatically created and added to the attributes.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
*
|
|
||||||
* @return Attribute
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException If the attribute does not yet exist and its name contains special characters
|
|
||||||
*/
|
|
||||||
public function getAttribute(string $name): Attribute
|
public function getAttribute(string $name): Attribute
|
||||||
{
|
{
|
||||||
return $this->getAttributes()->get($name);
|
return $this->getAttributes()->get($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the attribute with the given name and value
|
|
||||||
*
|
|
||||||
* If the attribute with the given name already exists, it gets overridden.
|
|
||||||
*
|
|
||||||
* @param string $name The name of the attribute
|
|
||||||
* @param string|bool|array $value The value of the attribute
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setAttribute($name, $value)
|
public function setAttribute($name, $value)
|
||||||
{
|
{
|
||||||
$this->getAttributes()->set($name, $value);
|
$this->getAttributes()->set($name, $value);
|
||||||
@ -159,33 +133,11 @@ abstract class BaseHtmlElement extends HtmlDocument
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the attribute with the given name or remove the given value from the attribute
|
|
||||||
*
|
|
||||||
* @param string $name The name of the attribute
|
|
||||||
* @param null|string|array $value The value to remove if specified
|
|
||||||
*
|
|
||||||
* @return ?Attribute The removed or changed attribute, if any, otherwise null
|
|
||||||
*/
|
|
||||||
public function removeAttribute(string $name, $value = null): ?Attribute
|
public function removeAttribute(string $name, $value = null): ?Attribute
|
||||||
{
|
{
|
||||||
return $this->getAttributes()->remove($name, $value);
|
return $this->getAttributes()->remove($name, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the given attributes
|
|
||||||
*
|
|
||||||
* @param Attributes|array $attributes
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function addAttributes($attributes)
|
|
||||||
{
|
|
||||||
$this->getAttributes()->add($attributes);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default attributes of the element
|
* Get the default attributes of the element
|
||||||
*
|
*
|
||||||
|
|||||||
32
vendor/ipl/html/src/Contract/DecorableFormElement.php
vendored
Normal file
32
vendor/ipl/html/src/Contract/DecorableFormElement.php
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\FormDecoration\DecoratorChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of form elements that support decoration
|
||||||
|
*/
|
||||||
|
interface DecorableFormElement
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get all decorators of this element
|
||||||
|
*
|
||||||
|
* @return DecoratorChain<FormElementDecoration>
|
||||||
|
*/
|
||||||
|
public function getDecorators(): DecoratorChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the element has any decorators
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasDecorators(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate the element using its decorators
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function applyDecoration(): void;
|
||||||
|
}
|
||||||
35
vendor/ipl/html/src/Contract/DecorationResult.php
vendored
Normal file
35
vendor/ipl/html/src/Contract/DecorationResult.php
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
interface DecorationResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add the given HTML to the end of the result
|
||||||
|
*
|
||||||
|
* @param ValidHtml $html The HTML to add
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function append(ValidHtml $html): static;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend the given HTML to the beginning of the result
|
||||||
|
*
|
||||||
|
* @param ValidHtml $html The HTML to prepend
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function prepend(ValidHtml $html): static;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the given HTML as the container of the result
|
||||||
|
*
|
||||||
|
* @param MutableHtml $html The container
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function wrap(MutableHtml $html): static;
|
||||||
|
}
|
||||||
40
vendor/ipl/html/src/Contract/DecoratorOptions.php
vendored
Normal file
40
vendor/ipl/html/src/Contract/DecoratorOptions.php
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for decorators
|
||||||
|
*
|
||||||
|
* This trait is intended for use by the classes which implement {@see DecoratorOptionsInterface}.
|
||||||
|
*/
|
||||||
|
trait DecoratorOptions
|
||||||
|
{
|
||||||
|
/** @var ?Attributes Attributes of the decorator */
|
||||||
|
protected ?Attributes $attributes = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attributes
|
||||||
|
*
|
||||||
|
* @return Attributes
|
||||||
|
*/
|
||||||
|
public function getAttributes(): Attributes
|
||||||
|
{
|
||||||
|
if ($this->attributes === null) {
|
||||||
|
$this->attributes = new Attributes();
|
||||||
|
$this->registerAttributeCallbacks($this->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register attribute callbacks
|
||||||
|
*
|
||||||
|
* Override this method in order to register attribute callbacks in concrete classes.
|
||||||
|
*
|
||||||
|
* @param Attributes $attributes
|
||||||
|
*/
|
||||||
|
abstract protected function registerAttributeCallbacks(Attributes $attributes): void;
|
||||||
|
}
|
||||||
18
vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
vendored
Normal file
18
vendor/ipl/html/src/Contract/DecoratorOptionsInterface.php
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for decorators that provide options
|
||||||
|
*/
|
||||||
|
interface DecoratorOptionsInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the attributes (decorator options)
|
||||||
|
*
|
||||||
|
* @return Attributes
|
||||||
|
*/
|
||||||
|
public function getAttributes(): Attributes;
|
||||||
|
}
|
||||||
39
vendor/ipl/html/src/Contract/DefaultFormElementDecoration.php
vendored
Normal file
39
vendor/ipl/html/src/Contract/DefaultFormElementDecoration.php
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\FormDecoration\DecoratorChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for form elements that support default element decoration
|
||||||
|
*
|
||||||
|
* @phpstan-import-type decoratorsFormat from DecoratorChain
|
||||||
|
* @phpstan-type loaderPaths array<int, array{0: class-string, 1?: string}>
|
||||||
|
*/
|
||||||
|
interface DefaultFormElementDecoration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set the default element decorators.
|
||||||
|
*
|
||||||
|
* The default decorators will be applied to all elements that do not have explicit decorators.
|
||||||
|
* The order of the decorators is important, as it determines the rendering order.
|
||||||
|
*
|
||||||
|
* Please see {@see DecoratorChain::addDecorators()} for the supported array formats.
|
||||||
|
*
|
||||||
|
* @param decoratorsFormat $decorators
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDefaultElementDecorators(array $decorators): static;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom element decorator loader paths for the elements
|
||||||
|
*
|
||||||
|
* Each entry must be an array with index 0: class namespace, index 1: class name suffix (optional).
|
||||||
|
*
|
||||||
|
* @param loaderPaths $loaderPaths
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addElementDecoratorLoaderPaths(array $loaderPaths): static;
|
||||||
|
}
|
||||||
87
vendor/ipl/html/src/Contract/Form.php
vendored
Normal file
87
vendor/ipl/html/src/Contract/Form.php
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
interface Form extends EventEmitterInterface
|
||||||
|
{
|
||||||
|
/** @var string Event emitted when the form is associated with a request but is not sent */
|
||||||
|
public const ON_REQUEST = 'request';
|
||||||
|
|
||||||
|
/** @var string Event emitted when the form has been sent */
|
||||||
|
public const ON_SENT = 'sent';
|
||||||
|
|
||||||
|
/** @var string Event emitted when the form is validated */
|
||||||
|
public const ON_VALIDATE = 'validate';
|
||||||
|
|
||||||
|
/** @var string Event emitted when the form has been submitted */
|
||||||
|
public const ON_SUBMIT = 'success';
|
||||||
|
|
||||||
|
/** @var string Event emitted in case of an error */
|
||||||
|
public const ON_ERROR = 'error';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Form submission URL
|
||||||
|
*
|
||||||
|
* @return ?string
|
||||||
|
*/
|
||||||
|
public function getAction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTTP method the form accepts
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMethod();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the request associated with the form
|
||||||
|
*
|
||||||
|
* @return ?ServerRequestInterface
|
||||||
|
*/
|
||||||
|
public function getRequest();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the given request
|
||||||
|
*
|
||||||
|
* The following events will be emitted:
|
||||||
|
* - {@see self::ON_REQUEST} when the form is associated with a request but is not sent
|
||||||
|
* - {@see self::ON_SENT} when the form has been sent
|
||||||
|
* - {@see self::ON_SUBMIT} when the form has been submitted
|
||||||
|
* - {@see self::ON_ERROR} in case of an error
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function handleRequest(ServerRequestInterface $request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the form has been sent
|
||||||
|
*
|
||||||
|
* A form is considered sent if the request's method equals the form's method.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasBeenSent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the form has been submitted
|
||||||
|
*
|
||||||
|
* A form is submitted when it has been sent and a submit button, if set, has been pressed.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasBeenSubmitted();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the form is valid
|
||||||
|
*
|
||||||
|
* Emits the {@see self::ON_VALIDATE} event if the form has not been validated before.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid();
|
||||||
|
}
|
||||||
40
vendor/ipl/html/src/Contract/FormDecoration.php
vendored
Normal file
40
vendor/ipl/html/src/Contract/FormDecoration.php
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a form decorator
|
||||||
|
*/
|
||||||
|
interface FormDecoration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Decorate the given form
|
||||||
|
*
|
||||||
|
* A decorator can create HTML elements and apply attributes to the given form.
|
||||||
|
* Only the elements added to {@see DecorationResult} are rendered in the end.
|
||||||
|
*
|
||||||
|
* The element can be added to the {@see DecorationResult} using the following three methods:
|
||||||
|
* - {@see DecorationResult::append()} will add the element to the end of the result.
|
||||||
|
* - {@see DecorationResult::prepend()} will add the element to the beginning of the result.
|
||||||
|
* - {@see DecorationResult::wrap()} will wrap the result with the given element.
|
||||||
|
*
|
||||||
|
* **Reference implementation:**
|
||||||
|
*
|
||||||
|
*```
|
||||||
|
* public function decorateForm(DecorationResult $result, Form $form): void
|
||||||
|
* {
|
||||||
|
* if (! $form->hasChanges()) {
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* $result->prepend(new HtmlElement('p', null, Text::create('You have unsaved changes.')));
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param DecorationResult $result
|
||||||
|
* @param Form $form
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function decorateForm(DecorationResult $result, Form $form): void;
|
||||||
|
}
|
||||||
4
vendor/ipl/html/src/Contract/FormElement.php
vendored
4
vendor/ipl/html/src/Contract/FormElement.php
vendored
@ -7,6 +7,8 @@ use ipl\Html\Form;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of form elements
|
* Representation of form elements
|
||||||
|
*
|
||||||
|
* @phpstan-import-type AttributesType from Attributes
|
||||||
*/
|
*/
|
||||||
interface FormElement extends Wrappable
|
interface FormElement extends Wrappable
|
||||||
{
|
{
|
||||||
@ -20,7 +22,7 @@ interface FormElement extends Wrappable
|
|||||||
/**
|
/**
|
||||||
* Add attributes or options to the form element
|
* Add attributes or options to the form element
|
||||||
*
|
*
|
||||||
* @param iterable $attributes
|
* @param Attributes|AttributesType $attributes
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
|
|||||||
43
vendor/ipl/html/src/Contract/FormElementDecoration.php
vendored
Normal file
43
vendor/ipl/html/src/Contract/FormElementDecoration.php
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of form element decorator
|
||||||
|
*/
|
||||||
|
interface FormElementDecoration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Decorate the given form element
|
||||||
|
*
|
||||||
|
* A decorator can create HTML elements and apply attributes to the given $formElement element.
|
||||||
|
* Only the elements added to {@see DecorationResult} are rendered in the end.
|
||||||
|
*
|
||||||
|
* The element can be added to the {@see DecorationResult} using the following three methods:
|
||||||
|
* - {@see DecorationResult::append()} will add the given HTML to the end of the result
|
||||||
|
* - {@see DecorationResult::prepend()} will prepend the given HTML to the beginning of the result
|
||||||
|
* - {@see DecorationResult::wrap()} will set the given HTML as the container of the result
|
||||||
|
*
|
||||||
|
* **Reference implementation:**
|
||||||
|
*
|
||||||
|
*```
|
||||||
|
*
|
||||||
|
* public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
* {
|
||||||
|
* $description = $formElement->getDescription();
|
||||||
|
*
|
||||||
|
* if ($description === null) {
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* $result->append(new HtmlElement('p', null, new Text($description)));
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param DecorationResult $result
|
||||||
|
* @param FormElement $formElement
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void;
|
||||||
|
}
|
||||||
@ -6,6 +6,8 @@ use ipl\Html\ValidHtml;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of form element decorators
|
* Representation of form element decorators
|
||||||
|
*
|
||||||
|
* @deprecated Use {@see FormElementDecoration} instead
|
||||||
*/
|
*/
|
||||||
interface FormElementDecorator extends ValidHtml
|
interface FormElementDecorator extends ValidHtml
|
||||||
{
|
{
|
||||||
|
|||||||
103
vendor/ipl/html/src/Contract/FormElements.php
vendored
Normal file
103
vendor/ipl/html/src/Contract/FormElements.php
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
interface FormElements extends EventEmitterInterface
|
||||||
|
{
|
||||||
|
/** @var string Event emitted when an element is registered */
|
||||||
|
public const ON_ELEMENT_REGISTERED = 'elementRegistered';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all elements
|
||||||
|
*
|
||||||
|
* @return FormElement[]
|
||||||
|
*/
|
||||||
|
public function getElements();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the given element exists
|
||||||
|
*
|
||||||
|
* @param string|FormElement $element
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasElement(string|FormElement $element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the element by the given name
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return FormElement
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If no element with the given name exists
|
||||||
|
*/
|
||||||
|
public function getElement(string $name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an element
|
||||||
|
*
|
||||||
|
* @param string|FormElement $typeOrElement Type of the element as string or an instance of FormElement
|
||||||
|
* @param null|string $name Name of the element
|
||||||
|
* @param null|array<string, mixed> $options Element options as key-value pairs
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the element is invalid (e.g., wrong type, no name)
|
||||||
|
*/
|
||||||
|
public function addElement(string|FormElement $typeOrElement, ?string $name = null, ?array $options = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an element
|
||||||
|
*
|
||||||
|
* Registers the element for value and validation handling but does not add it to the render stack.
|
||||||
|
* Emits event {@see self::ON_ELEMENT_REGISTERED} with the element as parameter.
|
||||||
|
*
|
||||||
|
* @param FormElement $element
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If $element does not provide a name
|
||||||
|
*/
|
||||||
|
public function registerElement(FormElement $element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an element
|
||||||
|
*
|
||||||
|
* @param string|FormElement $element
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function removeElement(string|FormElement $element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the element specified by name
|
||||||
|
*
|
||||||
|
* Returns $default if the element does not exist or has no value.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param mixed $default
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getValue(string $name, mixed $default = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the values for all but ignored elements
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> Values as name-value pairs
|
||||||
|
*/
|
||||||
|
public function getValues();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate values of registered elements
|
||||||
|
*
|
||||||
|
* @param iterable<string, mixed> $values Values as name-value pairs
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function populate(iterable $values);
|
||||||
|
}
|
||||||
90
vendor/ipl/html/src/Contract/HtmlElementInterface.php
vendored
Normal file
90
vendor/ipl/html/src/Contract/HtmlElementInterface.php
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use ipl\Html\Attribute;
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a html element
|
||||||
|
*
|
||||||
|
* @phpstan-import-type AttributeValue from Attribute
|
||||||
|
* @phpstan-import-type AttributesType from Attributes
|
||||||
|
*/
|
||||||
|
interface HtmlElementInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the HTML tag of the element
|
||||||
|
*
|
||||||
|
* @return non-empty-string
|
||||||
|
*/
|
||||||
|
public function getTag();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attributes of the element
|
||||||
|
*
|
||||||
|
* @return Attributes
|
||||||
|
*/
|
||||||
|
public function getAttributes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given attributes to the element
|
||||||
|
*
|
||||||
|
* @param Attributes|AttributesType $attributes
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addAttributes($attributes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the attribute with the given name exists, false otherwise
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasAttribute(string $name): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attribute with the given name
|
||||||
|
*
|
||||||
|
* If the attribute does not already exist, an empty one is automatically created and added to the attributes.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return Attribute
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the attribute does not yet exist and its name contains special characters
|
||||||
|
*/
|
||||||
|
public function getAttribute(string $name): Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute with the given name and value
|
||||||
|
*
|
||||||
|
* If the attribute with the given name already exists, it gets overridden.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the attribute
|
||||||
|
* @param AttributeValue $value The value of the attribute
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAttribute($name, $value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the attribute with the given name or remove the given value from the attribute
|
||||||
|
*
|
||||||
|
* @param string $name The name of the attribute
|
||||||
|
* @param AttributeValue $value The value to remove if specified
|
||||||
|
*
|
||||||
|
* @return ?Attribute The removed or changed attribute, if any, otherwise null
|
||||||
|
*/
|
||||||
|
public function removeAttribute(string $name, $value = null): ?Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the element is void
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isVoid();
|
||||||
|
}
|
||||||
90
vendor/ipl/html/src/Contract/MutableHtml.php
vendored
Normal file
90
vendor/ipl/html/src/Contract/MutableHtml.php
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\Contract;
|
||||||
|
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
interface MutableHtml extends ValidHtml
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add content
|
||||||
|
*
|
||||||
|
* @param ValidHtml ...$content
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addHtml(ValidHtml ...$content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend content
|
||||||
|
*
|
||||||
|
* @param ValidHtml ...$content
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function prependHtml(ValidHtml ...$content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set content
|
||||||
|
*
|
||||||
|
* @param ValidHtml ...$content
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setHtmlContent(ValidHtml ...$content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert Html after an existing Html node
|
||||||
|
*
|
||||||
|
* @param ValidHtml $newNode
|
||||||
|
* @param ValidHtml $existingNode
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function insertAfter(ValidHtml $newNode, ValidHtml $existingNode): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert Html before an existing Html node
|
||||||
|
*
|
||||||
|
* @param ValidHtml $newNode
|
||||||
|
* @param ValidHtml $existingNode
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function insertBefore(ValidHtml $newNode, ValidHtml $existingNode): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove content
|
||||||
|
*
|
||||||
|
* @param ValidHtml $content
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function remove(ValidHtml $content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the content
|
||||||
|
*
|
||||||
|
* @return ValidHtml[]
|
||||||
|
*/
|
||||||
|
public function getContent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the given content is a direct or indirect child of this Html
|
||||||
|
*
|
||||||
|
* A direct child is one that is part of this Html element's content. An indirect child
|
||||||
|
* is one that is part of a direct child's content (recursively).
|
||||||
|
*
|
||||||
|
* @param ValidHtml $content
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function contains(ValidHtml $content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether there is any content
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEmpty();
|
||||||
|
}
|
||||||
143
vendor/ipl/html/src/Form.php
vendored
143
vendor/ipl/html/src/Form.php
vendored
@ -2,26 +2,28 @@
|
|||||||
|
|
||||||
namespace ipl\Html;
|
namespace ipl\Html;
|
||||||
|
|
||||||
|
use ipl\Html\Contract\DefaultFormElementDecoration;
|
||||||
|
use ipl\Html\Contract\FormDecoration;
|
||||||
use ipl\Html\Contract\FormElement;
|
use ipl\Html\Contract\FormElement;
|
||||||
use ipl\Html\Contract\FormSubmitElement;
|
use ipl\Html\Contract\FormSubmitElement;
|
||||||
|
use ipl\Html\Contract\MutableHtml;
|
||||||
|
use ipl\Html\FormDecoration\DecoratorChain;
|
||||||
|
use ipl\Html\FormDecoration\FormDecorationResult;
|
||||||
use ipl\Html\FormElement\FormElements;
|
use ipl\Html\FormElement\FormElements;
|
||||||
use ipl\Stdlib\Messages;
|
use ipl\Stdlib\Messages;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Form extends BaseHtmlElement
|
class Form extends BaseHtmlElement implements Contract\Form, Contract\FormElements, DefaultFormElementDecoration
|
||||||
{
|
{
|
||||||
use FormElements {
|
use FormElements {
|
||||||
FormElements::remove as private removeElement;
|
FormElements::remove as private baseRemove;
|
||||||
|
FormElements::beforeRender as private baseBeforeRender;
|
||||||
}
|
}
|
||||||
use Messages;
|
use Messages;
|
||||||
|
|
||||||
public const ON_ELEMENT_REGISTERED = 'elementRegistered';
|
/** @deprecated Use {@see Contract\Form::ON_SUBMIT} instead */
|
||||||
public const ON_ERROR = 'error';
|
|
||||||
public const ON_REQUEST = 'request';
|
|
||||||
public const ON_SUCCESS = 'success';
|
public const ON_SUCCESS = 'success';
|
||||||
public const ON_SENT = 'sent';
|
|
||||||
public const ON_VALIDATE = 'validate';
|
|
||||||
|
|
||||||
/** @var string Form submission URL */
|
/** @var string Form submission URL */
|
||||||
protected $action;
|
protected $action;
|
||||||
@ -44,6 +46,12 @@ class Form extends BaseHtmlElement
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
protected $redirectUrl;
|
protected $redirectUrl;
|
||||||
|
|
||||||
|
/** @var ?DecoratorChain<FormDecoration> */
|
||||||
|
protected ?DecoratorChain $decorators = null;
|
||||||
|
|
||||||
|
/** @var bool Whether the form has been decorated */
|
||||||
|
protected bool $decorated = false;
|
||||||
|
|
||||||
protected $tag = 'form';
|
protected $tag = 'form';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,10 +67,39 @@ class Form extends BaseHtmlElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Form submission URL
|
* Escape reserved chars in the given string
|
||||||
*
|
*
|
||||||
* @return string|null
|
* The characters '.', ' ' and optionally brackets are converted to unused control characters
|
||||||
|
* File Separator: ␜, Group Separator: ␝, Record Separator: ␝, and Unit Separator: ␟ respectively.
|
||||||
|
*
|
||||||
|
* This is done because:
|
||||||
|
* PHP converts dots and spaces in form element names to underscores by default in the request data.
|
||||||
|
* For example, <input name="a.b" /> becomes $_REQUEST["a_b"].
|
||||||
|
*
|
||||||
|
* And if an external variable name begins with a valid array syntax, trailing characters are silently ignored.
|
||||||
|
* For example, <input name="foo[bar]baz"> becomes $_REQUEST['foo']['bar'].
|
||||||
|
* See https://www.php.net/manual/en/language.variables.external.php
|
||||||
|
*
|
||||||
|
* @param string $string The string to escape
|
||||||
|
* @param bool $escapeBrackets Whether to escape brackets
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
public static function escapeReservedChars(string $string, bool $escapeBrackets = true): string
|
||||||
|
{
|
||||||
|
$escapeMap = [
|
||||||
|
'.' => chr(28), // File Separator
|
||||||
|
' ' => chr(29) // Group Separator
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($escapeBrackets) {
|
||||||
|
$escapeMap['['] = chr(30); // Record Separator
|
||||||
|
$escapeMap[']'] = chr(31); // Unit Separator
|
||||||
|
}
|
||||||
|
|
||||||
|
return strtr($string, $escapeMap);
|
||||||
|
}
|
||||||
|
|
||||||
public function getAction()
|
public function getAction()
|
||||||
{
|
{
|
||||||
return $this->action;
|
return $this->action;
|
||||||
@ -82,11 +119,6 @@ class Form extends BaseHtmlElement
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the HTTP method to submit the form with
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMethod()
|
public function getMethod()
|
||||||
{
|
{
|
||||||
return $this->method;
|
return $this->method;
|
||||||
@ -156,9 +188,6 @@ class Form extends BaseHtmlElement
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ServerRequestInterface|null
|
|
||||||
*/
|
|
||||||
public function getRequest()
|
public function getRequest()
|
||||||
{
|
{
|
||||||
return $this->request;
|
return $this->request;
|
||||||
@ -167,7 +196,6 @@ class Form extends BaseHtmlElement
|
|||||||
public function setRequest($request)
|
public function setRequest($request)
|
||||||
{
|
{
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
$this->emit(Form::ON_REQUEST, [$request]);
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -197,15 +225,26 @@ class Form extends BaseHtmlElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ServerRequestInterface $request
|
* Get the decorators of this form
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return DecoratorChain<FormDecoration>
|
||||||
*/
|
*/
|
||||||
|
public function getDecorators(): DecoratorChain
|
||||||
|
{
|
||||||
|
if ($this->decorators === null) {
|
||||||
|
$this->decorators = new DecoratorChain(FormDecoration::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->decorators;
|
||||||
|
}
|
||||||
|
|
||||||
public function handleRequest(ServerRequestInterface $request)
|
public function handleRequest(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$this->setRequest($request);
|
$this->setRequest($request);
|
||||||
|
|
||||||
if (! $this->hasBeenSent()) {
|
if (! $this->hasBeenSent()) {
|
||||||
|
$this->emit(Contract\Form::ON_REQUEST, [$request, $this]);
|
||||||
|
|
||||||
// Always assemble
|
// Always assemble
|
||||||
$this->ensureAssembled();
|
$this->ensureAssembled();
|
||||||
|
|
||||||
@ -234,32 +273,25 @@ class Form extends BaseHtmlElement
|
|||||||
if ($this->hasBeenSubmitted()) {
|
if ($this->hasBeenSubmitted()) {
|
||||||
if ($this->isValid()) {
|
if ($this->isValid()) {
|
||||||
try {
|
try {
|
||||||
$this->emit(Form::ON_SENT, [$this]);
|
$this->emit(Contract\Form::ON_SENT, [$this]);
|
||||||
$this->onSuccess();
|
$this->onSuccess();
|
||||||
$this->emitOnce(Form::ON_SUCCESS, [$this]);
|
$this->emitOnce(Contract\Form::ON_SUBMIT, [$this]);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$this->addMessage($e);
|
$this->addMessage($e);
|
||||||
$this->onError();
|
$this->onError();
|
||||||
$this->emit(Form::ON_ERROR, [$e, $this]);
|
$this->emit(Contract\Form::ON_ERROR, [$e, $this]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->onError();
|
$this->onError();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->validatePartial();
|
$this->validatePartial();
|
||||||
$this->emit(Form::ON_SENT, [$this]);
|
$this->emit(Contract\Form::ON_SENT, [$this]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether the form has been sent
|
|
||||||
*
|
|
||||||
* A form is considered sent if the request's method equals the form's method.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasBeenSent()
|
public function hasBeenSent()
|
||||||
{
|
{
|
||||||
if ($this->request === null) {
|
if ($this->request === null) {
|
||||||
@ -269,14 +301,6 @@ class Form extends BaseHtmlElement
|
|||||||
return $this->request->getMethod() === $this->getMethod();
|
return $this->request->getMethod() === $this->getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether the form has been submitted
|
|
||||||
*
|
|
||||||
* A form is submitted when it has been sent and when the primary submit button, if set, has been pressed.
|
|
||||||
* This method calls {@link hasBeenSent()} in order to detect whether the form has been sent.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasBeenSubmitted()
|
public function hasBeenSubmitted()
|
||||||
{
|
{
|
||||||
if (! $this->hasBeenSent()) {
|
if (! $this->hasBeenSent()) {
|
||||||
@ -290,19 +314,12 @@ class Form extends BaseHtmlElement
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether the form is valid
|
|
||||||
*
|
|
||||||
* {@link validate()} is called automatically if the form has not been validated before.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid()
|
public function isValid()
|
||||||
{
|
{
|
||||||
if ($this->isValid === null) {
|
if ($this->isValid === null) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
$this->emit(self::ON_VALIDATE, [$this]);
|
$this->emit(Contract\Form::ON_VALIDATE, [$this]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->isValid;
|
return $this->isValid;
|
||||||
@ -348,17 +365,36 @@ class Form extends BaseHtmlElement
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remove(ValidHtml $elementOrHtml)
|
public function remove(ValidHtml $content)
|
||||||
{
|
{
|
||||||
if ($this->submitButton === $elementOrHtml) {
|
if ($this->submitButton === $content) {
|
||||||
$this->submitButton = null;
|
$this->submitButton = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->removeElement($elementOrHtml);
|
$this->baseRemove($content);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the form decoration
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function applyDecoration(): void
|
||||||
|
{
|
||||||
|
if ($this->decorated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = new FormDecorationResult($this);
|
||||||
|
foreach ($this->getDecorators() as $decorator) {
|
||||||
|
$decorator->decorateForm($result, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decorated = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected function onError()
|
protected function onError()
|
||||||
{
|
{
|
||||||
$errors = Html::tag('ul', ['class' => 'errors']);
|
$errors = Html::tag('ul', ['class' => 'errors']);
|
||||||
@ -399,4 +435,11 @@ class Form extends BaseHtmlElement
|
|||||||
->registerAttributeCallback('action', [$this, 'getAction'], [$this, 'setAction'])
|
->registerAttributeCallback('action', [$this, 'getAction'], [$this, 'setAction'])
|
||||||
->registerAttributeCallback('method', [$this, 'getMethod'], [$this, 'setMethod']);
|
->registerAttributeCallback('method', [$this, 'getMethod'], [$this, 'setMethod']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function beforeRender(): void
|
||||||
|
{
|
||||||
|
$this->baseBeforeRender();
|
||||||
|
|
||||||
|
$this->applyDecoration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
297
vendor/ipl/html/src/FormDecoration/DecoratorChain.php
vendored
Normal file
297
vendor/ipl/html/src/FormDecoration/DecoratorChain.php
vendored
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use Generator;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use ipl\Html\Contract\DecoratorOptionsInterface;
|
||||||
|
use ipl\Stdlib\Plugins;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
use function ipl\Stdlib\get_php_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DecoratorChain for form elements
|
||||||
|
*
|
||||||
|
* @template TDecorator of object
|
||||||
|
* @implements IteratorAggregate<int, TDecorator>
|
||||||
|
*
|
||||||
|
* @phpstan-type Ident string|class-string
|
||||||
|
* @phpstan-type decoratorOptionsFormat array<string, mixed>
|
||||||
|
* @phpstan-type _decoratorsFormat1 array<Ident, decoratorOptionsFormat>
|
||||||
|
* @phpstan-type _decoratorsFormat2 array<int, Ident|TDecorator|array{name: Ident, options?: decoratorOptionsFormat}>
|
||||||
|
* @phpstan-type decoratorsFormat _decoratorsFormat1 | _decoratorsFormat2
|
||||||
|
*/
|
||||||
|
class DecoratorChain implements IteratorAggregate
|
||||||
|
{
|
||||||
|
use Plugins;
|
||||||
|
|
||||||
|
/** @var class-string<TDecorator> The type of decorator to accept */
|
||||||
|
private string $decoratorType;
|
||||||
|
|
||||||
|
/** @var TDecorator[] All registered decorators */
|
||||||
|
private array $decorators = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new decorator chain
|
||||||
|
*
|
||||||
|
* @param class-string<TDecorator> $decoratorType The type of decorator to accept
|
||||||
|
*/
|
||||||
|
public function __construct(string $decoratorType)
|
||||||
|
{
|
||||||
|
$this->decoratorType = $decoratorType;
|
||||||
|
|
||||||
|
$this->addDefaultPluginLoader('decorator', __NAMESPACE__, 'Decorator');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a decorator loader
|
||||||
|
*
|
||||||
|
* @param string $namespace Namespace of the decorator(s)
|
||||||
|
* @param string $suffix Decorator class name suffix, if any
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addDecoratorLoader(string $namespace, string $suffix = ''): static
|
||||||
|
{
|
||||||
|
$this->addPluginLoader('decorator', $namespace, $suffix);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a decorator to the chain.
|
||||||
|
*
|
||||||
|
* @param TDecorator|Ident $decorator
|
||||||
|
* @param decoratorOptionsFormat $options Only allowed if parameter 1 is a string
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the decorator specification is invalid
|
||||||
|
*/
|
||||||
|
public function addDecorator(object|string $decorator, array $options = []): static
|
||||||
|
{
|
||||||
|
if (! empty($options) && ! is_string($decorator)) {
|
||||||
|
throw new InvalidArgumentException('No options are allowed with parameter 1 of type Decorator');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($decorator)) {
|
||||||
|
$decorator = $this->createDecorator($decorator, $options);
|
||||||
|
} elseif (! $decorator instanceof $this->decoratorType) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
'Expects parameter 1 to be a string or an instance of %s, got %s instead',
|
||||||
|
$this->decoratorType,
|
||||||
|
get_php_type($decorator)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decorators[] = $decorator;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the decorators from the given decorator specification to the chain
|
||||||
|
*
|
||||||
|
* The order of the decorators is important, as it determines the rendering order.
|
||||||
|
*
|
||||||
|
* *The following array formats are supported:*
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* // When no options are required or defaults are sufficient
|
||||||
|
* $decorators = [
|
||||||
|
* 'HtmlTag',
|
||||||
|
* 'Label'
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* // Override default options by defining the option key and value
|
||||||
|
*
|
||||||
|
* // key: decorator name, value: options
|
||||||
|
* $decorators = [
|
||||||
|
* 'HtmlTag' => ['tag' => 'span', 'placement' => 'append'],
|
||||||
|
* 'Label' => ['class' => 'element-label']
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* // or define the `name` and `options` key
|
||||||
|
* $decorators = [
|
||||||
|
* ['name' => 'HtmlTag', 'options' => ['tag' => 'span', 'placement' => 'append']],
|
||||||
|
* ['name' => 'Label', 'options' => ['class' => 'element-label']]
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* // or add Decorator instances
|
||||||
|
* $decorators = [
|
||||||
|
* (new HtmlTagDecorator())->getAttributes()->add(['tag' => 'span', 'placement' => 'append']),
|
||||||
|
* (new LabelDecorator())->getAttributes()->add(['class' => 'element-label'])
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* // Class paths are also supported
|
||||||
|
* $decorators = [
|
||||||
|
* LabelDecorator::class,
|
||||||
|
* ['name' => HtmlTagDecorator::class, ['tag' => 'span', 'placement' => 'append']]
|
||||||
|
* ];
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param static<TDecorator>|decoratorsFormat $decorators
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the decorator specification is invalid
|
||||||
|
*/
|
||||||
|
public function addDecorators(DecoratorChain|array $decorators): static
|
||||||
|
{
|
||||||
|
if ($decorators instanceof static) {
|
||||||
|
foreach ($decorators->decorators as $decorator) {
|
||||||
|
$this->addDecorator($decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($decorators as $decoratorName => $decoratorOptions) {
|
||||||
|
$position = $decoratorName;
|
||||||
|
if (is_int($decoratorName)) {
|
||||||
|
if (is_array($decoratorOptions)) {
|
||||||
|
if (! isset($decoratorOptions['name'])) {
|
||||||
|
throw new InvalidArgumentException("Key 'name' is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoratorName = $decoratorOptions['name'];
|
||||||
|
unset($decoratorOptions['name']);
|
||||||
|
|
||||||
|
$options = [];
|
||||||
|
if (isset($decoratorOptions['options'])) {
|
||||||
|
$options = $decoratorOptions['options'];
|
||||||
|
|
||||||
|
unset($decoratorOptions['options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($decoratorOptions)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
sprintf(
|
||||||
|
"No other keys except 'name' and 'options' are allowed, got '%s'",
|
||||||
|
implode("', '", array_keys($decoratorOptions))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoratorOptions = $options;
|
||||||
|
} else {
|
||||||
|
$decoratorName = $decoratorOptions;
|
||||||
|
$decoratorOptions = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_array($decoratorOptions)) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
"The key must be a decorator name and value must be an array of options, got value of type"
|
||||||
|
. " '%s' for key '%s'",
|
||||||
|
get_php_type($decoratorOptions),
|
||||||
|
$decoratorName,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_string($decoratorName) && ! $decoratorName instanceof $this->decoratorType) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
'Expects array value at position %d to be a string or an instance of %s, got %s instead',
|
||||||
|
$position,
|
||||||
|
$this->decoratorType,
|
||||||
|
get_php_type($decoratorName)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addDecorator($decoratorName, $decoratorOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all decorators from the chain
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function clearDecorators(): static
|
||||||
|
{
|
||||||
|
$this->decorators = [];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a decorator from the given name and options
|
||||||
|
*
|
||||||
|
* @param Ident $name
|
||||||
|
* @param decoratorOptionsFormat $options
|
||||||
|
*
|
||||||
|
* @return TDecorator
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the given decorator is unknown or not an instance of the expected type
|
||||||
|
* @throws UnexpectedValueException If the loaded decorator is not an instance of the expected type
|
||||||
|
*/
|
||||||
|
protected function createDecorator(string $name, array $options = []): object
|
||||||
|
{
|
||||||
|
if (class_exists($name)) {
|
||||||
|
$decorator = new $name();
|
||||||
|
if (! $decorator instanceof $this->decoratorType) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
"Invalid decorator class '%s'. decorator must be an instance of %s",
|
||||||
|
$name,
|
||||||
|
$this->decoratorType,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$class = $this->loadPlugin('decorator', $name);
|
||||||
|
if (! $class) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
"Can't load decorator '%s'. decorator unknown",
|
||||||
|
$name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$decorator = new $class();
|
||||||
|
if (! $decorator instanceof $this->decoratorType) {
|
||||||
|
throw new UnexpectedValueException(sprintf(
|
||||||
|
"%s expects loader to return an instance of %s for decorator '%s', got %s instead",
|
||||||
|
__METHOD__,
|
||||||
|
$this->decoratorType,
|
||||||
|
$name,
|
||||||
|
get_php_type($decorator)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($options)) {
|
||||||
|
if (! $decorator instanceof DecoratorOptionsInterface) {
|
||||||
|
throw new InvalidArgumentException(sprintf("Decorator '%s' does not support options", $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
$decorator->getAttributes()->add($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $decorator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the chain has decorators
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasDecorators(): bool
|
||||||
|
{
|
||||||
|
return ! empty($this->decorators);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over all decorators
|
||||||
|
*
|
||||||
|
* @return Generator<TDecorator>
|
||||||
|
*/
|
||||||
|
#[\Override]
|
||||||
|
public function getIterator(): Generator
|
||||||
|
{
|
||||||
|
foreach ($this->decorators as $decorator) {
|
||||||
|
yield $decorator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
vendored
Normal file
100
vendor/ipl/html/src/FormDecoration/DescriptionDecorator.php
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\DecoratorOptions;
|
||||||
|
use ipl\Html\Contract\DecoratorOptionsInterface;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
use ipl\Html\Contract\HtmlElementInterface;
|
||||||
|
use ipl\Html\FormElement\RadioElement;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the description of the form element
|
||||||
|
*/
|
||||||
|
class DescriptionDecorator implements FormElementDecoration, DecoratorOptionsInterface
|
||||||
|
{
|
||||||
|
use DecoratorOptions;
|
||||||
|
|
||||||
|
/** @var string|string[] CSS classes to apply */
|
||||||
|
protected string|array $class = 'form-element-description';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the css class(es)
|
||||||
|
*
|
||||||
|
* @return string|string[]
|
||||||
|
*/
|
||||||
|
public function getClass(): string|array
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the css class(es)
|
||||||
|
*
|
||||||
|
* @param string|string[] $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setClass(string|array $class): static
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$isHtmlElement = $formElement instanceof HtmlElementInterface;
|
||||||
|
|
||||||
|
if ($formElement->getDescription() === null || ($isHtmlElement && $formElement->getTag() === 'fieldset')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$elementDescription = $this->getElementDescription($formElement);
|
||||||
|
if ($isHtmlElement) {
|
||||||
|
if ($formElement->getAttributes()->has('id')) {
|
||||||
|
$elementId = $formElement->getAttributes()->get('id')->getValue();
|
||||||
|
} else {
|
||||||
|
$elementId = uniqid('form-element-');
|
||||||
|
|
||||||
|
// RadioElement applies all its attributes to each of its options, so we cannot set a fallback
|
||||||
|
// id attribute here.
|
||||||
|
if (! $formElement instanceof RadioElement) {
|
||||||
|
$formElement->getAttributes()->set('id', $elementId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$descriptionId = 'desc_' . $elementId;
|
||||||
|
$formElement->getAttributes()->set('aria-describedby', $descriptionId);
|
||||||
|
|
||||||
|
$elementDescription->getAttributes()->set('id', $descriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$elementDescription->getAttributes()->add('class', $this->getClass());
|
||||||
|
|
||||||
|
$result->append($elementDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the element description as HTML
|
||||||
|
*
|
||||||
|
* @param FormElement $formElement
|
||||||
|
*
|
||||||
|
* @return HtmlElementInterface & ValidHtml
|
||||||
|
*/
|
||||||
|
protected function getElementDescription(FormElement $formElement): HtmlElementInterface & ValidHtml
|
||||||
|
{
|
||||||
|
return new HtmlElement('p', content: new Text($formElement->getDescription()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerAttributeCallbacks(Attributes $attributes): void
|
||||||
|
{
|
||||||
|
$attributes->registerAttributeCallback('class', null, $this->setClass(...));
|
||||||
|
}
|
||||||
|
}
|
||||||
64
vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
vendored
Normal file
64
vendor/ipl/html/src/FormDecoration/ErrorsDecorator.php
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\DecoratorOptions;
|
||||||
|
use ipl\Html\Contract\DecoratorOptionsInterface;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the errors messages of the form element
|
||||||
|
*/
|
||||||
|
class ErrorsDecorator implements FormElementDecoration, DecoratorOptionsInterface
|
||||||
|
{
|
||||||
|
use DecoratorOptions;
|
||||||
|
|
||||||
|
/** @var string|string[] CSS classes to apply */
|
||||||
|
protected string|array $class = 'form-element-errors';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the css class(es)
|
||||||
|
*
|
||||||
|
* @return string|string[]
|
||||||
|
*/
|
||||||
|
public function getClass(): string|array
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the css class(es)
|
||||||
|
*
|
||||||
|
* @param string|string[] $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setClass(string|array $class): static
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$errors = new HtmlElement('ul', new Attributes(['class' => $this->getClass()]));
|
||||||
|
foreach ($formElement->getMessages() as $message) {
|
||||||
|
$errors->addHtml(new HtmlElement('li', null, Text::create($message)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $errors->isEmpty()) {
|
||||||
|
$result->append($errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerAttributeCallbacks(Attributes $attributes): void
|
||||||
|
{
|
||||||
|
$attributes->registerAttributeCallback('class', null, $this->setClass(...));
|
||||||
|
}
|
||||||
|
}
|
||||||
43
vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
vendored
Normal file
43
vendor/ipl/html/src/FormDecoration/FieldsetDecorator.php
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
use ipl\Html\Contract\HtmlElementInterface;
|
||||||
|
use ipl\Html\Contract\MutableHtml;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the fieldset of the form element
|
||||||
|
*/
|
||||||
|
class FieldsetDecorator implements FormElementDecoration
|
||||||
|
{
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$isHtmlElement = $formElement instanceof HtmlElementInterface;
|
||||||
|
if (! $formElement instanceof MutableHtml || ! $isHtmlElement || $formElement->getTag() !== 'fieldset') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$description = $formElement->getDescription();
|
||||||
|
if ($description !== null) {
|
||||||
|
$attributes = null;
|
||||||
|
if ($formElement->getAttributes()->has('id')) {
|
||||||
|
$descriptionId = 'desc_' . $formElement->getAttributes()->get('id')->getValue();
|
||||||
|
$formElement->getAttributes()->set('aria-describedby', $descriptionId);
|
||||||
|
$attributes = new Attributes(['id' => $descriptionId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$formElement->prependHtml(new HtmlElement('p', $attributes, new Text($description)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$label = $formElement->getLabel();
|
||||||
|
if ($label !== null) {
|
||||||
|
$formElement->prependHtml(new HtmlElement('legend', null, Text::create($label)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
vendored
Normal file
54
vendor/ipl/html/src/FormDecoration/FormDecorationResult.php
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\MutableHtml;
|
||||||
|
use ipl\Html\Contract\Wrappable;
|
||||||
|
use ipl\Html\Form;
|
||||||
|
use ipl\Html\HtmlDocument;
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
class FormDecorationResult implements DecorationResult
|
||||||
|
{
|
||||||
|
/** @var MutableHtml & Wrappable The current content */
|
||||||
|
private MutableHtml & Wrappable $content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new FormDecorationResult
|
||||||
|
*
|
||||||
|
* @param Form $form
|
||||||
|
*/
|
||||||
|
public function __construct(Form $form)
|
||||||
|
{
|
||||||
|
$this->content = $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function append(ValidHtml $html): static
|
||||||
|
{
|
||||||
|
$this->content->addHtml($html);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepend(ValidHtml $html): static
|
||||||
|
{
|
||||||
|
$this->content->prependHtml($html);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wrap(MutableHtml $html): static
|
||||||
|
{
|
||||||
|
if (! $html instanceof Wrappable) {
|
||||||
|
// If it's not a wrappable, mimic what wrapping usually means
|
||||||
|
$html = (new HtmlDocument())->addHtml($html);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->content->addWrapper($html);
|
||||||
|
$html->addHtml($this->content);
|
||||||
|
$this->content = $html;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
vendored
Normal file
96
vendor/ipl/html/src/FormDecoration/FormElementDecorationResult.php
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\MutableHtml;
|
||||||
|
use ipl\Html\HtmlDocument;
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores and renders the results of decorators
|
||||||
|
*
|
||||||
|
* @phpstan-type content array<int, ValidHtml|array<int, mixed>>
|
||||||
|
*/
|
||||||
|
class FormElementDecorationResult implements DecorationResult
|
||||||
|
{
|
||||||
|
/** @var content The HTML content */
|
||||||
|
protected array $content = [];
|
||||||
|
|
||||||
|
public function append(ValidHtml $html): static
|
||||||
|
{
|
||||||
|
$this->content[] = $html;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepend(ValidHtml $html): static
|
||||||
|
{
|
||||||
|
array_unshift($this->content, $html);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wrap(MutableHtml $html): static
|
||||||
|
{
|
||||||
|
$this->content = [[$html, $this->content]];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble the results
|
||||||
|
*
|
||||||
|
* @return HtmlDocument
|
||||||
|
*/
|
||||||
|
public function assemble(): HtmlDocument
|
||||||
|
{
|
||||||
|
$content = new HtmlDocument();
|
||||||
|
|
||||||
|
if (empty($this->content)) {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resolveContent($content, $this->content);
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve content
|
||||||
|
*
|
||||||
|
* @param MutableHtml $parent The parent element
|
||||||
|
* @param content $content The content to be added
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function resolveContent(MutableHtml $parent, array $content): void
|
||||||
|
{
|
||||||
|
foreach ($content as $item) {
|
||||||
|
if (is_array($item)) {
|
||||||
|
$item = $this->resolveWrappedContent($item[0], $item[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent->addHtml($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve wrapped content
|
||||||
|
*
|
||||||
|
* @param MutableHtml $parent The parent element
|
||||||
|
* @param ValidHtml|content $item The content to be added
|
||||||
|
*
|
||||||
|
* @return ValidHtml The resolved parent element with content added
|
||||||
|
*/
|
||||||
|
protected function resolveWrappedContent(MutableHtml $parent, ValidHtml|array $item): ValidHtml
|
||||||
|
{
|
||||||
|
if ($item instanceof ValidHtml) {
|
||||||
|
$parent->addHtml($item);
|
||||||
|
} else {
|
||||||
|
$this->resolveContent($parent, $item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
217
vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
vendored
Normal file
217
vendor/ipl/html/src/FormDecoration/HtmlTagDecorator.php
vendored
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\DecoratorOptions;
|
||||||
|
use ipl\Html\Contract\DecoratorOptionsInterface;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use RuntimeException;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
use function ipl\Stdlib\get_php_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the form element with an HTML tag
|
||||||
|
*/
|
||||||
|
class HtmlTagDecorator implements FormElementDecoration, DecoratorOptionsInterface
|
||||||
|
{
|
||||||
|
use DecoratorOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes how the HTML tag should transform the content. Default: {@see Transformation::Wrap}
|
||||||
|
*
|
||||||
|
* @var Transformation
|
||||||
|
*/
|
||||||
|
protected Transformation $transformation = Transformation::Wrap;
|
||||||
|
|
||||||
|
/** @var string HTML tag to use for the decoration. */
|
||||||
|
protected string $tag;
|
||||||
|
|
||||||
|
/** @var ?callable(FormElement): bool Callable to decide whether to decorate the element */
|
||||||
|
protected $condition;
|
||||||
|
|
||||||
|
/** @var ?(string|string[]) CSS classes to apply */
|
||||||
|
protected null|string|array $class = null;
|
||||||
|
|
||||||
|
/** @var array<string, mixed> Attributes to apply */
|
||||||
|
protected array $attrs = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTML tag to use for the decoration
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws RuntimeException if the tag is not set
|
||||||
|
*/
|
||||||
|
public function getTag(): string
|
||||||
|
{
|
||||||
|
if (empty($this->tag)) {
|
||||||
|
throw new RuntimeException('Option "tag" must be set');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the HTML tag to use for the decoration
|
||||||
|
*
|
||||||
|
* @param string $tag
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTag(string $tag): static
|
||||||
|
{
|
||||||
|
$this->tag = $tag;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the transformation type of the HTML tag
|
||||||
|
*
|
||||||
|
* @param Transformation $transformation
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTransformation(Transformation $transformation): static
|
||||||
|
{
|
||||||
|
$this->transformation = $transformation;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the transformation type of the HTML tag
|
||||||
|
*
|
||||||
|
* @return Transformation
|
||||||
|
*/
|
||||||
|
public function getTransformation(): Transformation
|
||||||
|
{
|
||||||
|
return $this->transformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the condition callable to decide whether to decorate the element
|
||||||
|
*
|
||||||
|
* @return ?callable(FormElement): bool
|
||||||
|
*/
|
||||||
|
public function getCondition(): ?callable
|
||||||
|
{
|
||||||
|
return $this->condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the condition callable to decide whether to decorate the element
|
||||||
|
*
|
||||||
|
* @param callable(FormElement): bool $condition
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCondition(callable $condition): static
|
||||||
|
{
|
||||||
|
$this->condition = $condition;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the css class(es)
|
||||||
|
*
|
||||||
|
* @return ?(string|string[])
|
||||||
|
*/
|
||||||
|
public function getClass(): string|array|null
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the css class(es)
|
||||||
|
*
|
||||||
|
* @param string|string[] $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setClass(string|array $class): static
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get attributes to apply
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function getAttrs(): array
|
||||||
|
{
|
||||||
|
return $this->attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set attributes to apply
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $attrs
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAttrs(array $attrs): static
|
||||||
|
{
|
||||||
|
$this->attrs = $attrs;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidArgumentException if the condition callback does not return a boolean
|
||||||
|
* @throws RuntimeException if the condition callback throws an exception
|
||||||
|
*/
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$condition = $this->getCondition();
|
||||||
|
if ($condition !== null) {
|
||||||
|
try {
|
||||||
|
$shouldDecorate = $condition($formElement);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
throw new RuntimeException('Condition callback failed', previous: $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_bool($shouldDecorate)) {
|
||||||
|
throw new InvalidArgumentException(sprintf(
|
||||||
|
'Condition callback must return a boolean, got %s',
|
||||||
|
get_php_type($shouldDecorate)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $shouldDecorate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->getClass();
|
||||||
|
$this->getTransformation()->apply(
|
||||||
|
$result,
|
||||||
|
new HtmlElement(
|
||||||
|
$this->getTag(),
|
||||||
|
$class === null
|
||||||
|
? new Attributes($this->getAttrs())
|
||||||
|
: new Attributes(['class' => $class] + $this->getAttrs())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerAttributeCallbacks(Attributes $attributes): void
|
||||||
|
{
|
||||||
|
$attributes
|
||||||
|
->registerAttributeCallback('tag', null, $this->setTag(...))
|
||||||
|
->registerAttributeCallback('transformation', null, $this->setTransformation(...))
|
||||||
|
->registerAttributeCallback('condition', null, $this->setCondition(...))
|
||||||
|
->registerAttributeCallback('class', null, $this->setClass(...))
|
||||||
|
->registerAttributeCallback('attrs', null, $this->setAttrs(...));
|
||||||
|
}
|
||||||
|
}
|
||||||
105
vendor/ipl/html/src/FormDecoration/LabelDecorator.php
vendored
Normal file
105
vendor/ipl/html/src/FormDecoration/LabelDecorator.php
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\DecoratorOptions;
|
||||||
|
use ipl\Html\Contract\DecoratorOptionsInterface;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
use ipl\Html\Contract\FormSubmitElement;
|
||||||
|
use ipl\Html\Contract\HtmlElementInterface;
|
||||||
|
use ipl\Html\FormElement\RadioElement;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
|
use ipl\Html\ValidHtml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the label of the form element
|
||||||
|
*/
|
||||||
|
class LabelDecorator implements FormElementDecoration, DecoratorOptionsInterface
|
||||||
|
{
|
||||||
|
use DecoratorOptions;
|
||||||
|
|
||||||
|
/** @var string|string[] CSS classes to apply */
|
||||||
|
protected string|array $class = 'form-element-label';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the css class(es)
|
||||||
|
*
|
||||||
|
* @return string|string[]
|
||||||
|
*/
|
||||||
|
public function getClass(): string|array
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the css class(es)
|
||||||
|
*
|
||||||
|
* @param string|string[] $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setClass(string|array $class): static
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$isHtmlElement = $formElement instanceof HtmlElementInterface;
|
||||||
|
|
||||||
|
$elementLabel = $this->getElementLabel($formElement);
|
||||||
|
if (
|
||||||
|
$formElement instanceof FormSubmitElement
|
||||||
|
|| $elementLabel === null
|
||||||
|
|| ($isHtmlElement && $formElement->getTag() === 'fieldset')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($elementLabel instanceof HtmlElementInterface) {
|
||||||
|
$attributes['class'] = $this->getClass();
|
||||||
|
// RadioElement applies all its attributes to each of its options, so we cannot set a fallback
|
||||||
|
// id and for attribute here.
|
||||||
|
if ($isHtmlElement && ! $formElement instanceof RadioElement) {
|
||||||
|
$elementAttributes = $formElement->getAttributes();
|
||||||
|
if (! $elementAttributes->has('id')) {
|
||||||
|
$elementAttributes->set('id', uniqid('form-element-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes['for'] = $elementAttributes->get('id')->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
$elementLabel->addAttributes($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result->append($elementLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label element for the given form element
|
||||||
|
*
|
||||||
|
* @param FormElement $formElement
|
||||||
|
*
|
||||||
|
* @return ?ValidHtml The label element or null if no label is set
|
||||||
|
*/
|
||||||
|
protected function getElementLabel(FormElement $formElement): ?ValidHtml
|
||||||
|
{
|
||||||
|
$label = $formElement->getLabel();
|
||||||
|
if ($label === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HtmlElement('label', content: new Text($label));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerAttributeCallbacks(Attributes $attributes): void
|
||||||
|
{
|
||||||
|
$attributes->registerAttributeCallback('class', null, $this->setClass(...));
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
vendored
Normal file
18
vendor/ipl/html/src/FormDecoration/RenderElementDecorator.php
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ipl\Html\FormDecoration;
|
||||||
|
|
||||||
|
use ipl\Html\Contract\DecorationResult;
|
||||||
|
use ipl\Html\Contract\FormElement;
|
||||||
|
use ipl\Html\Contract\FormElementDecoration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the form element itself
|
||||||
|
*/
|
||||||
|
class RenderElementDecorator implements FormElementDecoration
|
||||||
|
{
|
||||||
|
public function decorateFormElement(DecorationResult $result, FormElement $formElement): void
|
||||||
|
{
|
||||||
|
$result->append($formElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user