mirror of
https://github.com/wavelog/wavelog.git
synced 2026-03-22 10:24:14 +00:00
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
require_once './src/Label/vendor/autoload.php';
|
||||
use Cloudlog\Label\PDF_Label;
|
||||
use Cloudlog\Label\tfpdf;
|
||||
use Cloudlog\Label\font\unifont\ttfonts;
|
||||
@@ -7,7 +8,7 @@ use Cloudlog\Label\font\unifont\ttfonts;
|
||||
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Labels extends CI_Controller {
|
||||
/*
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Controller: Labels
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -15,7 +16,7 @@ class Labels extends CI_Controller {
|
||||
| This Controller handles all things Labels, creating, editing and printing
|
||||
|
|
||||
|
|
||||
*/
|
||||
*/
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
@@ -34,7 +35,7 @@ class Labels extends CI_Controller {
|
||||
| Nothing fancy just shows the main display of how many labels are waiting
|
||||
| to be printed per station profile.
|
||||
|
|
||||
*/
|
||||
*/
|
||||
public function index() {
|
||||
$data['page_title'] = "QSL Card Labels";
|
||||
|
||||
@@ -52,7 +53,7 @@ class Labels extends CI_Controller {
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('labels/index');
|
||||
$this->load->view('interface_assets/footer', $footerData);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -62,9 +63,9 @@ class Labels extends CI_Controller {
|
||||
|
|
||||
| Shows the form used to create a label type.
|
||||
|
|
||||
*/
|
||||
*/
|
||||
public function create() {
|
||||
|
||||
|
||||
$data['page_title'] = "Create Label Type";
|
||||
|
||||
$this->load->library('form_validation');
|
||||
@@ -81,10 +82,10 @@ class Labels extends CI_Controller {
|
||||
{
|
||||
$this->load->model('labels_model');
|
||||
$this->labels_model->addLabel();
|
||||
|
||||
|
||||
redirect('labels');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function printids() {
|
||||
@@ -103,11 +104,13 @@ class Labels extends CI_Controller {
|
||||
|
||||
$this->prepareLabel($result);
|
||||
}
|
||||
|
||||
|
||||
function prepareLabel($qsos, $jscall = false) {
|
||||
$this->load->model('labels_model');
|
||||
$label = $this->labels_model->getDefaultLabel();
|
||||
|
||||
$label->font='DejaVuSans'; // Fix font to DejaVuSans
|
||||
|
||||
|
||||
try {
|
||||
if ($label) {
|
||||
$pdf = new PDF_Label(array(
|
||||
@@ -144,20 +147,20 @@ class Labels extends CI_Controller {
|
||||
}
|
||||
}
|
||||
define('FPDF_FONTPATH', './src/Label/font/');
|
||||
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
if ($label->font == 'DejaVuSans') {
|
||||
|
||||
if ($label->font == 'DejaVuSans') { // leave this here, for future Use
|
||||
$pdf->AddFont($label->font,'','DejaVuSansMono.ttf',true);
|
||||
$pdf->SetFont($label->font);
|
||||
} else {
|
||||
$pdf->AddFont($label->font);
|
||||
$pdf->SetFont($label->font);
|
||||
}
|
||||
|
||||
|
||||
if ($qsos->num_rows() > 0) {
|
||||
if ($label->qsos == 1) {
|
||||
$this->makeOneQsoLabel($qsos->result(), $pdf);
|
||||
$this->makeMultiQsoLabel($qsos->result(), $pdf,1);
|
||||
} else {
|
||||
$this->makeMultiQsoLabel($qsos->result(), $pdf, $label->qsos);
|
||||
}
|
||||
@@ -168,31 +171,19 @@ class Labels extends CI_Controller {
|
||||
$pdf->Output();
|
||||
}
|
||||
|
||||
function makeOneQsoLabel($qsos, $pdf) {
|
||||
foreach($qsos as $qso) {
|
||||
$time = strtotime($qso->COL_TIME_ON);
|
||||
$myFormatForView = date("d/m/Y H:i", $time);
|
||||
if($qso->COL_SAT_NAME != "") {
|
||||
$text = sprintf("%s\n\n%s %s\n%s %s \n\n%s", 'To: '.$qso->COL_CALL, $myFormatForView, 'on '.$qso->COL_BAND.' 2x'.$qso->COL_MODE.' RST '.$qso->COL_RST_SENT.'', 'Satellite: '.$qso->COL_SAT_NAME.' Mode: '.strtoupper($qso->COL_SAT_MODE).' ', '', 'Thanks for QSO.');
|
||||
} else {
|
||||
$text = sprintf("%s\n\n%s %s\n%s %s \n\n%s", 'To: '.$qso->COL_CALL, $myFormatForView, 'on '.$qso->COL_BAND.' 2x'.$qso->COL_MODE.' RST '.$qso->COL_RST_SENT.'', '', '', 'Thanks for QSO.');
|
||||
}
|
||||
|
||||
$pdf->Add_Label($text);
|
||||
}
|
||||
}
|
||||
|
||||
function makeMultiQsoLabel($qsos, $pdf, $numberofqsos) {
|
||||
$text = '';
|
||||
$current_callsign = '';
|
||||
$current_sat = '';
|
||||
$qso_data = [];
|
||||
foreach($qsos as $qso) {
|
||||
if ($qso->COL_CALL !== $current_callsign) {
|
||||
if (($qso->COL_SAT_NAME !== $current_sat) || ($qso->COL_CALL !== $current_callsign)) {
|
||||
if (!empty($qso_data)) {
|
||||
$this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos);
|
||||
$this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos);
|
||||
$qso_data = [];
|
||||
}
|
||||
$current_callsign = $qso->COL_CALL;
|
||||
$current_sat = $qso->COL_SAT_NAME;
|
||||
}
|
||||
|
||||
$qso_data[] = [
|
||||
@@ -203,47 +194,63 @@ class Labels extends CI_Controller {
|
||||
'mygrid' => $qso->station_gridsquare,
|
||||
'sat' => $qso->COL_SAT_NAME,
|
||||
'sat_mode' => $qso->COL_SAT_MODE,
|
||||
'qsl_recvd' => $qso->COL_QSL_RCVD
|
||||
];
|
||||
}
|
||||
if (!empty($qso_data)) {
|
||||
$this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos);
|
||||
$this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos);
|
||||
}
|
||||
}
|
||||
// New begin
|
||||
|
||||
function makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos) {
|
||||
$text = 'To: ' . $current_callsign . "\n\n";
|
||||
$count = 0;
|
||||
$qsotext = '';
|
||||
foreach ($qso_data as $key => $qso) {
|
||||
function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) {
|
||||
$tableData = [];
|
||||
$count_qso = 0;
|
||||
$qso=[];
|
||||
foreach ($preliminaryData as $key => $row) {
|
||||
$qso=$row;
|
||||
$time = strtotime($qso['time']);
|
||||
$myFormatForView = date("d/m/Y H:i", $time);
|
||||
$myFormatForView = date("Y-m-d H:i", $time);
|
||||
$rowData = [
|
||||
'Date/Time (UTC)' => $myFormatForView,
|
||||
'Band' => $row['band'],
|
||||
'Mode' => $row['mode'],
|
||||
'RST' => $row['rst'],
|
||||
];
|
||||
$tableData[] = $rowData;
|
||||
$count_qso++;
|
||||
|
||||
if($qso['sat'] != "") {
|
||||
$qsotext .= sprintf("%s %s %s %s\n", $myFormatForView, 'on '.$qso['band'].' 2x'.$qso['mode'].' RST '.$qso['rst'].'', 'Satellite: '.$qso['sat'].' Mode: '.strtoupper($qso['sat_mode']).' ', '');
|
||||
} else {
|
||||
$qsotext .= sprintf("%s %s\n", $myFormatForView, 'on '.$qso['band'].' 2x'.$qso['mode'].' RST '.$qso['rst']);
|
||||
if($count_qso == $qso_per_label){
|
||||
$this->generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso);
|
||||
$tableData = []; // reset the data
|
||||
$count_qso = 0; // reset the counter
|
||||
}
|
||||
$count++;
|
||||
|
||||
if ($count == $numberofqsos) {
|
||||
$text .= $qsotext;
|
||||
$text .= "\n" . 'Thanks for QSOs.';
|
||||
$pdf->Add_Label($text);
|
||||
$text = 'To: ' . $current_callsign . "\n\n";
|
||||
$count = 0;
|
||||
$qsotext = '';
|
||||
}
|
||||
unset($qso_data[$key]);
|
||||
unset($preliminaryData[$key]);
|
||||
}
|
||||
|
||||
if ($qsotext != '') {
|
||||
$text .= $qsotext;
|
||||
$text .= "\n" . 'Thanks for QSOs.';
|
||||
$pdf->Add_Label($text);
|
||||
// generate label for remaining QSOs
|
||||
if($count_qso > 0){
|
||||
$this->generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso);
|
||||
$preliminaryData = []; // reset the data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function generateLabel($pdf, $current_callsign, $tableData,$numofqsos,$qso){
|
||||
$builder = new \AsciiTable\Builder();
|
||||
$builder->addRows($tableData);
|
||||
$text = "Confirming QSO".($numofqsos>1 ? 's' : '')." with ";
|
||||
$text .= $current_callsign;
|
||||
$text .= "\n";
|
||||
$text .= $builder->renderTable();
|
||||
if($qso['sat'] != "") {
|
||||
$text .= "\n".'Satellite: '.$qso['sat'].' Mode: '.strtoupper($qso['sat_mode'][0]).'/'.strtoupper($qso['sat_mode'][1]);
|
||||
}
|
||||
$text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : '');
|
||||
$text .= " | ".($qso['qsl_recvd'] == 'Y' ? 'TNX' : 'PSE')." QSL";
|
||||
$pdf->Add_Label($text);
|
||||
}
|
||||
|
||||
// New End
|
||||
|
||||
public function edit($id) {
|
||||
$this->load->model('labels_model');
|
||||
|
||||
@@ -278,4 +285,4 @@ class Labels extends CI_Controller {
|
||||
$this->labels_model->saveDefaultLabel($id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,10 @@ class Labels_model extends CI_Model {
|
||||
$this->db->where('station_profile.user_id', $this->session->userdata('user_id'));
|
||||
$this->db->where_in('COL_QSL_SENT', array('R', 'Q'));
|
||||
$this->db->order_by("COL_DXCC", "ASC");
|
||||
$this->db->order_by("COL_CALL", "ASC");
|
||||
$this->db->order_by("COL_SAT_NAME", "ASC");
|
||||
$this->db->order_by("COL_TIME_ON", "ASC");
|
||||
$this->db->order_by("COL_MODE", "ASC");
|
||||
$query = $this->db->get($this->config->item('table_name'));
|
||||
|
||||
return $query;
|
||||
@@ -139,4 +143,4 @@ class Labels_model extends CI_Model {
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,29 +111,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label" for="font">Font</label>
|
||||
<div class="col-sm-4">
|
||||
<select name="font" class="form-control" id="font">
|
||||
<option value="courier">Courier</option>
|
||||
<option value="courierb">Courierb</option>
|
||||
<option value="courierbi">Courierbi</option>
|
||||
<option value="courieri">Courieri</option>
|
||||
<option value="DejaVuSans">DejaVuSans</option>
|
||||
<option value="helvetica">Helvetica</option>
|
||||
<option value="helveticab">Helveticab</option>
|
||||
<option value="helveticabi">Helveticabi</option>
|
||||
<option value="helveticai">Helveticai</option>
|
||||
<option value="symbol">Symbol</option>
|
||||
<option value="times">Times</option>
|
||||
<option value="timesb">Timesb</option>
|
||||
<option value="timesb">Timesb</option>
|
||||
<option value="timesbi">Timesbi</option>
|
||||
<option value="zapfdingbats">Zapfdingbats</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><i class="fas fa-plus-square"></i> Save Label Type</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,4 +118,4 @@
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -110,30 +110,6 @@
|
||||
<input name="label_qsos" type="number" min="1" max="40" step="1" class="form-control" id="label_qsos" aria-describedby="font_sizeHelp" value="<?php if(isset($label->qsos)) { echo $label->qsos; } ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label" for="font">Font</label>
|
||||
<div class="col-sm-4">
|
||||
<select name="font" class="form-control" id="font">
|
||||
<option value="courier" <?php if($label->font == "courier") { echo "selected=\"selected\""; } ?>>Courier</option>
|
||||
<option value="courierb" <?php if($label->font == "courierb") { echo "selected=\"selected\""; } ?>>Courierb</option>
|
||||
<option value="courierbi" <?php if($label->font == "courierbi") { echo "selected=\"selected\""; } ?>>Courierbi</option>
|
||||
<option value="courieri" <?php if($label->font == "courieri") { echo "selected=\"selected\""; } ?>>Courieri</option>
|
||||
<option value="DejaVuSans" <?php if($label->font == "DejaVuSans") { echo "selected=\"selected\""; } ?>>DejaVuSans</option>
|
||||
<option value="helvetica" <?php if($label->font == "helvetica") { echo "selected=\"selected\""; } ?>>Helvetica</option>
|
||||
<option value="helveticab" <?php if($label->font == "helveticab") { echo "selected=\"selected\""; } ?>>Helveticab</option>
|
||||
<option value="helveticabi" <?php if($label->font == "helveticabi") { echo "selected=\"selected\""; } ?>>Helveticabi</option>
|
||||
<option value="helveticai" <?php if($label->font == "helveticai") { echo "selected=\"selected\""; } ?>>Helveticai</option>
|
||||
<option value="symbol" <?php if($label->font == "symbol") { echo "selected=\"selected\""; } ?>>Symbol</option>
|
||||
<option value="times" <?php if($label->font == "times") { echo "selected=\"selected\""; } ?>>Times</option>
|
||||
<option value="timesb" <?php if($label->font == "timesb") { echo "selected=\"selected\""; } ?>>Timesb</option>
|
||||
<option value="timesb" <?php if($label->font == "timesb") { echo "selected=\"selected\""; } ?>>Timesb</option>
|
||||
<option value="timesbi" <?php if($label->font == "timesbi") { echo "selected=\"selected\""; } ?>>Timesbi</option>
|
||||
<option value="zapfdingbats" <?php if($label->font == "zapfdingbats") { echo "selected=\"selected\""; } ?>>Zapfdingbats</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><i class="fas fa-plus-square"></i> Save Label Type</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,4 +117,4 @@
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
25
src/Label/vendor/autoload.php
vendored
Normal file
25
src/Label/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit6ef2b7bf933fafec62d6bf7c15d6f12f::getLoader();
|
||||
585
src/Label/vendor/composer/ClassLoader.php
vendored
Normal file
585
src/Label/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,585 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
359
src/Label/vendor/composer/InstalledVersions.php
vendored
Normal file
359
src/Label/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, 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[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, 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[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, 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[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, 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[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<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[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @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';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @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 __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
src/Label/vendor/composer/LICENSE
vendored
Normal file
21
src/Label/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
10
src/Label/vendor/composer/autoload_classmap.php
vendored
Normal file
10
src/Label/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
9
src/Label/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
src/Label/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
12
src/Label/vendor/composer/autoload_psr4.php
vendored
Normal file
12
src/Label/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'dekor\\' => array($vendorDir . '/dekor/php-array-table/src'),
|
||||
'Ds\\' => array($vendorDir . '/php-ds/php-ds/src'),
|
||||
'AsciiTable\\' => array($vendorDir . '/malios/php-to-ascii-table/src'),
|
||||
);
|
||||
38
src/Label/vendor/composer/autoload_real.php
vendored
Normal file
38
src/Label/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit6ef2b7bf933fafec62d6bf7c15d6f12f
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit6ef2b7bf933fafec62d6bf7c15d6f12f', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit6ef2b7bf933fafec62d6bf7c15d6f12f', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit6ef2b7bf933fafec62d6bf7c15d6f12f::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
44
src/Label/vendor/composer/autoload_static.php
vendored
Normal file
44
src/Label/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit6ef2b7bf933fafec62d6bf7c15d6f12f
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'D' =>
|
||||
array (
|
||||
'Ds\\' => 3,
|
||||
),
|
||||
'A' =>
|
||||
array (
|
||||
'AsciiTable\\' => 11,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Ds\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-ds/php-ds/src',
|
||||
),
|
||||
'AsciiTable\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/malios/php-to-ascii-table/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit6ef2b7bf933fafec62d6bf7c15d6f12f::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit6ef2b7bf933fafec62d6bf7c15d6f12f::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit6ef2b7bf933fafec62d6bf7c15d6f12f::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
171
src/Label/vendor/composer/installed.json
vendored
Normal file
171
src/Label/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "dekor/php-array-table",
|
||||
"version": "2.0",
|
||||
"version_normalized": "2.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/deniskoronets/php-array-table.git",
|
||||
"reference": "ca40b21ba84eee6a9658a33fc5f897d76baaf8e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/deniskoronets/php-array-table/zipball/ca40b21ba84eee6a9658a33fc5f897d76baaf8e5",
|
||||
"reference": "ca40b21ba84eee6a9658a33fc5f897d76baaf8e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10"
|
||||
},
|
||||
"time": "2023-02-10T10:13:42+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"dekor\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Denis Koronets",
|
||||
"email": "deniskoronets@woo.zp.ua",
|
||||
"homepage": "https://woo.zp.ua/"
|
||||
}
|
||||
],
|
||||
"description": "PHP Library for printing associative arrays as text table (similar to mysql terminal console)",
|
||||
"keywords": [
|
||||
"library",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/deniskoronets/php-array-table/issues",
|
||||
"source": "https://github.com/deniskoronets/php-array-table/tree/2.0"
|
||||
},
|
||||
"install-path": "../dekor/php-array-table"
|
||||
},
|
||||
{
|
||||
"name": "malios/php-to-ascii-table",
|
||||
"version": "v3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/malios/php-to-ascii-table.git",
|
||||
"reference": "1a4621f5286f72ff0823627088e94382546b9218"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/malios/php-to-ascii-table/zipball/1a4621f5286f72ff0823627088e94382546b9218",
|
||||
"reference": "1a4621f5286f72ff0823627088e94382546b9218",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7|^8",
|
||||
"php-ds/php-ds": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "@stable",
|
||||
"vimeo/psalm": "@stable"
|
||||
},
|
||||
"time": "2022-02-13T20:15:16+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AsciiTable\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mehmed Aliosman",
|
||||
"email": "dev.mehmed.aliosman@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP library to generate plain text tables.",
|
||||
"keywords": [
|
||||
"ascii",
|
||||
"php",
|
||||
"plain text table",
|
||||
"table"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/malios/php-to-ascii-table/issues",
|
||||
"source": "https://github.com/malios/php-to-ascii-table/tree/v3.0.0"
|
||||
},
|
||||
"install-path": "../malios/php-to-ascii-table"
|
||||
},
|
||||
{
|
||||
"name": "php-ds/php-ds",
|
||||
"version": "v1.4.1",
|
||||
"version_normalized": "1.4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-ds/polyfill.git",
|
||||
"reference": "43d2df301a9e2017f67b8c11d94a5222f9c00fd1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-ds/polyfill/zipball/43d2df301a9e2017f67b8c11d94a5222f9c00fd1",
|
||||
"reference": "43d2df301a9e2017f67b8c11d94a5222f9c00fd1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ds": "1.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-ds/tests": "^1.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ds": "to improve performance and reduce memory usage"
|
||||
},
|
||||
"time": "2022-03-09T20:39:30+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rudi Theunissen",
|
||||
"email": "rudolf.theunissen@gmail.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"data structures",
|
||||
"ds",
|
||||
"php",
|
||||
"polyfill"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-ds/polyfill/issues",
|
||||
"source": "https://github.com/php-ds/polyfill/tree/v1.4.1"
|
||||
},
|
||||
"install-path": "../php-ds/php-ds"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
50
src/Label/vendor/composer/installed.php
vendored
Normal file
50
src/Label/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '377e3875ddde0f2437686215a845f75230f7dd17',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '377e3875ddde0f2437686215a845f75230f7dd17',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dekor/php-array-table' => array(
|
||||
'pretty_version' => '2.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => 'ca40b21ba84eee6a9658a33fc5f897d76baaf8e5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dekor/php-array-table',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'malios/php-to-ascii-table' => array(
|
||||
'pretty_version' => 'v3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '1a4621f5286f72ff0823627088e94382546b9218',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../malios/php-to-ascii-table',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-ds/php-ds' => array(
|
||||
'pretty_version' => 'v1.4.1',
|
||||
'version' => '1.4.1.0',
|
||||
'reference' => '43d2df301a9e2017f67b8c11d94a5222f9c00fd1',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-ds/php-ds',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
26
src/Label/vendor/composer/platform_check.php
vendored
Normal file
26
src/Label/vendor/composer/platform_check.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70000)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
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(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
2
src/Label/vendor/malios/php-to-ascii-table/.gitignore
vendored
Normal file
2
src/Label/vendor/malios/php-to-ascii-table/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.idea/
|
||||
vendor/
|
||||
21
src/Label/vendor/malios/php-to-ascii-table/LICENSE.md
vendored
Normal file
21
src/Label/vendor/malios/php-to-ascii-table/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Mehmed Aliosman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
116
src/Label/vendor/malios/php-to-ascii-table/README.md
vendored
Normal file
116
src/Label/vendor/malios/php-to-ascii-table/README.md
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
# php-to-ascii-table
|
||||
A small PHP library for generating plain text tables.
|
||||
|
||||

|
||||
|
||||
## Getting Started
|
||||
### Prerequisites
|
||||
|
||||
- PHP >= 7
|
||||
- ext-mbstring
|
||||
- Optionally Install [php-ds](https://github.com/php-ds/extension) extension (Recommended).
|
||||
|
||||
### Installation
|
||||
|
||||
Install via composer:
|
||||
|
||||
```bash
|
||||
$ composer require malios/php-to-ascii-table
|
||||
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```php
|
||||
<?php
|
||||
$builder = new \AsciiTable\Builder();
|
||||
|
||||
$builder->addRows([
|
||||
[
|
||||
'Order No' => 'A0001',
|
||||
'Product Name' => 'Intel CPU',
|
||||
'Price' => 700.00,
|
||||
'Quantity' => 1
|
||||
],
|
||||
[
|
||||
'Order No' => 'A0002',
|
||||
'Product Name' => 'Hard disk 10TB',
|
||||
'Price' => 500.00,
|
||||
'Quantity' => 2
|
||||
],
|
||||
[
|
||||
'Order No' => 'A0003',
|
||||
'Product Name' => 'Dell Laptop',
|
||||
'Price' => 11600.00,
|
||||
'Quantity' => 8
|
||||
],
|
||||
[
|
||||
'Order No' => 'A0004',
|
||||
'Product Name' => 'Intel CPU',
|
||||
'Price' => 5200.00,
|
||||
'Quantity' => 3
|
||||
]
|
||||
]);
|
||||
|
||||
$builder->addRow([
|
||||
'Order No' => 'A0005',
|
||||
'Product Name' => 'A4Tech Mouse',
|
||||
'Price' => 100.00,
|
||||
'Quantity' => 10
|
||||
]);
|
||||
|
||||
$builder->setTitle('Product List');
|
||||
|
||||
echo $builder->renderTable();
|
||||
|
||||
|
||||
// Show only some fields
|
||||
|
||||
$builder->showColumns(['Order No', 'Product Name', 'Quantity']);
|
||||
|
||||
echo $builder->renderTable();
|
||||
|
||||
```
|
||||
### Build table from objects
|
||||
You can build table form any object that implements JsonSerializable interface.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
class Person implements \JsonSerializable
|
||||
{
|
||||
private $name;
|
||||
|
||||
private $age;
|
||||
|
||||
public function __construct(string $name, int $age) {
|
||||
$this->name = $name;
|
||||
$this->age = $age;
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'age' => $this->age
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$builder = new \AsciiTable\Builder();
|
||||
|
||||
$builder->addRow(new Person('John', 25));
|
||||
$builder->addRow(new Person('Bill', 30));
|
||||
|
||||
echo $builder->renderTable();
|
||||
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
All contributors are welcome. You can open a new issue or submit a pull request.
|
||||
See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for details.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
|
||||
BIN
src/Label/vendor/malios/php-to-ascii-table/assets/table.png
vendored
Normal file
BIN
src/Label/vendor/malios/php-to-ascii-table/assets/table.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
46
src/Label/vendor/malios/php-to-ascii-table/composer.json
vendored
Normal file
46
src/Label/vendor/malios/php-to-ascii-table/composer.json
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "malios/php-to-ascii-table",
|
||||
"description": "A PHP library to generate plain text tables.",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"php",
|
||||
"table",
|
||||
"ascii",
|
||||
"plain text table"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mehmed Aliosman",
|
||||
"email": "dev.mehmed.aliosman@gmail.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7|^8",
|
||||
"php-ds/php-ds": "^1.1",
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "@stable",
|
||||
"vimeo/psalm": "@stable"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AsciiTable\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"AsciiTable\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"@phpunit",
|
||||
"@psalm"
|
||||
],
|
||||
"phpunit": "phpunit tests/ colors=always",
|
||||
"psalm": "psalm"
|
||||
}
|
||||
}
|
||||
2585
src/Label/vendor/malios/php-to-ascii-table/composer.lock
generated
vendored
Normal file
2585
src/Label/vendor/malios/php-to-ascii-table/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md
vendored
Normal file
9
src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
## Contributing
|
||||
|
||||
1. Fork project
|
||||
2. Create your feature branch: `git checkout -b my-new-feature`
|
||||
3. Make changes
|
||||
4. Run tests: `php vendor/bin/phpunit tests/`
|
||||
5. Commit your changes: `git commit -am 'Add some feature'`
|
||||
6. Push to the branch: `git push origin my-new-feature`
|
||||
7. Submit a pull request
|
||||
55
src/Label/vendor/malios/php-to-ascii-table/psalm.xml
vendored
Normal file
55
src/Label/vendor/malios/php-to-ascii-table/psalm.xml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
totallyTyped="false"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
<DeprecatedProperty errorLevel="info" />
|
||||
<DeprecatedClass errorLevel="info" />
|
||||
<DeprecatedConstant errorLevel="info" />
|
||||
<DeprecatedFunction errorLevel="info" />
|
||||
<DeprecatedInterface errorLevel="info" />
|
||||
<DeprecatedTrait errorLevel="info" />
|
||||
|
||||
<InternalMethod errorLevel="info" />
|
||||
<InternalProperty errorLevel="info" />
|
||||
<InternalClass errorLevel="info" />
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info" />
|
||||
<MissingConstructor errorLevel="info" />
|
||||
<MissingClosureParamType errorLevel="info" />
|
||||
<MissingParamType errorLevel="info" />
|
||||
|
||||
<RedundantCondition errorLevel="info" />
|
||||
|
||||
<DocblockTypeContradiction errorLevel="info" />
|
||||
<RedundantConditionGivenDocblockType errorLevel="info" />
|
||||
|
||||
<UnresolvableInclude errorLevel="info" />
|
||||
|
||||
<RawObjectIteration errorLevel="info" />
|
||||
|
||||
<InvalidStringClass errorLevel="info" />
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
253
src/Label/vendor/malios/php-to-ascii-table/src/Builder.php
vendored
Normal file
253
src/Label/vendor/malios/php-to-ascii-table/src/Builder.php
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
use AsciiTable\Exception\BuilderException;
|
||||
use Ds\Collection;
|
||||
|
||||
class Builder
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CELL_SEPARATOR = '│';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_LINE_SEPARATOR = '─';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CELL_PADDING = ' ';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_JOIN_INNER = '┼';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CORNER_TOP_LEFT = '┌';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CORNER_TOP_RIGHT = '┐';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_JOIN_LEFT_INNER = '├';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_JOIN_RIGHT_INNER = '┤';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_JOIN_TOP_INNER = '┬';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_JOIN_BOTTOM_INNER = '┴';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CORNER_BOTTOM_LEFT = '└';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const CHAR_CORNER_BOTTOM_RIGHT = '┘';
|
||||
|
||||
/**
|
||||
* @var Table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $title;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->table = new Table();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table
|
||||
*
|
||||
* @return Table
|
||||
*/
|
||||
public function getTable() : Table
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add single row.
|
||||
* The value passed should be either an array or an JsonSerializable object
|
||||
*
|
||||
* @param array|\JsonSerializable $rowArrayOrObject
|
||||
* @throws BuilderException
|
||||
*/
|
||||
public function addRow($rowArrayOrObject)
|
||||
{
|
||||
if (is_array($rowArrayOrObject)) {
|
||||
$rowArray = $rowArrayOrObject;
|
||||
} else if ($rowArrayOrObject instanceof \JsonSerializable) {
|
||||
$rowArray = $rowArrayOrObject->jsonSerialize();
|
||||
} else {
|
||||
throw new BuilderException(sprintf(
|
||||
'Row must be either an array or JsonSerializable, %s given instead',
|
||||
gettype($rowArrayOrObject)
|
||||
));
|
||||
}
|
||||
|
||||
$row = new Row();
|
||||
foreach ($rowArray as $columnName => $value) {
|
||||
$cell = new Cell($columnName, $value);
|
||||
$row->addCell($cell);
|
||||
}
|
||||
|
||||
$this->table->addRow($row);
|
||||
}
|
||||
|
||||
public function setTitle(string $title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple rows
|
||||
*
|
||||
* @param array[]|\JsonSerializable[] $rows
|
||||
* @return void
|
||||
*/
|
||||
public function addRows(array $rows)
|
||||
{
|
||||
foreach ($rows as $row) {
|
||||
$this->addRow($row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show only specific columns of the table
|
||||
*
|
||||
* @param array $columnNames
|
||||
* @return void
|
||||
* @throws BuilderException
|
||||
*/
|
||||
public function showColumns(array $columnNames)
|
||||
{
|
||||
$this->table->setVisibleColumns($columnNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render table and return result string
|
||||
*
|
||||
* @return string
|
||||
* @throws BuilderException
|
||||
*/
|
||||
public function renderTable() : string
|
||||
{
|
||||
if ($this->table->isEmpty()) throw new BuilderException('Cannot render empty table');
|
||||
|
||||
$visibleColumns = $this->table->getVisibleColumns();
|
||||
|
||||
// border for header and footer
|
||||
$borderParts = array_map(function ($columnName) {
|
||||
$width = $this->table->getColumnWidth($columnName);
|
||||
return str_repeat(self::CHAR_LINE_SEPARATOR, ($width + 2));
|
||||
}, $visibleColumns->toArray());
|
||||
|
||||
$borderTop = self::CHAR_CORNER_TOP_LEFT
|
||||
. join(self::CHAR_JOIN_TOP_INNER, $borderParts)
|
||||
. self::CHAR_CORNER_TOP_RIGHT;
|
||||
$borderMiddle = self::CHAR_JOIN_LEFT_INNER
|
||||
. join(self::CHAR_JOIN_INNER, $borderParts)
|
||||
. self::CHAR_JOIN_RIGHT_INNER;
|
||||
$borderBottom = self::CHAR_CORNER_BOTTOM_LEFT
|
||||
. join(self::CHAR_JOIN_BOTTOM_INNER, $borderParts)
|
||||
. self::CHAR_CORNER_BOTTOM_RIGHT;
|
||||
|
||||
$headerCells = array_map(function ($columnName) {
|
||||
return new Cell($columnName, $columnName);
|
||||
}, $visibleColumns->toArray());
|
||||
|
||||
$headerRow = new Row();
|
||||
$headerRow->addCells(...$headerCells);
|
||||
$header = $this->renderRow($headerRow, $visibleColumns);
|
||||
|
||||
$body = '';
|
||||
$rows = $this->table->getRows();
|
||||
$visibleColumns = $this->table->getVisibleColumns();
|
||||
foreach ($rows as $row) {
|
||||
$currentLine = $this->renderRow($row, $visibleColumns);
|
||||
$body .= $currentLine . PHP_EOL;
|
||||
}
|
||||
|
||||
if ($this->title === null) {
|
||||
$titleString = '';
|
||||
} else {
|
||||
$titlePadding = intdiv(max(0, mb_strwidth($borderTop) - mb_strwidth($this->title)), 2);
|
||||
$titleString = str_repeat(' ', $titlePadding) . $this->title . PHP_EOL;
|
||||
}
|
||||
|
||||
$tableAsString = $titleString . $borderTop . PHP_EOL . $header . PHP_EOL . $borderMiddle . PHP_EOL . $body . $borderBottom;
|
||||
return $tableAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render single row and return string
|
||||
*
|
||||
* @param RowInterface $row
|
||||
* @param Collection $columnNames
|
||||
* @return string
|
||||
*/
|
||||
private function renderRow(RowInterface $row, Collection $columnNames)
|
||||
{
|
||||
$line = self::CHAR_CELL_SEPARATOR;
|
||||
|
||||
// render cells of the row
|
||||
foreach ($columnNames as $columnName) {
|
||||
$colWidth = $this->table->getColumnWidth($columnName);
|
||||
if ($row->hasCell($columnName)) {
|
||||
$cell = $row->getCell($columnName);
|
||||
$currentCell = $this->renderCell($cell, $colWidth);
|
||||
} else {
|
||||
$currentCell = $this->renderCell(new Cell($columnName, ''), $colWidth);
|
||||
}
|
||||
|
||||
$line .= $currentCell . self::CHAR_CELL_SEPARATOR;
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render cell content with left and right padding depending on the column width
|
||||
*
|
||||
* @param CellInterface $cell
|
||||
* @param int $colWidth
|
||||
* @return string
|
||||
*/
|
||||
private function renderCell(CellInterface $cell, int $colWidth) : string
|
||||
{
|
||||
$filler = str_repeat(self::CHAR_CELL_PADDING, ($colWidth - $cell->getWidth()));
|
||||
if ($cell->getAlign() == Cell::ALIGN_LEFT) {
|
||||
$content = self::CHAR_CELL_PADDING . $cell->getValue() . $filler . self::CHAR_CELL_PADDING;
|
||||
} else {
|
||||
$content = self::CHAR_CELL_PADDING . $filler . $cell->getValue() . self::CHAR_CELL_PADDING;
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
105
src/Label/vendor/malios/php-to-ascii-table/src/Cell.php
vendored
Normal file
105
src/Label/vendor/malios/php-to-ascii-table/src/Cell.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
class Cell implements CellInterface
|
||||
{
|
||||
/**
|
||||
* int
|
||||
*/
|
||||
const ALIGN_LEFT = 0;
|
||||
|
||||
/**
|
||||
* int
|
||||
*/
|
||||
const ALIGN_RIGHT = 1;
|
||||
|
||||
/**
|
||||
* The name of the column that the cell belongs to
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $columnName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $align = self::ALIGN_LEFT;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $width = 0;
|
||||
|
||||
public function __construct($columnName, $value = '')
|
||||
{
|
||||
$this->setColumnName($columnName);
|
||||
$this->setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValue() : string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
if (is_float($value)) {
|
||||
$round = round($value);
|
||||
if (($value - $round) === (float)0) {
|
||||
$this->value = number_format($value, 2, '.', ' ');
|
||||
} else {
|
||||
$this->value = (string) $value;
|
||||
}
|
||||
$this->align = self::ALIGN_RIGHT;
|
||||
} elseif (is_int($value)) {
|
||||
$this->value = (string) $value;
|
||||
$this->align = self::ALIGN_RIGHT;
|
||||
} else {
|
||||
$this->value = (string) $value;
|
||||
$this->align = self::ALIGN_LEFT;
|
||||
}
|
||||
|
||||
$this->width = mb_strwidth($this->value);
|
||||
}
|
||||
|
||||
public function getAlign(): int
|
||||
{
|
||||
return $this->align;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getColumnName() : string
|
||||
{
|
||||
return $this->columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setColumnName(string $columnName)
|
||||
{
|
||||
$this->columnName = $columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWidth() : int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
}
|
||||
48
src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php
vendored
Normal file
48
src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
interface CellInterface
|
||||
{
|
||||
/**
|
||||
* Get value of the cell
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue() : string;
|
||||
|
||||
/**
|
||||
* Set value of the cell.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setValue($value);
|
||||
|
||||
/**
|
||||
* Get the name of the column that the cell belongs to
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnName() : string;
|
||||
|
||||
/**
|
||||
* Get the alignment of the cell
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAlign(): int;
|
||||
|
||||
/**
|
||||
* Set the name of the column that the cell belongs to
|
||||
*
|
||||
* @param string $columnName
|
||||
*/
|
||||
public function setColumnName(string $columnName);
|
||||
|
||||
/**
|
||||
* Get the width (string length) of the cell
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth() : int;
|
||||
}
|
||||
7
src/Label/vendor/malios/php-to-ascii-table/src/Exception/BuilderException.php
vendored
Normal file
7
src/Label/vendor/malios/php-to-ascii-table/src/Exception/BuilderException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace AsciiTable\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class BuilderException extends Exception{ }
|
||||
61
src/Label/vendor/malios/php-to-ascii-table/src/Row.php
vendored
Normal file
61
src/Label/vendor/malios/php-to-ascii-table/src/Row.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
use Ds\Map;
|
||||
use Ds\Collection;
|
||||
|
||||
class Row implements RowInterface
|
||||
{
|
||||
/**
|
||||
* @var Map
|
||||
*/
|
||||
private $cells;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cells = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCell(CellInterface $cell)
|
||||
{
|
||||
$this->cells->put($cell->getColumnName(), $cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCells(CellInterface ...$cells)
|
||||
{
|
||||
foreach ($cells as $cell) {
|
||||
$this->addCell($cell);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCell($columnName) : CellInterface
|
||||
{
|
||||
return $this->cells->get($columnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCell($columnName) : bool
|
||||
{
|
||||
return $this->cells->hasKey($columnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCells() : Collection
|
||||
{
|
||||
return $this->cells;
|
||||
}
|
||||
}
|
||||
45
src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php
vendored
Normal file
45
src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
use Ds\Collection;
|
||||
|
||||
interface RowInterface
|
||||
{
|
||||
/**
|
||||
* Add single cell to the row
|
||||
*
|
||||
* @param CellInterface $cell
|
||||
*/
|
||||
public function addCell(CellInterface $cell);
|
||||
|
||||
/**
|
||||
* Add multiple cells to row
|
||||
*
|
||||
* @param CellInterface ...$cells
|
||||
*/
|
||||
public function addCells(CellInterface ...$cells);
|
||||
|
||||
/**
|
||||
* Get single cell by name
|
||||
*
|
||||
* @param $columnName
|
||||
* @return CellInterface
|
||||
*/
|
||||
public function getCell($columnName) : CellInterface;
|
||||
|
||||
/**
|
||||
* Check if the row has a cell cell for given column
|
||||
*
|
||||
* @param $columnName
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCell($columnName) : bool;
|
||||
|
||||
/**
|
||||
* Get all cells
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCells() : Collection;
|
||||
}
|
||||
123
src/Label/vendor/malios/php-to-ascii-table/src/Table.php
vendored
Normal file
123
src/Label/vendor/malios/php-to-ascii-table/src/Table.php
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
use Ds\Map;
|
||||
use Ds\Set;
|
||||
|
||||
class Table implements TableInterface
|
||||
{
|
||||
/**
|
||||
* @var RowInterface[]
|
||||
*/
|
||||
private $rows = [];
|
||||
|
||||
/**
|
||||
* @var Set
|
||||
*/
|
||||
private $visibleColumns;
|
||||
|
||||
/**
|
||||
* @var Set
|
||||
*/
|
||||
private $allColumns;
|
||||
|
||||
/**
|
||||
* @var Map
|
||||
*/
|
||||
private $biggestValues;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->visibleColumns = new Set();
|
||||
$this->allColumns = new Set();
|
||||
$this->biggestValues = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addRow(RowInterface $row)
|
||||
{
|
||||
foreach ($row->getCells() as $cell) {
|
||||
$columnName = $cell->getColumnName();
|
||||
|
||||
$this->allColumns->add($columnName);
|
||||
|
||||
$width = $cell->getWidth();
|
||||
if ($this->biggestValues->hasKey($columnName)) {
|
||||
if ($width > $this->biggestValues->get($columnName)) {
|
||||
$this->biggestValues->put($columnName, $width);
|
||||
}
|
||||
} else {
|
||||
$this->biggestValues->put($columnName, $width);
|
||||
}
|
||||
}
|
||||
|
||||
array_push($this->rows, $row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRows() : array
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEmpty() : bool
|
||||
{
|
||||
return empty($this->rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVisibleColumns(array $columnNames)
|
||||
{
|
||||
$this->visibleColumns->clear();
|
||||
$this->visibleColumns->allocate(count($columnNames));
|
||||
$this->visibleColumns->add(...$columnNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVisibleColumns() : Set
|
||||
{
|
||||
if ($this->visibleColumns->isEmpty()) {
|
||||
return $this->getAllColumns();
|
||||
}
|
||||
|
||||
return $this->visibleColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAllColumns() : Set
|
||||
{
|
||||
return $this->allColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getColumnWidth(string $columnName) : int
|
||||
{
|
||||
$width = 0;
|
||||
if ($this->biggestValues->hasKey($columnName)) {
|
||||
$width = $this->biggestValues->get($columnName);
|
||||
}
|
||||
|
||||
$visibleColumns = $this->getVisibleColumns();
|
||||
if ($visibleColumns->contains($columnName) && mb_strwidth($columnName) > $width) {
|
||||
$width = mb_strwidth($columnName);
|
||||
}
|
||||
|
||||
return $width;
|
||||
}
|
||||
}
|
||||
58
src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php
vendored
Normal file
58
src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace AsciiTable;
|
||||
|
||||
use Ds\Set;
|
||||
|
||||
interface TableInterface
|
||||
{
|
||||
/**
|
||||
* Add single row to the table
|
||||
*
|
||||
* @param RowInterface $row
|
||||
*/
|
||||
public function addRow(RowInterface $row);
|
||||
|
||||
/**
|
||||
* Get all rows in the table
|
||||
*
|
||||
* @return RowInterface[]
|
||||
*/
|
||||
public function getRows() : array;
|
||||
|
||||
/**
|
||||
* Check if the table is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty() : bool;
|
||||
|
||||
/**
|
||||
* Set visible columns
|
||||
*
|
||||
* @param string[] $columnNames
|
||||
*/
|
||||
public function setVisibleColumns(array $columnNames);
|
||||
|
||||
/**
|
||||
* Get visible columns
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function getVisibleColumns() : Set;
|
||||
|
||||
/**
|
||||
* Get all columns in the table
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function getAllColumns() : Set;
|
||||
|
||||
/**
|
||||
* Get the width of a column by name
|
||||
*
|
||||
* @param string $columnName
|
||||
* @return int
|
||||
*/
|
||||
public function getColumnWidth(string $columnName) : int;
|
||||
}
|
||||
33
src/Label/vendor/php-ds/php-ds/CHANGELOG.md
vendored
Normal file
33
src/Label/vendor/php-ds/php-ds/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [1.3.0] - 2020-10-13
|
||||
### Changed
|
||||
- Implement ArrayAccess consistently
|
||||
### Fixed
|
||||
- Return types were incorrectly nullable in some cases
|
||||
- Deque capacity was inconsistent with the extension
|
||||
|
||||
## [1.2.0] - 2017-08-03
|
||||
### Changed
|
||||
- Minor capacity updates
|
||||
|
||||
## [1.1.1] - 2016-08-09
|
||||
### Fixed
|
||||
- `Stack` and `Queue` array access should throw `OutOfBoundsException`, not `Error`.
|
||||
|
||||
### Improved
|
||||
- Added a lot of docblock comments that were missing.
|
||||
|
||||
## [1.1.0] - 2016-08-04
|
||||
### Added
|
||||
- `Pair::copy`
|
||||
|
||||
## [1.0.3] - 2016-08-01
|
||||
### Added
|
||||
- `Set::merge`
|
||||
|
||||
## [1.0.2] - 2016-07-31
|
||||
### Added
|
||||
- `Map::putAll`
|
||||
21
src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md
vendored
Normal file
21
src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are accepted via [pull requests](https://github.com/php-ds/ext/pulls). If you would like to report a bug, please create an [issue](https://github.com/php-ds/ext/issues) instead.
|
||||
|
||||
## Issues
|
||||
|
||||
- **How to reproduce** - Provide an easy way to reproduce the bug. This makes it easier for others to debug.
|
||||
|
||||
- **Platform details** - Specify your platform and your PHP version, eg. "PHP 7.0.2 on Ubuntu 14.04 64x".
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- **Add tests** - Your patch won't be accepted if it doesn't have tests where appropriate.
|
||||
|
||||
- **Document any change in behaviour** - Make sure the README and any other relevant documentation updated.
|
||||
|
||||
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
|
||||
|
||||
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
|
||||
|
||||
- **Coding style** - Try to match the style of the rest of the source wherever possible. Your patch won't be accepted if the style is significantly different.
|
||||
20
src/Label/vendor/php-ds/php-ds/LICENSE
vendored
Normal file
20
src/Label/vendor/php-ds/php-ds/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Rudi Theunissen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
38
src/Label/vendor/php-ds/php-ds/README.md
vendored
Normal file
38
src/Label/vendor/php-ds/php-ds/README.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Data Structures for PHP
|
||||
|
||||
[](https://github.com/php-ds/polyfill/actions?query=workflow%3A%22CI%22+branch%3Amaster)
|
||||
[](https://packagist.org/packages/php-ds/php-ds)
|
||||
|
||||
This is a compatibility polyfill for the [extension](https://github.com/php-ds/extension). You should include this package as a dependency of your project
|
||||
to ensure that your codebase would still be functional in an environment where the extension is not installed. The polyfill will not be loaded if the extension is installed and enabled.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
composer require php-ds/php-ds
|
||||
```
|
||||
|
||||
You can also *require* that the extension be installed using `ext-ds`.
|
||||
|
||||
## Test
|
||||
|
||||
```
|
||||
composer install
|
||||
composer test
|
||||
```
|
||||
|
||||
Make sure that the *ds* extension is not enabled, as the polyfill will not be loaded if it is.
|
||||
The test output will indicate whether the extension is active.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](CONTRIBUTING.md) for more information.
|
||||
|
||||
### Credits
|
||||
|
||||
- [Rudi Theunissen](https://github.com/rtheunissen)
|
||||
- [Joe Watkins](https://github.com/krakjoe)
|
||||
|
||||
### License
|
||||
|
||||
The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.
|
||||
32
src/Label/vendor/php-ds/php-ds/composer.json
vendored
Normal file
32
src/Label/vendor/php-ds/php-ds/composer.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "php-ds/php-ds",
|
||||
"license": "MIT",
|
||||
"keywords": ["php", "ds", "data structures", "polyfill"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rudi Theunissen",
|
||||
"email": "rudolf.theunissen@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-ds/tests": "^1.3"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ds": "1.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ds": "to improve performance and reduce memory usage"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4" : {
|
||||
"Ds\\": "src"
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/Label/vendor/php-ds/php-ds/src/Collection.php
vendored
Normal file
56
src/Label/vendor/php-ds/php-ds/src/Collection.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
/**
|
||||
* Collection is the base interface which covers functionality common to all the
|
||||
* data structures in this library. It guarantees that all structures are
|
||||
* traversable, countable, and can be converted to json using json_encode().
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template-covariant TKey
|
||||
* @template-covariant TValue
|
||||
* @extends Traversable<TKey, TValue>
|
||||
*/
|
||||
interface Collection extends \IteratorAggregate, \Countable, \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Removes all values from the collection.
|
||||
*/
|
||||
public function clear();
|
||||
|
||||
/**
|
||||
* Returns the size of the collection.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int;
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of the collection.
|
||||
*
|
||||
* @return static a copy of the collection.
|
||||
*
|
||||
* @psalm-return static<TKey, TValue>
|
||||
*/
|
||||
public function copy();
|
||||
|
||||
/**
|
||||
* Returns whether the collection is empty.
|
||||
*
|
||||
* This should be equivalent to a count of zero, but is not required.
|
||||
* Implementations should define what empty means in their own context.
|
||||
*/
|
||||
public function isEmpty(): bool;
|
||||
|
||||
/**
|
||||
* Returns an array representation of the collection.
|
||||
*
|
||||
* The format of the returned array is implementation-dependent.
|
||||
* Some implementations may throw an exception if an array representation
|
||||
* could not be created.
|
||||
*
|
||||
* @return array<TKey, TValue>
|
||||
*/
|
||||
public function toArray(): array;
|
||||
}
|
||||
29
src/Label/vendor/php-ds/php-ds/src/Deque.php
vendored
Normal file
29
src/Label/vendor/php-ds/php-ds/src/Deque.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
/**
|
||||
* A Deque (pronounced "deck") is a sequence of values in a contiguous buffer
|
||||
* that grows and shrinks automatically. The name is a common abbreviation of
|
||||
* "double-ended queue".
|
||||
*
|
||||
* While a Deque is very similar to a Vector, it offers constant time operations
|
||||
* at both ends of the buffer, ie. shift, unshift, push and pop are all O(1).
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Sequence<TValue>
|
||||
*/
|
||||
final class Deque implements Sequence
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
use Traits\GenericSequence;
|
||||
use Traits\SquaredCapacity;
|
||||
|
||||
public const MIN_CAPACITY = 8;
|
||||
|
||||
protected function shouldIncreaseCapacity(): bool
|
||||
{
|
||||
return count($this) >= $this->capacity;
|
||||
}
|
||||
}
|
||||
32
src/Label/vendor/php-ds/php-ds/src/Hashable.php
vendored
Normal file
32
src/Label/vendor/php-ds/php-ds/src/Hashable.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
/**
|
||||
* Hashable is an interface which allows objects to be used as keys.
|
||||
*
|
||||
* It’s an alternative to spl_object_hash(), which determines an object’s hash
|
||||
* based on its handle: this means that two objects that are considered equal
|
||||
* by an implicit definition would not treated as equal because they are not
|
||||
* the same instance.
|
||||
*
|
||||
* @package Ds
|
||||
*/
|
||||
interface Hashable
|
||||
{
|
||||
/**
|
||||
* Produces a scalar value to be used as the object's hash, which determines
|
||||
* where it goes in the hash table. While this value does not have to be
|
||||
* unique, objects which are equal must have the same hash value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function hash();
|
||||
|
||||
/**
|
||||
* Determines if two objects should be considered equal. Both objects will
|
||||
* be instances of the same class but may not be the same instance.
|
||||
*
|
||||
* @param mixed $obj An instance of the same class to compare to.
|
||||
*/
|
||||
public function equals($obj): bool;
|
||||
}
|
||||
811
src/Label/vendor/php-ds/php-ds/src/Map.php
vendored
Normal file
811
src/Label/vendor/php-ds/php-ds/src/Map.php
vendored
Normal file
@@ -0,0 +1,811 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use Error;
|
||||
use OutOfBoundsException;
|
||||
use OutOfRangeException;
|
||||
use Traversable;
|
||||
use UnderflowException;
|
||||
|
||||
/**
|
||||
* A Map is a sequential collection of key-value pairs, almost identical to an
|
||||
* array used in a similar context. Keys can be any type, but must be unique.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TKey
|
||||
* @template TValue
|
||||
* @implements Collection<TKey, TValue>
|
||||
*/
|
||||
final class Map implements Collection, \ArrayAccess
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
use Traits\SquaredCapacity;
|
||||
|
||||
public const MIN_CAPACITY = 8;
|
||||
|
||||
/**
|
||||
* @var array internal array to store pairs
|
||||
*
|
||||
* @psalm-var array<int, Pair>
|
||||
*/
|
||||
private $pairs = [];
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param iterable<mixed, mixed> $values
|
||||
*
|
||||
* @psalm-param iterable<TKey, TValue> $values
|
||||
*/
|
||||
public function __construct(iterable $values = [])
|
||||
{
|
||||
if (func_num_args()) {
|
||||
$this->putAll($values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all values by applying a callback function to each value.
|
||||
*
|
||||
* @param callable $callback Accepts two arguments: key and value, should
|
||||
* return what the updated value will be.
|
||||
*
|
||||
* @psalm-param callable(TKey, TValue): TValue $callback
|
||||
*/
|
||||
public function apply(callable $callback)
|
||||
{
|
||||
foreach ($this->pairs as &$pair) {
|
||||
$pair->value = $callback($pair->key, $pair->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->pairs = [];
|
||||
$this->capacity = self::MIN_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first Pair from the Map
|
||||
*
|
||||
* @return Pair
|
||||
*
|
||||
* @throws UnderflowException
|
||||
*
|
||||
* @psalm-return Pair<TKey, TValue>
|
||||
*/
|
||||
public function first(): Pair
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
return $this->pairs[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last Pair from the Map
|
||||
*
|
||||
* @return Pair
|
||||
*
|
||||
* @throws UnderflowException
|
||||
*
|
||||
* @psalm-return Pair<TKey, TValue>
|
||||
*/
|
||||
public function last(): Pair
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
return $this->pairs[count($this->pairs) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pair at a specified position in the Map
|
||||
*
|
||||
* @return Pair
|
||||
*
|
||||
* @throws OutOfRangeException
|
||||
*
|
||||
* @psalm-return Pair<TKey, TValue>
|
||||
*/
|
||||
public function skip(int $position): Pair
|
||||
{
|
||||
if ($position < 0 || $position >= count($this->pairs)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
return $this->pairs[$position]->copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of associating all keys of a given traversable object
|
||||
* or array with their corresponding values, as well as those of this map.
|
||||
*
|
||||
* @param array|\Traversable $values
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @template TKey2
|
||||
* @template TValue2
|
||||
* @psalm-param iterable<TKey2, TValue2> $values
|
||||
* @psalm-return Map<TKey|TKey2, TValue|TValue2>
|
||||
*/
|
||||
public function merge($values): Map
|
||||
{
|
||||
$merged = new self($this);
|
||||
$merged->putAll($values);
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map containing the pairs of the current instance whose keys
|
||||
* are also present in the given map. In other words, returns a copy of the
|
||||
* current map with all keys removed that are not also in the other map.
|
||||
*
|
||||
* @param Map $map The other map.
|
||||
*
|
||||
* @return Map A new map containing the pairs of the current instance
|
||||
* whose keys are also present in the given map. In other
|
||||
* words, returns a copy of the current map with all keys
|
||||
* removed that are not also in the other map.
|
||||
*
|
||||
* @template TKey2
|
||||
* @template TValue2
|
||||
* @psalm-param Map<TKey2, TValue2> $map
|
||||
* @psalm-return Map<TKey&TKey2, TValue>
|
||||
*/
|
||||
public function intersect(Map $map): Map
|
||||
{
|
||||
return $this->filter(function($key) use ($map) {
|
||||
return $map->hasKey($key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of removing all keys from the current instance that
|
||||
* are present in a given map.
|
||||
*
|
||||
* @param Map $map The map containing the keys to exclude.
|
||||
*
|
||||
* @return Map The result of removing all keys from the current instance
|
||||
* that are present in a given map.
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param Map<TKey, TValue2> $map
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function diff(Map $map): Map
|
||||
{
|
||||
return $this->filter(function($key) use ($map) {
|
||||
return ! $map->hasKey($key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether two keys are equal.
|
||||
*
|
||||
* @param mixed $a
|
||||
* @param mixed $b
|
||||
*
|
||||
* @psalm-param TKey $a
|
||||
* @psalm-param TKey $b
|
||||
*/
|
||||
private function keysAreEqual($a, $b): bool
|
||||
{
|
||||
if (is_object($a) && $a instanceof Hashable) {
|
||||
return get_class($a) === get_class($b) && $a->equals($b);
|
||||
}
|
||||
|
||||
return $a === $b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to look up a key in the table.
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @return Pair|null
|
||||
*
|
||||
* @psalm-return Pair<TKey, TValue>|null
|
||||
*/
|
||||
private function lookupKey($key)
|
||||
{
|
||||
foreach ($this->pairs as $pair) {
|
||||
if ($this->keysAreEqual($pair->key, $key)) {
|
||||
return $pair;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to look up a value in the table.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return Pair|null
|
||||
*
|
||||
* @psalm-return Pair<TKey, TValue>|null
|
||||
*/
|
||||
private function lookupValue($value)
|
||||
{
|
||||
foreach ($this->pairs as $pair) {
|
||||
if ($pair->value === $value) {
|
||||
return $pair;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an association a given key exists.
|
||||
*
|
||||
* @param mixed $key
|
||||
*
|
||||
* @psalm-param TKey $key
|
||||
*/
|
||||
public function hasKey($key): bool
|
||||
{
|
||||
return $this->lookupKey($key) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an association for a given value exists.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function hasValue($value): bool
|
||||
{
|
||||
return $this->lookupValue($value) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->pairs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map containing only the values for which a predicate
|
||||
* returns true. A boolean test will be used if a predicate is not provided.
|
||||
*
|
||||
* @param callable|null $callback Accepts a key and a value, and returns:
|
||||
* true : include the value,
|
||||
* false: skip the value.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @psalm-param (callable(TKey, TValue): bool)|null $callback
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function filter(callable $callback = null): Map
|
||||
{
|
||||
$filtered = new self();
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
if ($callback ? $callback($key, $value) : $value) {
|
||||
$filtered->put($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value associated with a key, or an optional default if the
|
||||
* key is not associated with a value.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed The associated value or fallback default if provided.
|
||||
*
|
||||
* @throws OutOfBoundsException if no default was provided and the key is
|
||||
* not associated with a value.
|
||||
*
|
||||
* @template TDefault
|
||||
* @psalm-param TKey $key
|
||||
* @psalm-param TDefault $default
|
||||
* @psalm-return TValue|TDefault
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (($pair = $this->lookupKey($key))) {
|
||||
return $pair->value;
|
||||
}
|
||||
|
||||
// Check if a default was provided.
|
||||
if (func_num_args() === 1) {
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of all the keys in the map.
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @psalm-return Set<TKey>
|
||||
*/
|
||||
public function keys(): Set
|
||||
{
|
||||
$key = function($pair) {
|
||||
return $pair->key;
|
||||
};
|
||||
|
||||
return new Set(array_map($key, $this->pairs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map using the results of applying a callback to each value.
|
||||
*
|
||||
* The keys will be equal in both maps.
|
||||
*
|
||||
* @param callable $callback Accepts two arguments: key and value, should
|
||||
* return what the updated value will be.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @template TNewValue
|
||||
* @psalm-param callable(TKey, TValue): TNewValue $callback
|
||||
* @psalm-return Map<TKey, TNewValue>
|
||||
*/
|
||||
public function map(callable $callback): Map
|
||||
{
|
||||
$mapped = new self();
|
||||
foreach ($this->pairs as $pair) {
|
||||
$mapped->put($pair->key, $callback($pair->key, $pair->value));
|
||||
}
|
||||
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequence of pairs representing all associations.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-return Sequence<Pair<TKey, TValue>>
|
||||
*/
|
||||
public function pairs(): Sequence
|
||||
{
|
||||
$copy = function($pair) {
|
||||
return $pair->copy();
|
||||
};
|
||||
|
||||
return new Vector(array_map($copy, $this->pairs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a key with a value, replacing a previous association if there
|
||||
* was one.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @psalm-param TKey $key
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function put($key, $value)
|
||||
{
|
||||
$pair = $this->lookupKey($key);
|
||||
|
||||
if ($pair) {
|
||||
$pair->value = $value;
|
||||
|
||||
} else {
|
||||
$this->checkCapacity();
|
||||
$this->pairs[] = new Pair($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates associations for all keys and corresponding values of either an
|
||||
* array or iterable object.
|
||||
*
|
||||
* @param iterable<mixed, mixed> $values
|
||||
*
|
||||
* @psalm-param iterable<TKey, TValue> $values
|
||||
*/
|
||||
public function putAll(iterable $values)
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
$this->put($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively reduces the map to a single value using a callback.
|
||||
*
|
||||
* @param callable $callback Accepts the carry, key, and value, and
|
||||
* returns an updated carry value.
|
||||
*
|
||||
* @param mixed|null $initial Optional initial carry value.
|
||||
*
|
||||
* @return mixed The carry value of the final iteration, or the initial
|
||||
* value if the map was empty.
|
||||
*
|
||||
* @template TCarry
|
||||
* @psalm-param callable(TCarry, TKey, TValue): TCarry $callback
|
||||
* @psalm-param TCarry $initial
|
||||
* @psalm-return TCarry
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null)
|
||||
{
|
||||
$carry = $initial;
|
||||
|
||||
foreach ($this->pairs as $pair) {
|
||||
$carry = $callback($carry, $pair->key, $pair->value);
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely removes a pair from the internal array by position. It is
|
||||
* important to remove it from the array and not just use 'unset'.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
private function delete(int $position)
|
||||
{
|
||||
$pair = $this->pairs[$position];
|
||||
$value = $pair->value;
|
||||
|
||||
array_splice($this->pairs, $position, 1, null);
|
||||
$this->checkCapacity();
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key's association from the map and returns the associated value
|
||||
* or a provided default if provided.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed The associated value or fallback default if provided.
|
||||
*
|
||||
* @throws \OutOfBoundsException if no default was provided and the key is
|
||||
* not associated with a value.
|
||||
*
|
||||
* @template TDefault
|
||||
* @psalm-param TKey $key
|
||||
* @psalm-param TDefault $default
|
||||
* @psalm-return TValue|TDefault
|
||||
*/
|
||||
public function remove($key, $default = null)
|
||||
{
|
||||
foreach ($this->pairs as $position => $pair) {
|
||||
if ($this->keysAreEqual($pair->key, $key)) {
|
||||
return $this->delete($position);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a default was provided
|
||||
if (func_num_args() === 1) {
|
||||
throw new \OutOfBoundsException();
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the map in-place
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
$this->pairs = array_reverse($this->pairs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reversed copy of the map.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function reversed(): Map
|
||||
{
|
||||
$reversed = new self();
|
||||
$reversed->pairs = array_reverse($this->pairs);
|
||||
|
||||
return $reversed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sub-sequence of a given length starting at a specified offset.
|
||||
*
|
||||
* @param int $offset If the offset is non-negative, the map will
|
||||
* start at that offset in the map. If offset is
|
||||
* negative, the map will start that far from the
|
||||
* end.
|
||||
*
|
||||
* @param int|null $length If a length is given and is positive, the
|
||||
* resulting set will have up to that many pairs in
|
||||
* it. If the requested length results in an
|
||||
* overflow, only pairs up to the end of the map
|
||||
* will be included.
|
||||
*
|
||||
* If a length is given and is negative, the map
|
||||
* will stop that many pairs from the end.
|
||||
*
|
||||
* If a length is not provided, the resulting map
|
||||
* will contains all pairs between the offset and
|
||||
* the end of the map.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function slice(int $offset, int $length = null): Map
|
||||
{
|
||||
$map = new self();
|
||||
|
||||
if (func_num_args() === 1) {
|
||||
$slice = array_slice($this->pairs, $offset);
|
||||
} else {
|
||||
$slice = array_slice($this->pairs, $offset, $length);
|
||||
}
|
||||
|
||||
foreach ($slice as $pair) {
|
||||
$map->put($pair->key, $pair->value);
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the map in-place, based on an optional callable comparator.
|
||||
*
|
||||
* The map will be sorted by value.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
*/
|
||||
public function sort(callable $comparator = null)
|
||||
{
|
||||
if ($comparator) {
|
||||
usort($this->pairs, function($a, $b) use ($comparator) {
|
||||
return $comparator($a->value, $b->value);
|
||||
});
|
||||
|
||||
} else {
|
||||
usort($this->pairs, function($a, $b) {
|
||||
return $a->value <=> $b->value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sorted copy of the map, based on an optional callable
|
||||
* comparator. The map will be sorted by value.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function sorted(callable $comparator = null): Map
|
||||
{
|
||||
$copy = $this->copy();
|
||||
$copy->sort($comparator);
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the map in-place, based on an optional callable comparator.
|
||||
*
|
||||
* The map will be sorted by key.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two keys to be compared.
|
||||
*
|
||||
* @psalm-param (callable(TKey, TKey): int)|null $comparator
|
||||
*/
|
||||
public function ksort(callable $comparator = null)
|
||||
{
|
||||
if ($comparator) {
|
||||
usort($this->pairs, function($a, $b) use ($comparator) {
|
||||
return $comparator($a->key, $b->key);
|
||||
});
|
||||
|
||||
} else {
|
||||
usort($this->pairs, function($a, $b) {
|
||||
return $a->key <=> $b->key;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sorted copy of the map, based on an optional callable
|
||||
* comparator. The map will be sorted by key.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two keys to be compared.
|
||||
*
|
||||
* @return Map
|
||||
*
|
||||
* @psalm-param (callable(TKey, TKey): int)|null $comparator
|
||||
* @psalm-return Map<TKey, TValue>
|
||||
*/
|
||||
public function ksorted(callable $comparator = null): Map
|
||||
{
|
||||
$copy = $this->copy();
|
||||
$copy->ksort($comparator);
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of all values in the map.
|
||||
*
|
||||
* @return int|float The sum of all the values in the map.
|
||||
*/
|
||||
public function sum()
|
||||
{
|
||||
return $this->values()->sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = [];
|
||||
|
||||
foreach ($this->pairs as $pair) {
|
||||
$array[$pair->key] = $pair->value;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequence of all the associated values in the Map.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-return Sequence<TValue>
|
||||
*/
|
||||
public function values(): Sequence
|
||||
{
|
||||
$value = function($pair) {
|
||||
return $pair->value;
|
||||
};
|
||||
|
||||
return new Vector(array_map($value, $this->pairs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map that contains the pairs of the current instance as well
|
||||
* as the pairs of another map.
|
||||
*
|
||||
* @param Map $map The other map, to combine with the current instance.
|
||||
*
|
||||
* @return Map A new map containing all the pairs of the current
|
||||
* instance as well as another map.
|
||||
*
|
||||
* @template TKey2
|
||||
* @template TValue2
|
||||
* @psalm-param Map<TKey2, TValue2> $map
|
||||
* @psalm-return Map<TKey|TKey2, TValue|TValue2>
|
||||
*/
|
||||
public function union(Map $map): Map
|
||||
{
|
||||
return $this->merge($map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map using keys of either the current instance or of another
|
||||
* map, but not of both.
|
||||
*
|
||||
* @param Map $map
|
||||
*
|
||||
* @return Map A new map containing keys in the current instance as well
|
||||
* as another map, but not in both.
|
||||
*
|
||||
* @template TKey2
|
||||
* @template TValue2
|
||||
* @psalm-param Map<TKey2, TValue2> $map
|
||||
* @psalm-return Map<TKey|TKey2, TValue|TValue2>
|
||||
*/
|
||||
public function xor(Map $map): Map
|
||||
{
|
||||
return $this->merge($map)->filter(function($key) use ($map) {
|
||||
return $this->hasKey($key) ^ $map->hasKey($key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
foreach ($this->pairs as $pair) {
|
||||
yield $pair->key => $pair->value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation to be used for var_dump and print_r.
|
||||
*
|
||||
* @psalm-return array<Pair<TKey, TValue>>
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return $this->pairs()->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->put($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function &offsetGet($offset)
|
||||
{
|
||||
$pair = $this->lookupKey($offset);
|
||||
|
||||
if ($pair) {
|
||||
return $pair->value;
|
||||
}
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->remove($offset, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->get($offset, null) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation that can be natively converted to JSON, which is
|
||||
* called when invoking json_encode.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @see \JsonSerializable
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return (object) $this->toArray();
|
||||
}
|
||||
}
|
||||
158
src/Label/vendor/php-ds/php-ds/src/Pair.php
vendored
Normal file
158
src/Label/vendor/php-ds/php-ds/src/Pair.php
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use OutOfBoundsException;
|
||||
|
||||
/**
|
||||
* A pair which represents a key and an associated value.
|
||||
*
|
||||
* @property mixed $key
|
||||
* @property mixed $value
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template-covariant TKey
|
||||
* @template-covariant TValue
|
||||
*/
|
||||
final class Pair implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var mixed The pair's key
|
||||
*
|
||||
* @psalm-param TKey $key
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* @var mixed The pair's value
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @psalm-param TKey $key
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function __construct($key = null, $value = null)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $name
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
if ($name === 'key' || $name === 'value') {
|
||||
return $this->$name !== null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows unset($pair->key) to not completely remove the property,
|
||||
* but be set to null instead.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __unset(string $name)
|
||||
{
|
||||
if ($name === 'key' || $name === 'value') {
|
||||
$this->$name = null;
|
||||
return;
|
||||
}
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $name
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function &__get($name)
|
||||
{
|
||||
if ($name === 'key' || $name === 'value') {
|
||||
return $this->$name;
|
||||
}
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if ($name === 'key' || $name === 'value') {
|
||||
$this->$name = $value;
|
||||
return;
|
||||
}
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the Pair
|
||||
*
|
||||
* @psalm-return self<TKey, TValue>
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return new self($this->key, $this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation to be used for var_dump and print_r.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @psalm-return array{key: TKey, value: TValue}
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @psalm-return array{key: TKey, value: TValue}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'key' => $this->key,
|
||||
'value' => $this->value,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @psalm-return array{key: TKey, value: TValue}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the pair.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return 'object(' . get_class($this) . ')';
|
||||
}
|
||||
}
|
||||
340
src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php
vendored
Normal file
340
src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use UnderflowException;
|
||||
|
||||
/**
|
||||
* A PriorityQueue is very similar to a Queue. Values are pushed into the queue
|
||||
* with an assigned priority, and the value with the highest priority will
|
||||
* always be at the front of the queue.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Collection<int, TValue>
|
||||
*/
|
||||
final class PriorityQueue implements Collection
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
use Traits\SquaredCapacity;
|
||||
|
||||
public const MIN_CAPACITY = 8;
|
||||
|
||||
/**
|
||||
* @var array<int, PriorityNode<TValue>>
|
||||
*/
|
||||
private $heap = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $stamp = 0;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->heap = [];
|
||||
$this->stamp = 0;
|
||||
$this->capacity = self::MIN_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
$copy = new PriorityQueue();
|
||||
|
||||
$copy->heap = $this->heap;
|
||||
$copy->stamp = $this->stamp;
|
||||
$copy->capacity = $this->capacity;
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->heap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value with the highest priority in the priority queue.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throw UnderflowException
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
return $this->heap[0]->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of a node's left leaf.
|
||||
*
|
||||
* @param int $index The index of the node.
|
||||
*
|
||||
* @return int The index of the left leaf.
|
||||
*/
|
||||
private function left(int $index): int
|
||||
{
|
||||
return ($index * 2) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of a node's right leaf.
|
||||
*
|
||||
* @param int $index The index of the node.
|
||||
*
|
||||
* @return int The index of the right leaf.
|
||||
*/
|
||||
private function right(int $index): int
|
||||
{
|
||||
return ($index * 2) + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of a node's parent node.
|
||||
*
|
||||
* @param int $index The index of the node.
|
||||
*
|
||||
* @return int The index of the parent.
|
||||
*/
|
||||
private function parent(int $index): int
|
||||
{
|
||||
return (int) (($index - 1) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two indices of the heap.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function compare(int $a, int $b)
|
||||
{
|
||||
$x = $this->heap[$a];
|
||||
$y = $this->heap[$b];
|
||||
|
||||
// Compare priority, using insertion stamp as fallback.
|
||||
return ($x->priority <=> $y->priority) ?: ($y->stamp <=> $x->stamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the nodes at two indices of the heap.
|
||||
*/
|
||||
private function swap(int $a, int $b)
|
||||
{
|
||||
$temp = $this->heap[$a];
|
||||
$this->heap[$a] = $this->heap[$b];
|
||||
$this->heap[$b] = $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of a node's largest leaf node.
|
||||
*
|
||||
* @param int $parent the parent node.
|
||||
*
|
||||
* @return int the index of the node's largest leaf node.
|
||||
*/
|
||||
private function getLargestLeaf(int $parent)
|
||||
{
|
||||
$left = $this->left($parent);
|
||||
$right = $this->right($parent);
|
||||
|
||||
if ($right < count($this->heap) && $this->compare($left, $right) < 0) {
|
||||
return $right;
|
||||
}
|
||||
|
||||
return $left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the process of sifting down a given node index to ensure that
|
||||
* the heap's properties are preserved.
|
||||
*/
|
||||
private function siftDown(int $node)
|
||||
{
|
||||
$last = floor(count($this->heap) / 2);
|
||||
|
||||
for ($parent = $node; $parent < $last; $parent = $leaf) {
|
||||
|
||||
// Determine the largest leaf to potentially swap with the parent.
|
||||
$leaf = $this->getLargestLeaf($parent);
|
||||
|
||||
// Done if the parent is not greater than its largest leaf
|
||||
if ($this->compare($parent, $leaf) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->swap($parent, $leaf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root node and sifts it down the heap.
|
||||
*
|
||||
* @param PriorityNode $node
|
||||
*/
|
||||
private function setRoot(PriorityNode $node)
|
||||
{
|
||||
$this->heap[0] = $node;
|
||||
$this->siftDown(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root node of the heap.
|
||||
*
|
||||
* @return PriorityNode
|
||||
*/
|
||||
private function getRoot(): PriorityNode
|
||||
{
|
||||
return $this->heap[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and removes the value with the highest priority in the queue.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
// Last leaf of the heap to become the new root.
|
||||
$leaf = array_pop($this->heap);
|
||||
|
||||
if (empty($this->heap)) {
|
||||
return $leaf->value;
|
||||
}
|
||||
|
||||
// Cache the current root value to return before replacing with next.
|
||||
$value = $this->getRoot()->value;
|
||||
|
||||
// Replace the root, then sift down.
|
||||
$this->setRoot($leaf);
|
||||
$this->checkCapacity();
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sifts a node up the heap until it's in the right position.
|
||||
*/
|
||||
private function siftUp(int $leaf)
|
||||
{
|
||||
for (; $leaf > 0; $leaf = $parent) {
|
||||
$parent = $this->parent($leaf);
|
||||
|
||||
// Done when parent priority is greater.
|
||||
if ($this->compare($leaf, $parent) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$this->swap($parent, $leaf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a value into the queue, with a specified priority.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function push($value, int $priority)
|
||||
{
|
||||
$this->checkCapacity();
|
||||
|
||||
// Add new leaf, then sift up to maintain heap,
|
||||
$this->heap[] = new PriorityNode($value, $priority, $this->stamp++);
|
||||
$this->siftUp(count($this->heap) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$heap = $this->heap;
|
||||
$array = [];
|
||||
|
||||
while ( ! $this->isEmpty()) {
|
||||
$array[] = $this->pop();
|
||||
}
|
||||
|
||||
$this->heap = $heap;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
while ( ! $this->isEmpty()) {
|
||||
yield $this->pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @template TValue
|
||||
*/
|
||||
final class PriorityNode
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*
|
||||
* @psalm-var TValue
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $priority;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $stamp;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param int $priority
|
||||
* @param int $stamp
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function __construct($value, int $priority, int $stamp)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->priority = $priority;
|
||||
$this->stamp = $stamp;
|
||||
}
|
||||
}
|
||||
195
src/Label/vendor/php-ds/php-ds/src/Queue.php
vendored
Normal file
195
src/Label/vendor/php-ds/php-ds/src/Queue.php
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use Error;
|
||||
use OutOfBoundsException;
|
||||
|
||||
/**
|
||||
* A “first in, first out” or “FIFO” collection that only allows access to the
|
||||
* value at the front of the queue and iterates in that order, destructively.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Collection<int, TValue>
|
||||
*/
|
||||
final class Queue implements Collection, \ArrayAccess
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
|
||||
/**
|
||||
* @var Deque internal deque to store values.
|
||||
*
|
||||
* @psalm-var Deque<TValue>
|
||||
*/
|
||||
private $deque;
|
||||
|
||||
/**
|
||||
* Creates an instance using the values of an array or Traversable object.
|
||||
*
|
||||
* @param iterable<mixed> $values
|
||||
*
|
||||
* @psalm-param iterable<TValue> $values
|
||||
*/
|
||||
public function __construct(iterable $values = [])
|
||||
{
|
||||
$this->deque = new Deque($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a specified capacity. This
|
||||
* potentially reduces the number of reallocations as the size increases.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity)
|
||||
{
|
||||
$this->deque->allocate($capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the queue.
|
||||
*/
|
||||
public function capacity(): int
|
||||
{
|
||||
return $this->deque->capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->deque->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return new self($this->deque);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->deque);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the front of the queue without removing it.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
return $this->deque->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and removes the value at the front of the Queue.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
return $this->deque->shift();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes zero or more values into the back of the queue.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function push(...$values)
|
||||
{
|
||||
$this->deque->push(...$values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->deque->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iterator
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
while ( ! $this->isEmpty()) {
|
||||
yield $this->pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->push($value);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the internal sequence will be cloned too.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->deque = clone $this->deque;
|
||||
}
|
||||
}
|
||||
330
src/Label/vendor/php-ds/php-ds/src/Sequence.php
vendored
Normal file
330
src/Label/vendor/php-ds/php-ds/src/Sequence.php
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
/**
|
||||
* Describes the behaviour of values arranged in a single, linear dimension.
|
||||
* Some languages refer to this as a "List". It’s similar to an array that uses
|
||||
* incremental integer keys, with the exception of a few characteristics:
|
||||
*
|
||||
* - Values will always be indexed as [0, 1, 2, …, size - 1].
|
||||
* - Only allowed to access values by index in the range [0, size - 1].
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @extends Collection<int, TValue>
|
||||
*/
|
||||
interface Sequence extends Collection, \ArrayAccess
|
||||
{
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a required capacity.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity);
|
||||
|
||||
/**
|
||||
* Updates every value in the sequence by applying a callback, using the
|
||||
* return value as the new value.
|
||||
*
|
||||
* @param callable $callback Accepts the value, returns the new value.
|
||||
*
|
||||
* @psalm-param callable(TValue): TValue $callback
|
||||
*/
|
||||
public function apply(callable $callback);
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the sequence.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function capacity(): int;
|
||||
|
||||
/**
|
||||
* Determines whether the sequence contains all of zero or more values.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @return bool true if at least one value was provided and the sequence
|
||||
* contains all given values, false otherwise.
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function contains(...$values): bool;
|
||||
|
||||
/**
|
||||
* Returns a new sequence containing only the values for which a callback
|
||||
* returns true. A boolean test will be used if a callback is not provided.
|
||||
*
|
||||
* @param callable|null $callback Accepts a value, returns a boolean result:
|
||||
* true : include the value,
|
||||
* false: skip the value.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-param (callable(TValue): bool)|null $callback
|
||||
* @psalm-return Sequence<TValue>
|
||||
*/
|
||||
public function filter(callable $callback = null): Sequence;
|
||||
|
||||
/**
|
||||
* Returns the index of a given value, or null if it could not be found.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return int|null
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function find($value);
|
||||
|
||||
/**
|
||||
* Returns the first value in the sequence.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \UnderflowException if the sequence is empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function first();
|
||||
|
||||
/**
|
||||
* Returns the value at a given index (position) in the sequence.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \OutOfRangeException if the index is not in the range [0, size-1]
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function get(int $index);
|
||||
|
||||
/**
|
||||
* Inserts zero or more values at a given index.
|
||||
*
|
||||
* Each value after the index will be moved one position to the right.
|
||||
* Values may be inserted at an index equal to the size of the sequence.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @throws \OutOfRangeException if the index is not in the range [0, n]
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function insert(int $index, ...$values);
|
||||
|
||||
/**
|
||||
* Joins all values of the sequence into a string, adding an optional 'glue'
|
||||
* between them. Returns an empty string if the sequence is empty.
|
||||
*/
|
||||
public function join(string $glue = null): string;
|
||||
|
||||
/**
|
||||
* Returns the last value in the sequence.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \UnderflowException if the sequence is empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function last();
|
||||
|
||||
/**
|
||||
* Returns a new sequence using the results of applying a callback to each
|
||||
* value.
|
||||
*
|
||||
* @param callable $callback
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @template TNewValue
|
||||
* @psalm-param callable(TValue): TNewValue $callback
|
||||
* @psalm-return Sequence<TNewValue>
|
||||
*/
|
||||
public function map(callable $callback): Sequence;
|
||||
|
||||
/**
|
||||
* Returns the result of adding all given values to the sequence.
|
||||
*
|
||||
* @param array|\Traversable $values
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param iterable<TValue2> $values
|
||||
* @psalm-return Sequence<TValue|TValue2>
|
||||
*/
|
||||
public function merge($values): Sequence;
|
||||
|
||||
/**
|
||||
* Removes the last value in the sequence, and returns it.
|
||||
*
|
||||
* @return mixed what was the last value in the sequence.
|
||||
*
|
||||
* @throws \UnderflowException if the sequence is empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function pop();
|
||||
|
||||
/**
|
||||
* Adds zero or more values to the end of the sequence.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function push(...$values);
|
||||
|
||||
/**
|
||||
* Iteratively reduces the sequence to a single value using a callback.
|
||||
*
|
||||
* @param callable $callback Accepts the carry and current value, and
|
||||
* returns an updated carry value.
|
||||
*
|
||||
* @param mixed|null $initial Optional initial carry value.
|
||||
*
|
||||
* @return mixed The carry value of the final iteration, or the initial
|
||||
* value if the sequence was empty.
|
||||
*
|
||||
* @template TCarry
|
||||
* @psalm-param callable(TCarry, TValue): TCarry $callback
|
||||
* @psalm-param TCarry $initial
|
||||
* @psalm-return TCarry
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null);
|
||||
|
||||
/**
|
||||
* Removes and returns the value at a given index in the sequence.
|
||||
*
|
||||
* @param int $index this index to remove.
|
||||
*
|
||||
* @return mixed the removed value.
|
||||
*
|
||||
* @throws \OutOfRangeException if the index is not in the range [0, size-1]
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function remove(int $index);
|
||||
|
||||
/**
|
||||
* Reverses the sequence in-place.
|
||||
*/
|
||||
public function reverse();
|
||||
|
||||
/**
|
||||
* Returns a reversed copy of the sequence.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-return Sequence<TValue>
|
||||
*/
|
||||
public function reversed();
|
||||
|
||||
/**
|
||||
* Rotates the sequence by a given number of rotations, which is equivalent
|
||||
* to successive calls to 'shift' and 'push' if the number of rotations is
|
||||
* positive, or 'pop' and 'unshift' if negative.
|
||||
*
|
||||
* @param int $rotations The number of rotations (can be negative).
|
||||
*/
|
||||
public function rotate(int $rotations);
|
||||
|
||||
/**
|
||||
* Replaces the value at a given index in the sequence with a new value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws \OutOfRangeException if the index is not in the range [0, size-1]
|
||||
*
|
||||
* @psalm-param TValue $value
|
||||
*/
|
||||
public function set(int $index, $value);
|
||||
|
||||
/**
|
||||
* Removes and returns the first value in the sequence.
|
||||
*
|
||||
* @return mixed what was the first value in the sequence.
|
||||
*
|
||||
* @throws \UnderflowException if the sequence was empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function shift();
|
||||
|
||||
/**
|
||||
* Returns a sub-sequence of a given length starting at a specified index.
|
||||
*
|
||||
* @param int $index If the index is positive, the sequence will start
|
||||
* at that index in the sequence. If index is negative,
|
||||
* the sequence will start that far from the end.
|
||||
*
|
||||
* @param int $length If a length is given and is positive, the resulting
|
||||
* sequence will have up to that many values in it.
|
||||
* If the length results in an overflow, only values
|
||||
* up to the end of the sequence will be included.
|
||||
*
|
||||
* If a length is given and is negative, the sequence
|
||||
* will stop that many values from the end.
|
||||
*
|
||||
* If a length is not provided, the resulting sequence
|
||||
* will contain all values between the index and the
|
||||
* end of the sequence.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-return Sequence<TValue>
|
||||
*/
|
||||
public function slice(int $index, int $length = null): Sequence;
|
||||
|
||||
/**
|
||||
* Sorts the sequence in-place, based on an optional callable comparator.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
* Should return the result of a <=> b.
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
*/
|
||||
public function sort(callable $comparator = null);
|
||||
|
||||
/**
|
||||
* Returns a sorted copy of the sequence, based on an optional callable
|
||||
* comparator. Natural ordering will be used if a comparator is not given.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
* Should return the result of a <=> b.
|
||||
*
|
||||
* @return Sequence
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
* @psalm-return Sequence<TValue>
|
||||
*/
|
||||
public function sorted(callable $comparator = null): Sequence;
|
||||
|
||||
/**
|
||||
* Returns the sum of all values in the sequence.
|
||||
*
|
||||
* @return int|float The sum of all the values in the sequence.
|
||||
*/
|
||||
public function sum();
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @return list<TValue>
|
||||
*/
|
||||
function toArray(): array;
|
||||
|
||||
/**
|
||||
* Adds zero or more values to the front of the sequence.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function unshift(...$values);
|
||||
}
|
||||
538
src/Label/vendor/php-ds/php-ds/src/Set.php
vendored
Normal file
538
src/Label/vendor/php-ds/php-ds/src/Set.php
vendored
Normal file
@@ -0,0 +1,538 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use Error;
|
||||
use OutOfBoundsException;
|
||||
use OutOfRangeException;
|
||||
|
||||
/**
|
||||
* A sequence of unique values.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Collection<int, TValue>
|
||||
*/
|
||||
final class Set implements Collection, \ArrayAccess
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
|
||||
public const MIN_CAPACITY = Map::MIN_CAPACITY;
|
||||
|
||||
/**
|
||||
* @var Map internal map to store the values.
|
||||
*
|
||||
* @psalm-var Map<int, TValue>
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* Creates a new set using the values of an array or Traversable object.
|
||||
* The keys of either will not be preserved.
|
||||
*
|
||||
* @param iterable $values
|
||||
*
|
||||
* @psalm-param iterable<TValue> $values
|
||||
*/
|
||||
public function __construct(iterable $values = [])
|
||||
{
|
||||
$this->table = new Map();
|
||||
|
||||
foreach ($values as $value) {
|
||||
$this->add($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds zero or more values to the set.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function add(...$values)
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->table->put($value, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a specified capacity. This
|
||||
* potentially reduces the number of reallocations as the size increases.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity)
|
||||
{
|
||||
$this->table->allocate($capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the set.
|
||||
*/
|
||||
public function capacity(): int
|
||||
{
|
||||
return $this->table->capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all elements in the Set
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->table->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the set contains all of zero or more values.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @return bool true if at least one value was provided and the set
|
||||
* contains all given values, false otherwise.
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function contains(...$values): bool
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
if ( ! $this->table->hasKey($value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return new self($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the Stack
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set using values from this set that aren't in another set.
|
||||
*
|
||||
* Formally: A \ B = {x ∈ A | x ∉ B}
|
||||
*
|
||||
* @param Set $set
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param Set<TValue2> $set
|
||||
* @psalm-return Set<TValue>
|
||||
*/
|
||||
public function diff(Set $set): Set
|
||||
{
|
||||
return $this->table->diff($set->table)->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set using values in either this set or in another set,
|
||||
* but not in both.
|
||||
*
|
||||
* Formally: A ⊖ B = {x : x ∈ (A \ B) ∪ (B \ A)}
|
||||
*
|
||||
* @param Set $set
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param Set<TValue2> $set
|
||||
* @psalm-return Set<TValue|TValue2>
|
||||
*/
|
||||
public function xor(Set $set): Set
|
||||
{
|
||||
return $this->table->xor($set->table)->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new set containing only the values for which a callback
|
||||
* returns true. A boolean test will be used if a callback is not provided.
|
||||
*
|
||||
* @param callable|null $callback Accepts a value, returns a boolean:
|
||||
* true : include the value,
|
||||
* false: skip the value.
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @psalm-param (callable(TValue): bool)|null $callback
|
||||
* @psalm-return Set<TValue>
|
||||
*/
|
||||
public function filter(callable $callback = null): Set
|
||||
{
|
||||
return new self(array_filter($this->toArray(), $callback ?: 'boolval'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value in the set.
|
||||
*
|
||||
* @return mixed the first value in the set.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
return $this->table->first()->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at a specified position in the set.
|
||||
*
|
||||
* @return mixed|null
|
||||
*
|
||||
* @throws OutOfRangeException
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function get(int $position)
|
||||
{
|
||||
return $this->table->skip($position)->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set using values common to both this set and another set.
|
||||
*
|
||||
* In other words, returns a copy of this set with all values removed that
|
||||
* aren't in the other set.
|
||||
*
|
||||
* Formally: A ∩ B = {x : x ∈ A ∧ x ∈ B}
|
||||
*
|
||||
* @param Set $set
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param Set<TValue2> $set
|
||||
* @psalm-return Set<TValue&TValue2>
|
||||
*/
|
||||
public function intersect(Set $set): Set
|
||||
{
|
||||
return $this->table->intersect($set->table)->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->table->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins all values of the set into a string, adding an optional 'glue'
|
||||
* between them. Returns an empty string if the set is empty.
|
||||
*
|
||||
* @param string|null $glue
|
||||
*/
|
||||
public function join(string $glue = null): string
|
||||
{
|
||||
return implode($glue ?? '', $this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last value in the set.
|
||||
*
|
||||
* @return mixed the last value in the set.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function last()
|
||||
{
|
||||
return $this->table->last()->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new set using the results of applying a callback to each
|
||||
* value.
|
||||
*
|
||||
* @param callable $callback
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TNewValue
|
||||
* @psalm-param callable(TValue): TNewValue $callback
|
||||
* @psalm-return Set<TNewValue>
|
||||
*/
|
||||
public function map(callable $callback) {
|
||||
return new self(array_map($callback, $this->toArray()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively reduces the set to a single value using a callback.
|
||||
*
|
||||
* @param callable $callback Accepts the carry and current value, and
|
||||
* returns an updated carry value.
|
||||
*
|
||||
* @param mixed|null $initial Optional initial carry value.
|
||||
*
|
||||
* @return mixed The carry value of the final iteration, or the initial
|
||||
* value if the set was empty.
|
||||
*
|
||||
* @template TCarry
|
||||
* @psalm-param callable(TCarry, TValue): TCarry $callback
|
||||
* @psalm-param TCarry $initial
|
||||
* @psalm-return TCarry
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null)
|
||||
{
|
||||
$carry = $initial;
|
||||
|
||||
foreach ($this as $value) {
|
||||
$carry = $callback($carry, $value);
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes zero or more values from the set.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function remove(...$values)
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->table->remove($value, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the set in-place.
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
$this->table->reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reversed copy of the set.
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @psalm-return Set<TValue>
|
||||
*/
|
||||
public function reversed(): Set
|
||||
{
|
||||
$reversed = $this->copy();
|
||||
$reversed->table->reverse();
|
||||
|
||||
return $reversed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a subset of a given length starting at a specified offset.
|
||||
*
|
||||
* @param int $offset If the offset is non-negative, the set will start
|
||||
* at that offset in the set. If offset is negative,
|
||||
* the set will start that far from the end.
|
||||
*
|
||||
* @param int $length If a length is given and is positive, the resulting
|
||||
* set will have up to that many values in it.
|
||||
* If the requested length results in an overflow, only
|
||||
* values up to the end of the set will be included.
|
||||
*
|
||||
* If a length is given and is negative, the set
|
||||
* will stop that many values from the end.
|
||||
*
|
||||
* If a length is not provided, the resulting set
|
||||
* will contains all values between the offset and the
|
||||
* end of the set.
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @psalm-return Set<TValue>
|
||||
*/
|
||||
public function slice(int $offset, int $length = null): Set
|
||||
{
|
||||
$sliced = new self();
|
||||
$sliced->table = $this->table->slice($offset, $length);
|
||||
|
||||
return $sliced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the set in-place, based on an optional callable comparator.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
* Should return the result of a <=> b.
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
*/
|
||||
public function sort(callable $comparator = null)
|
||||
{
|
||||
$this->table->ksort($comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sorted copy of the set, based on an optional callable
|
||||
* comparator. Natural ordering will be used if a comparator is not given.
|
||||
*
|
||||
* @param callable|null $comparator Accepts two values to be compared.
|
||||
* Should return the result of a <=> b.
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @psalm-param (callable(TValue, TValue): int)|null $comparator
|
||||
* @psalm-return Set<TValue>
|
||||
*/
|
||||
public function sorted(callable $comparator = null): Set
|
||||
{
|
||||
$sorted = $this->copy();
|
||||
$sorted->table->ksort($comparator);
|
||||
|
||||
return $sorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of adding all given values to the set.
|
||||
*
|
||||
* @param array|\Traversable $values
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param iterable<TValue2> $values
|
||||
* @psalm-return Set<TValue|TValue2>
|
||||
*/
|
||||
public function merge($values): Set
|
||||
{
|
||||
$merged = $this->copy();
|
||||
|
||||
foreach ($values as $value) {
|
||||
$merged->add($value);
|
||||
}
|
||||
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return iterator_to_array($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of all values in the set.
|
||||
*
|
||||
* @return int|float The sum of all the values in the set.
|
||||
*/
|
||||
public function sum()
|
||||
{
|
||||
return array_sum($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set that contains the values of this set as well as the
|
||||
* values of another set.
|
||||
*
|
||||
* Formally: A ∪ B = {x: x ∈ A ∨ x ∈ B}
|
||||
*
|
||||
* @param Set $set
|
||||
*
|
||||
* @return Set
|
||||
*
|
||||
* @template TValue2
|
||||
* @psalm-param Set<TValue2> $set
|
||||
* @psalm-return Set<TValue|TValue2>
|
||||
*/
|
||||
public function union(Set $set): Set
|
||||
{
|
||||
$union = new self();
|
||||
|
||||
foreach ($this as $value) {
|
||||
$union->add($value);
|
||||
}
|
||||
|
||||
foreach ($set as $value) {
|
||||
$union->add($value);
|
||||
}
|
||||
|
||||
return $union;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iterator
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
foreach ($this->table as $key => $value) {
|
||||
yield $key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->add($value);
|
||||
return;
|
||||
}
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->table->skip($offset)->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the internal table will be cloned too.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->table = clone $this->table;
|
||||
}
|
||||
}
|
||||
198
src/Label/vendor/php-ds/php-ds/src/Stack.php
vendored
Normal file
198
src/Label/vendor/php-ds/php-ds/src/Stack.php
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
use Error;
|
||||
use OutOfBoundsException;
|
||||
|
||||
/**
|
||||
* A “last in, first out” or “LIFO” collection that only allows access to the
|
||||
* value at the top of the structure and iterates in that order, destructively.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Sequence<TValue>
|
||||
*/
|
||||
final class Stack implements Collection, \ArrayAccess
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
|
||||
/**
|
||||
* @var Vector internal vector to store values of the stack.
|
||||
*
|
||||
* @psalm-var Vector<TValue>
|
||||
*/
|
||||
private $vector;
|
||||
|
||||
/**
|
||||
* Creates an instance using the values of an array or Traversable object.
|
||||
*
|
||||
* @param iterable<mixed> $values
|
||||
*
|
||||
* @psalm-param iterable<TValue> $values
|
||||
*/
|
||||
public function __construct(iterable $values = [])
|
||||
{
|
||||
$this->vector = new Vector($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all elements in the Stack
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->vector->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return new self($this->vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the Stack
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a specified capacity. This
|
||||
* potentially reduces the number of reallocations as the size increases.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity)
|
||||
{
|
||||
$this->vector->allocate($capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current capacity of the stack.
|
||||
*/
|
||||
public function capacity(): int
|
||||
{
|
||||
return $this->vector->capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the top of the stack without removing it.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \UnderflowException if the stack is empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
return $this->vector->last();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and removes the value at the top of the stack.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \UnderflowException if the stack is empty.
|
||||
*
|
||||
* @psalm-return TValue
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
return $this->vector->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes zero or more values onto the top of the stack.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*
|
||||
* @psalm-param TValue ...$values
|
||||
*/
|
||||
public function push(...$values)
|
||||
{
|
||||
$this->vector->push(...$values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_reverse($this->vector->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
while ( ! $this->isEmpty()) {
|
||||
yield $this->pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->push($value);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the internal vector will be cloned too.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->vector = clone $this->vector;
|
||||
}
|
||||
}
|
||||
130
src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php
vendored
Normal file
130
src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace Ds\Traits;
|
||||
|
||||
use Ds\Deque;
|
||||
|
||||
/**
|
||||
* Common to structures that deal with an internal capacity. While none of the
|
||||
* PHP implementations actually make use of a capacity, it's important to keep
|
||||
* consistent with the extension.
|
||||
*/
|
||||
trait Capacity
|
||||
{
|
||||
/**
|
||||
* @var int internal capacity
|
||||
*/
|
||||
private $capacity = self::MIN_CAPACITY;
|
||||
|
||||
/**
|
||||
* Returns the current capacity.
|
||||
*/
|
||||
public function capacity(): int
|
||||
{
|
||||
return $this->capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a specified capacity. This
|
||||
* potentially reduces the number of reallocations as the size increases.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity)
|
||||
{
|
||||
$this->capacity = max($capacity, $this->capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float the structures growth factor.
|
||||
*/
|
||||
protected function getGrowthFactor(): float
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float to multiply by when decreasing capacity.
|
||||
*/
|
||||
protected function getDecayFactor(): float
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float the ratio between size and capacity when capacity should be
|
||||
* decreased.
|
||||
*/
|
||||
protected function getTruncateThreshold(): float
|
||||
{
|
||||
return 0.25;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and adjusts capacity if required.
|
||||
*/
|
||||
protected function checkCapacity()
|
||||
{
|
||||
if ($this->shouldIncreaseCapacity()) {
|
||||
$this->increaseCapacity();
|
||||
} else {
|
||||
if ($this->shouldDecreaseCapacity()) {
|
||||
$this->decreaseCapacity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $total
|
||||
*/
|
||||
protected function ensureCapacity(int $total)
|
||||
{
|
||||
if ($total > $this->capacity()) {
|
||||
$this->capacity = max($total, $this->nextCapacity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether capacity should be increased.
|
||||
*/
|
||||
protected function shouldIncreaseCapacity(): bool
|
||||
{
|
||||
return $this->count() >= $this->capacity();
|
||||
}
|
||||
|
||||
protected function nextCapacity(): int
|
||||
{
|
||||
return (int) ($this->capacity() * $this->getGrowthFactor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when capacity should be increased to accommodate new values.
|
||||
*/
|
||||
protected function increaseCapacity()
|
||||
{
|
||||
$this->capacity = max(
|
||||
$this->count(),
|
||||
$this->nextCapacity()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when capacity should be decrease if it drops below a threshold.
|
||||
*/
|
||||
protected function decreaseCapacity()
|
||||
{
|
||||
$this->capacity = max(
|
||||
self::MIN_CAPACITY,
|
||||
(int) ($this->capacity() * $this->getDecayFactor())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether capacity should be increased.
|
||||
*/
|
||||
protected function shouldDecreaseCapacity(): bool
|
||||
{
|
||||
return count($this) <= $this->capacity() * $this->getTruncateThreshold();
|
||||
}
|
||||
}
|
||||
75
src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php
vendored
Normal file
75
src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
namespace Ds\Traits;
|
||||
|
||||
/**
|
||||
* Common to structures that implement the base collection interface.
|
||||
*/
|
||||
trait GenericCollection
|
||||
{
|
||||
/**
|
||||
* Returns whether the collection is empty.
|
||||
*
|
||||
* This should be equivalent to a count of zero, but is not required.
|
||||
* Implementations should define what empty means in their own context.
|
||||
*
|
||||
* @return bool whether the collection is empty.
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return count($this) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation that can be natively converted to JSON, which is
|
||||
* called when invoking json_encode.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @see \JsonSerializable
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shallow copy of the collection.
|
||||
*
|
||||
* @return static a shallow copy of the collection.
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return new static($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the collection.
|
||||
*
|
||||
* The format of the returned array is implementation-dependent. Some
|
||||
* implementations may throw an exception if an array representation
|
||||
* could not be created (for example when object are used as keys).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function toArray(): array;
|
||||
|
||||
/**
|
||||
* Invoked when calling var_dump.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the collection, which is invoked when
|
||||
* the collection is converted to a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return 'object(' . get_class($this) . ')';
|
||||
}
|
||||
}
|
||||
419
src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php
vendored
Normal file
419
src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
<?php
|
||||
namespace Ds\Traits;
|
||||
|
||||
use Ds\Sequence;
|
||||
use OutOfRangeException;
|
||||
use UnderflowException;
|
||||
|
||||
/**
|
||||
* Common functionality of all structures that implement 'Sequence'. Because the
|
||||
* polyfill's only goal is to achieve consistent behaviour, all sequences will
|
||||
* share the same implementation using an array array.
|
||||
*
|
||||
* @package Ds\Traits
|
||||
*/
|
||||
trait GenericSequence
|
||||
{
|
||||
/**
|
||||
* @var array internal array used to store the values of the sequence.
|
||||
*
|
||||
* @psalm-var array<TValue>
|
||||
*/
|
||||
private $array = [];
|
||||
|
||||
/**
|
||||
* @param iterable $values
|
||||
*
|
||||
* @psalm-param iterable<TValue> $values
|
||||
*/
|
||||
public function __construct(iterable $values = [])
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->push($value);
|
||||
}
|
||||
|
||||
$this->capacity = max(
|
||||
$values === null ? 0 : count($values),
|
||||
$this::MIN_CAPACITY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function apply(callable $callback)
|
||||
{
|
||||
foreach ($this->array as &$value) {
|
||||
$value = $callback($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function merge($values): Sequence
|
||||
{
|
||||
$copy = $this->copy();
|
||||
$copy->push(...$values);
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function contains(...$values): bool
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
if ($this->find($value) === null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function filter(callable $callback = null): Sequence
|
||||
{
|
||||
return new self(array_filter($this->array, $callback ?: 'boolval'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function find($value)
|
||||
{
|
||||
$offset = array_search($value, $this->array, true);
|
||||
|
||||
return $offset === false ? null : $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
return $this->array[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get(int $index)
|
||||
{
|
||||
if ( ! $this->validIndex($index)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
return $this->array[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function insert(int $index, ...$values)
|
||||
{
|
||||
if ( ! $this->validIndex($index) && $index !== count($this)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
array_splice($this->array, $index, 0, $values);
|
||||
$this->checkCapacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function join(string $glue = null): string
|
||||
{
|
||||
return implode($glue ?? '', $this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function last()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
return $this->array[count($this) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function map(callable $callback): Sequence
|
||||
{
|
||||
return new self(array_map($callback, $this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
$value = array_pop($this->array);
|
||||
$this->checkCapacity();
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function push(...$values)
|
||||
{
|
||||
$this->ensureCapacity($this->count() + count($values));
|
||||
|
||||
foreach ($values as $value) {
|
||||
$this->array[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null)
|
||||
{
|
||||
return array_reduce($this->array, $callback, $initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function remove(int $index)
|
||||
{
|
||||
if ( ! $this->validIndex($index)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
$value = array_splice($this->array, $index, 1, null)[0];
|
||||
$this->checkCapacity();
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
$this->array = array_reverse($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function reversed(): Sequence
|
||||
{
|
||||
return new self(array_reverse($this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts negative or large rotations into the minimum positive number
|
||||
* of rotations required to rotate the sequence by a given $r.
|
||||
*/
|
||||
private function normalizeRotations(int $r)
|
||||
{
|
||||
$n = count($this);
|
||||
|
||||
if ($n < 2) return 0;
|
||||
if ($r < 0) return $n - (abs($r) % $n);
|
||||
|
||||
return $r % $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function rotate(int $rotations)
|
||||
{
|
||||
for ($r = $this->normalizeRotations($rotations); $r > 0; $r--) {
|
||||
array_push($this->array, array_shift($this->array));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function set(int $index, $value)
|
||||
{
|
||||
if ( ! $this->validIndex($index)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
$this->array[$index] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function shift()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new UnderflowException();
|
||||
}
|
||||
|
||||
$value = array_shift($this->array);
|
||||
$this->checkCapacity();
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function slice(int $offset, int $length = null): Sequence
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
$length = count($this);
|
||||
}
|
||||
|
||||
return new self(array_slice($this->array, $offset, $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function sort(callable $comparator = null)
|
||||
{
|
||||
if ($comparator) {
|
||||
usort($this->array, $comparator);
|
||||
} else {
|
||||
sort($this->array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function sorted(callable $comparator = null): Sequence
|
||||
{
|
||||
$copy = $this->copy();
|
||||
$copy->sort($comparator);
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function sum()
|
||||
{
|
||||
return array_sum($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function unshift(...$values)
|
||||
{
|
||||
if ($values) {
|
||||
$this->array = array_merge($values, $this->array);
|
||||
$this->checkCapacity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function validIndex(int $index)
|
||||
{
|
||||
return $index >= 0 && $index < count($this);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
foreach ($this->array as $value) {
|
||||
yield $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->array = [];
|
||||
$this->capacity = self::MIN_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->push($value);
|
||||
} else {
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function &offsetGet($offset)
|
||||
{
|
||||
if ( ! $this->validIndex($offset)) {
|
||||
throw new OutOfRangeException();
|
||||
}
|
||||
|
||||
return $this->array[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if (is_integer($offset) && $this->validIndex($offset)) {
|
||||
$this->remove($offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return is_integer($offset)
|
||||
&& $this->validIndex($offset)
|
||||
&& $this->get($offset) !== null;
|
||||
}
|
||||
}
|
||||
58
src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php
vendored
Normal file
58
src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace Ds\Traits;
|
||||
|
||||
/**
|
||||
* Common to structures that require a capacity which is a power of two.
|
||||
*/
|
||||
trait SquaredCapacity
|
||||
{
|
||||
use Capacity;
|
||||
|
||||
/**
|
||||
* Rounds an integer to the next power of two if not already a power of two.
|
||||
*
|
||||
* @param int $capacity
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function square(int $capacity): int
|
||||
{
|
||||
return pow(2, ceil(log($capacity, 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that enough memory is allocated for a specified capacity. This
|
||||
* potentially reduces the number of reallocations as the size increases.
|
||||
*
|
||||
* @param int $capacity The number of values for which capacity should be
|
||||
* allocated. Capacity will stay the same if this value
|
||||
* is less than or equal to the current capacity.
|
||||
*/
|
||||
public function allocate(int $capacity)
|
||||
{
|
||||
$this->capacity = max($this->square($capacity), $this->capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when capacity should be increased to accommodate new values.
|
||||
*/
|
||||
protected function increaseCapacity()
|
||||
{
|
||||
$this->capacity = $this->square(
|
||||
max(
|
||||
count($this) + 1,
|
||||
$this->capacity * $this->getGrowthFactor()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $total
|
||||
*/
|
||||
protected function ensureCapacity(int $total)
|
||||
{
|
||||
while ($total > $this->capacity()) {
|
||||
$this->increaseCapacity();
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Label/vendor/php-ds/php-ds/src/Vector.php
vendored
Normal file
35
src/Label/vendor/php-ds/php-ds/src/Vector.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace Ds;
|
||||
|
||||
/**
|
||||
* A Vector is a sequence of values in a contiguous buffer that grows and
|
||||
* shrinks automatically. It’s the most efficient sequential structure because
|
||||
* a value’s index is a direct mapping to its index in the buffer, and the
|
||||
* growth factor isn't bound to a specific multiple or exponent.
|
||||
*
|
||||
* @package Ds
|
||||
*
|
||||
* @template TValue
|
||||
* @implements Sequence<TValue>
|
||||
*/
|
||||
final class Vector implements Sequence
|
||||
{
|
||||
use Traits\GenericCollection;
|
||||
use Traits\GenericSequence;
|
||||
use Traits\Capacity;
|
||||
|
||||
public const MIN_CAPACITY = 8;
|
||||
|
||||
protected function getGrowthFactor(): float
|
||||
{
|
||||
return 1.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether capacity should be increased.
|
||||
*/
|
||||
protected function shouldIncreaseCapacity(): bool
|
||||
{
|
||||
return count($this) > $this->capacity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user