From fa8eefd8501baaeef0a0fc25f6c6f78c6d0d5967 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 06:04:16 +0000 Subject: [PATCH 01/14] ASCII-Tables first approach --- application/controllers/Labels.php | 51 +- src/Label/generatelabels-noalternate.php | 110 + src/Label/generatelabels.php | 120 + src/Label/vendor/autoload.php | 25 + src/Label/vendor/composer/ClassLoader.php | 585 ++++ .../vendor/composer/InstalledVersions.php | 359 +++ src/Label/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 10 + .../vendor/composer/autoload_namespaces.php | 9 + src/Label/vendor/composer/autoload_psr4.php | 12 + src/Label/vendor/composer/autoload_real.php | 38 + src/Label/vendor/composer/autoload_static.php | 44 + src/Label/vendor/composer/installed.json | 171 ++ src/Label/vendor/composer/installed.php | 50 + src/Label/vendor/composer/platform_check.php | 26 + .../malios/php-to-ascii-table/.gitignore | 2 + .../malios/php-to-ascii-table/LICENSE.md | 21 + .../malios/php-to-ascii-table/README.md | 116 + .../php-to-ascii-table/assets/table.png | Bin 0 -> 97148 bytes .../malios/php-to-ascii-table/composer.json | 46 + .../malios/php-to-ascii-table/composer.lock | 2585 +++++++++++++++++ .../php-to-ascii-table/docs/CONTRIBUTING.md | 9 + .../malios/php-to-ascii-table/psalm.xml | 55 + .../malios/php-to-ascii-table/src/Builder.php | 253 ++ .../malios/php-to-ascii-table/src/Cell.php | 105 + .../php-to-ascii-table/src/CellInterface.php | 48 + .../src/Exception/BuilderException.php | 7 + .../malios/php-to-ascii-table/src/Row.php | 61 + .../php-to-ascii-table/src/RowInterface.php | 45 + .../malios/php-to-ascii-table/src/Table.php | 123 + .../php-to-ascii-table/src/TableInterface.php | 58 + .../php-to-ascii-table/tests/BuilderTest.php | 328 +++ .../php-to-ascii-table/tests/CellTest.php | 52 + .../php-to-ascii-table/tests/RowTest.php | 24 + .../php-to-ascii-table/tests/TableTest.php | 87 + src/Label/vendor/php-ds/php-ds/CHANGELOG.md | 33 + .../vendor/php-ds/php-ds/CONTRIBUTING.md | 21 + src/Label/vendor/php-ds/php-ds/LICENSE | 20 + src/Label/vendor/php-ds/php-ds/README.md | 38 + src/Label/vendor/php-ds/php-ds/composer.json | 32 + .../vendor/php-ds/php-ds/src/Collection.php | 56 + src/Label/vendor/php-ds/php-ds/src/Deque.php | 29 + .../vendor/php-ds/php-ds/src/Hashable.php | 32 + src/Label/vendor/php-ds/php-ds/src/Map.php | 811 ++++++ src/Label/vendor/php-ds/php-ds/src/Pair.php | 158 + .../php-ds/php-ds/src/PriorityQueue.php | 340 +++ src/Label/vendor/php-ds/php-ds/src/Queue.php | 195 ++ .../vendor/php-ds/php-ds/src/Sequence.php | 330 +++ src/Label/vendor/php-ds/php-ds/src/Set.php | 538 ++++ src/Label/vendor/php-ds/php-ds/src/Stack.php | 198 ++ .../php-ds/php-ds/src/Traits/Capacity.php | 130 + .../php-ds/src/Traits/GenericCollection.php | 75 + .../php-ds/src/Traits/GenericSequence.php | 419 +++ .../php-ds/src/Traits/SquaredCapacity.php | 58 + src/Label/vendor/php-ds/php-ds/src/Vector.php | 35 + .../vendor/php-ds/php-ds/tests/bootstrap.php | 7 + 56 files changed, 9209 insertions(+), 2 deletions(-) create mode 100644 src/Label/generatelabels-noalternate.php create mode 100644 src/Label/generatelabels.php create mode 100644 src/Label/vendor/autoload.php create mode 100644 src/Label/vendor/composer/ClassLoader.php create mode 100644 src/Label/vendor/composer/InstalledVersions.php create mode 100644 src/Label/vendor/composer/LICENSE create mode 100644 src/Label/vendor/composer/autoload_classmap.php create mode 100644 src/Label/vendor/composer/autoload_namespaces.php create mode 100644 src/Label/vendor/composer/autoload_psr4.php create mode 100644 src/Label/vendor/composer/autoload_real.php create mode 100644 src/Label/vendor/composer/autoload_static.php create mode 100644 src/Label/vendor/composer/installed.json create mode 100644 src/Label/vendor/composer/installed.php create mode 100644 src/Label/vendor/composer/platform_check.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/.gitignore create mode 100644 src/Label/vendor/malios/php-to-ascii-table/LICENSE.md create mode 100644 src/Label/vendor/malios/php-to-ascii-table/README.md create mode 100644 src/Label/vendor/malios/php-to-ascii-table/assets/table.png create mode 100644 src/Label/vendor/malios/php-to-ascii-table/composer.json create mode 100644 src/Label/vendor/malios/php-to-ascii-table/composer.lock create mode 100644 src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md create mode 100644 src/Label/vendor/malios/php-to-ascii-table/psalm.xml create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/Builder.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/Cell.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/Exception/BuilderException.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/Row.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/Table.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/BuilderTest.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php create mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php create mode 100644 src/Label/vendor/php-ds/php-ds/CHANGELOG.md create mode 100644 src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md create mode 100644 src/Label/vendor/php-ds/php-ds/LICENSE create mode 100644 src/Label/vendor/php-ds/php-ds/README.md create mode 100644 src/Label/vendor/php-ds/php-ds/composer.json create mode 100644 src/Label/vendor/php-ds/php-ds/src/Collection.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Deque.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Hashable.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Map.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Pair.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Queue.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Sequence.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Set.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Stack.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php create mode 100644 src/Label/vendor/php-ds/php-ds/src/Vector.php create mode 100644 src/Label/vendor/php-ds/php-ds/tests/bootstrap.php diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 9b813de0..05014557 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -1,5 +1,6 @@ COL_CALL !== $current_callsign) { if (!empty($qso_data)) { - $this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos); + $this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos); + // $this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos); + array_push($whole_qsos,$qso_data); $qso_data = []; } $current_callsign = $qso->COL_CALL; @@ -207,8 +211,51 @@ class Labels extends CI_Controller { } if (!empty($qso_data)) { $this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos); + array_push($whole_qsos,$qso_data); } } +// New begin + +function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { + $tableData = []; + $count_qso = 0; + + foreach ($preliminaryData as $key => $row) { + $rowData = [ + 'Date/UTC' => $row['time'], + 'Band' => $row['band'], + 'Mode' => $row['mode'], + 'RST' => $row['rst'], + ]; + $tableData[] = $rowData; + $count_qso++; + + if($count_qso == $qso_per_label){ + generateLabel($pdf, $current_callsign, $tableData); + $tableData = []; // reset the data + $count_qso = 0; // reset the counter + } + unset($preliminaryData[$key]); + } + // generate label for remaining QSOs + if($count_qso > 0){ + $this->generateLabel($pdf, $current_callsign, $tableData); + $preliminaryData = []; // reset the data + } +} + +function generateLabel($pdf, $current_callsign, $tableData){ + $builder = new \AsciiTable\Builder(); + $builder->addRows($tableData); + $text = "Confirming QSO with "; + $text .= $current_callsign; + $text .= "\n"; + $text .= $builder->renderTable(); + $text .= "\nThanks for the QSO"; + $pdf->Add_Label($text); +} + +// New End function makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos) { $text = 'To: ' . $current_callsign . "\n\n"; @@ -278,4 +325,4 @@ class Labels extends CI_Controller { $this->labels_model->saveDefaultLabel($id); } -} \ No newline at end of file +} diff --git a/src/Label/generatelabels-noalternate.php b/src/Label/generatelabels-noalternate.php new file mode 100644 index 00000000..4b49de3a --- /dev/null +++ b/src/Label/generatelabels-noalternate.php @@ -0,0 +1,110 @@ +AddPage(); +$fontName = 'DejaVuSans'; +$pdf->AddFont($fontName,'','DejaVuSansMono.ttf',true); +$pdf->AddFont($fontName,'B','DejaVuSansMono.ttf',true); +$pdf->SetFont($fontName,'',6); +$con = mysqli_connect("localhost","USERNAME","PASSWORD","DATABASE"); + +// Check connection +if (mysqli_connect_errno()) { + echo "Failed to connect to MySQL: " . mysqli_connect_error(); +} + +$sql = "SELECT c.COL_PRIMARY_KEY, c.COL_CALL, c.COL_TIME_ON, c.COL_MODE, c.COL_BAND, c.COL_RST_SENT, p.station_gridsquare, p.station_cnty, p.state, p.station_id FROM TABLE_HRD_CONTACTS_V01 c INNER JOIN station_profile p ON c.station_id=p.station_id WHERE c.COL_QSL_SENT LIKE 'R' ORDER BY c.COL_CALL,c.COL_TIME_ON;"; +$result = $con->query($sql); + +function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { + $tableData = []; + $count_qso = 0; + + foreach ($preliminaryData as $key => $row) { + $rowData = [ + 'Date/Time UTC' => $row['Date/Time UTC'], + 'Band' => $row['Band'], + 'Mode' => $row['Mode'], + 'RST' => $row['RST'], + 'My Grid' => $row['My Grid'], + 'My County' => $row['My County'], + ]; + $tableData[] = $rowData; + $count_qso++; + + if($count_qso == $qso_per_label){ + generateLabel($pdf, $current_callsign, $tableData); + $tableData = []; // reset the data + $count_qso = 0; // reset the counter + } + unset($preliminaryData[$key]); + } + // generate label for remaining QSOs + if($count_qso > 0){ + generateLabel($pdf, $current_callsign, $tableData); + $preliminaryData = []; // reset the data + } +} + +function generateLabel($pdf, $current_callsign, $tableData){ + $builder = new \AsciiTable\Builder(); + $builder->addRows($tableData); + $text = "Confirming QSO with "; + $text .= $current_callsign; + $text .= "\n"; + $text .= $builder->renderTable(); + $text .= "\nThanks for the QSO"; + $pdf->Add_Label($text); +} + +if ($result->num_rows > 0) { + $current_callsign = ''; + $preliminaryData = []; + + // output data of each row + while($row = $result->fetch_assoc()) { + if ($row['COL_CALL'] !== $current_callsign) { + while (!empty($preliminaryData)) { + finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label); + } + $current_callsign = $row['COL_CALL']; + } + + $time = strtotime($row["COL_TIME_ON"]); + $myFormatForView = date("Y-m-y H:i", $time); + + $band = $row['COL_BAND']; + $mode = $row['COL_MODE']; + $rst = $row['COL_RST_SENT']; + $grid = $row['station_gridsquare']; + $county = $row['station_cnty'] . ',' . $row['state']; + + + // Add the row of data to the preliminary data + $preliminaryData[] = [ + 'Date/Time UTC' => $myFormatForView, + 'Band' => $band, + 'Mode' => $mode, + 'RST' => $rst, + 'My Grid' => $grid, + 'My County' => $county, + ]; + } + + while (!empty($preliminaryData)) { + finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label); + } +} else { + echo "0 results"; +} + +$pdf->Output(); + +?> diff --git a/src/Label/generatelabels.php b/src/Label/generatelabels.php new file mode 100644 index 00000000..475f4af5 --- /dev/null +++ b/src/Label/generatelabels.php @@ -0,0 +1,120 @@ +AddPage(); +$fontName = 'DejaVuSans'; +$pdf->AddFont($fontName,'','DejaVuSansMono.ttf',true); +$pdf->AddFont($fontName,'B','DejaVuSansMono.ttf',true); +$pdf->SetFont($fontName,'',6); +$con = mysqli_connect("localhost","USERNAME","PASSWORD","DATABASE"); + +// Check connection +if (mysqli_connect_errno()) { + echo "Failed to connect to MySQL: " . mysqli_connect_error(); +} + +$sql = "SELECT c.COL_PRIMARY_KEY, c.COL_CALL, c.COL_TIME_ON, c.COL_MODE, c.COL_BAND, c.COL_RST_SENT, p.station_gridsquare, p.station_cnty, p.state, p.station_id FROM TABLE_HRD_CONTACTS_V01 c INNER JOIN station_profile p ON c.station_id=p.station_id WHERE c.COL_QSL_SENT LIKE 'R' ORDER BY c.COL_CALL,c.COL_TIME_ON;"; +$result = $con->query($sql); + +function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label, &$hasNonAlternateCounty) { + $tableData = []; + $count_qso = 0; + + foreach ($preliminaryData as $key => $row) { + $rowData = [ + 'Date/Time UTC' => $row['Date/Time UTC'], + 'Band' => $row['Band'], + 'Mode' => $row['Mode'], + 'RST' => $row['RST'], + ]; + if ($hasNonAlternateCounty) { + $rowData['My Grid'] = $row['My Grid']; + $rowData['My County'] = $row['My County']; + } + $tableData[] = $rowData; + $count_qso++; + + if($count_qso == $qso_per_label){ + generateLabel($pdf, $current_callsign, $tableData); + $tableData = []; // reset the data + $count_qso = 0; // reset the counter + } + unset($preliminaryData[$key]); + } + // generate label for remaining QSOs + if($count_qso > 0){ + generateLabel($pdf, $current_callsign, $tableData); + $preliminaryData = []; // reset the data + } +} + +function generateLabel($pdf, $current_callsign, $tableData){ + $builder = new \AsciiTable\Builder(); + $builder->addRows($tableData); + $text = "Confirming QSO with "; + $text .= $current_callsign; + $text .= "\n"; + $text .= $builder->renderTable(); + $text .= "\nThanks for the QSO"; + $pdf->Add_Label($text); +} + +if ($result->num_rows > 0) { + $current_callsign = ''; + $preliminaryData = []; + $hasNonAlternateCounty = false; + + // output data of each row + while($row = $result->fetch_assoc()) { + if ($row['COL_CALL'] !== $current_callsign) { + while (!empty($preliminaryData)) { + finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label, $hasNonAlternateCounty); + } + $current_callsign = $row['COL_CALL']; + $hasNonAlternateCounty = false; + } + + $time = strtotime($row["COL_TIME_ON"]); + $myFormatForView = date("Y-m-y H:i", $time); + + $band = $row['COL_BAND']; + $mode = $row['COL_MODE']; + $rst = $row['COL_RST_SENT']; + $grid = $row['station_gridsquare']; + $county = $row['station_cnty'] . ',' . $row['state']; + + if ($county !== $alternate_county) { + $hasNonAlternateCounty = true; + } + + // Add the row of data to the preliminary data + $preliminaryData[] = [ + 'Date/Time UTC' => $myFormatForView, + 'Band' => $band, + 'Mode' => $mode, + 'RST' => $rst, + 'My Grid' => $grid, + 'My County' => $county, + ]; + } + + while (!empty($preliminaryData)) { + finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label, $hasNonAlternateCounty); + } +} else { + echo "0 results"; +} + +$pdf->Output(); + +?> diff --git a/src/Label/vendor/autoload.php b/src/Label/vendor/autoload.php new file mode 100644 index 00000000..e09b8e09 --- /dev/null +++ b/src/Label/vendor/autoload.php @@ -0,0 +1,25 @@ + + * Jordi Boggiano + * + * 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 + * @author Jordi Boggiano + * @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> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + 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> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $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); + } +} diff --git a/src/Label/vendor/composer/InstalledVersions.php b/src/Label/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..51e734a7 --- /dev/null +++ b/src/Label/vendor/composer/InstalledVersions.php @@ -0,0 +1,359 @@ + + * Jordi Boggiano + * + * 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}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + 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 + */ + 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 + */ + 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} + */ + 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}> + */ + 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} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + 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} $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} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/src/Label/vendor/composer/LICENSE b/src/Label/vendor/composer/LICENSE new file mode 100644 index 00000000..f27399a0 --- /dev/null +++ b/src/Label/vendor/composer/LICENSE @@ -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. + diff --git a/src/Label/vendor/composer/autoload_classmap.php b/src/Label/vendor/composer/autoload_classmap.php new file mode 100644 index 00000000..0fb0a2c1 --- /dev/null +++ b/src/Label/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $vendorDir . '/composer/InstalledVersions.php', +); diff --git a/src/Label/vendor/composer/autoload_namespaces.php b/src/Label/vendor/composer/autoload_namespaces.php new file mode 100644 index 00000000..15a2ff3a --- /dev/null +++ b/src/Label/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/dekor/php-array-table/src'), + 'Ds\\' => array($vendorDir . '/php-ds/php-ds/src'), + 'AsciiTable\\' => array($vendorDir . '/malios/php-to-ascii-table/src'), +); diff --git a/src/Label/vendor/composer/autoload_real.php b/src/Label/vendor/composer/autoload_real.php new file mode 100644 index 00000000..0cd90118 --- /dev/null +++ b/src/Label/vendor/composer/autoload_real.php @@ -0,0 +1,38 @@ +register(true); + + return $loader; + } +} diff --git a/src/Label/vendor/composer/autoload_static.php b/src/Label/vendor/composer/autoload_static.php new file mode 100644 index 00000000..b985aa95 --- /dev/null +++ b/src/Label/vendor/composer/autoload_static.php @@ -0,0 +1,44 @@ + + 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); + } +} diff --git a/src/Label/vendor/composer/installed.json b/src/Label/vendor/composer/installed.json new file mode 100644 index 00000000..dee3a022 --- /dev/null +++ b/src/Label/vendor/composer/installed.json @@ -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": [] +} diff --git a/src/Label/vendor/composer/installed.php b/src/Label/vendor/composer/installed.php new file mode 100644 index 00000000..5b86cebf --- /dev/null +++ b/src/Label/vendor/composer/installed.php @@ -0,0 +1,50 @@ + 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, + ), + ), +); diff --git a/src/Label/vendor/composer/platform_check.php b/src/Label/vendor/composer/platform_check.php new file mode 100644 index 00000000..f79e574b --- /dev/null +++ b/src/Label/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 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 + ); +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/.gitignore b/src/Label/vendor/malios/php-to-ascii-table/.gitignore new file mode 100644 index 00000000..4c36e385 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/.gitignore @@ -0,0 +1,2 @@ +.idea/ +vendor/ diff --git a/src/Label/vendor/malios/php-to-ascii-table/LICENSE.md b/src/Label/vendor/malios/php-to-ascii-table/LICENSE.md new file mode 100644 index 00000000..20a68f33 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/LICENSE.md @@ -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. \ No newline at end of file diff --git a/src/Label/vendor/malios/php-to-ascii-table/README.md b/src/Label/vendor/malios/php-to-ascii-table/README.md new file mode 100644 index 00000000..46040aa6 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/README.md @@ -0,0 +1,116 @@ +# php-to-ascii-table +A small PHP library for generating plain text tables. + +![example table](assets/table.png) + +## 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 +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 +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. diff --git a/src/Label/vendor/malios/php-to-ascii-table/assets/table.png b/src/Label/vendor/malios/php-to-ascii-table/assets/table.png new file mode 100644 index 0000000000000000000000000000000000000000..4df9803797450a59de8704ce4d449bf6725b790c GIT binary patch literal 97148 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 literal 0 HcmV?d00001 diff --git a/src/Label/vendor/malios/php-to-ascii-table/composer.json b/src/Label/vendor/malios/php-to-ascii-table/composer.json new file mode 100644 index 00000000..a61cfeee --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/composer.json @@ -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" + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/composer.lock b/src/Label/vendor/malios/php-to-ascii-table/composer.lock new file mode 100644 index 00000000..a07970e2 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/composer.lock @@ -0,0 +1,2585 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "02916a8da4bcc0f9d2f42566f1b01d2a", + "packages": [ + { + "name": "php-ds/php-ds", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/php-ds/polyfill.git", + "reference": "e1f03c9f3da643c0cd691b414d5ba89f03dde543" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-ds/polyfill/zipball/e1f03c9f3da643c0cd691b414d5ba89f03dde543", + "reference": "e1f03c9f3da643c0cd691b414d5ba89f03dde543", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "php-ds/tests": "^1.1" + }, + "suggest": { + "ext-ds": "to improve performance and reduce memory usage" + }, + "type": "library", + "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" + ], + "time": "2016-08-28T10:35:47+00:00" + } + ], + "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "13930a582947831bb66ff1aeac28672fd91c38ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/13930a582947831bb66ff1aeac28672fd91c38ea", + "reference": "13930a582947831bb66ff1aeac28672fd91c38ea", + "shasum": "" + }, + "require": { + "php": ">=7" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "phpstan/phpstan": "^0.8.5", + "phpunit/phpunit": "^6.0.9 | ^7", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\": "lib" + }, + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "http://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "time": "2019-11-11T19:32:05+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "9d8205686a004948475dc43f8a88d2fa5e75a113" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/9d8205686a004948475dc43f8a88d2fa5e75a113", + "reference": "9d8205686a004948475dc43f8a88d2fa5e75a113", + "shasum": "" + }, + "require": { + "amphp/amp": "^2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "infection/infection": "^0.9.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\ByteStream\\": "lib" + }, + "files": [ + "lib/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "time": "2019-10-27T14:33:41+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "cbe23383749496fe0f373345208b79568e4bc248" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/cbe23383749496fe0f373345208b79568e4bc248", + "reference": "cbe23383749496fe0f373345208b79568e4bc248", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-11-06T16:40:04+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.3.x-dev", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-10-21T16:45:58+00:00" + }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "23366dd0cab0a0f3fd3016bf3c0b36dec74348e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/23366dd0cab0a0f3fd3016bf3c0b36dec74348e7", + "reference": "23366dd0cab0a0f3fd3016bf3c0b36dec74348e7", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0", + "php": ">=7.0", + "phpdocumentor/reflection-docblock": "^4.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "time": "2019-09-12T22:41:08+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "378801f6139bb74ac215d81cca1272af61df9a9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/378801f6139bb74ac215d81cca1272af61df9a9f", + "reference": "378801f6139bb74ac215d81cca1272af61df9a9f", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpstan/phpstan": "*", + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "time": "2019-06-23T21:03:50+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "9012edbd1604a93cee7e7422d07a2c5776c56e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/9012edbd1604a93cee7e7422d07a2c5776c56e0c", + "reference": "9012edbd1604a93cee7e7422d07a2c5776c56e0c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2019-08-26T15:40:39+00:00" + }, + { + "name": "netresearch/jsonmapper", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06", + "reference": "0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "time": "2019-08-15T19:41:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.2.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/b76bbc3c51f22c570648de48e8c2d941ed5e2cf2", + "reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "0.0.4", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2019-10-25T18:33:07+00:00" + }, + { + "name": "ocramius/package-versions", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "3a7ca6eafde0eec1b964cf967e6e71bf27ecc737" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/3a7ca6eafde0eec1b964cf967e6e71bf27ecc737", + "reference": "3a7ca6eafde0eec1b964cf967e6e71bf27ecc737", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.3.0" + }, + "require-dev": { + "composer/composer": "^1.8.6", + "doctrine/coding-standard": "^6.0.0", + "ext-zip": "*", + "infection/infection": "^0.13.4", + "phpunit/phpunit": "^8.2.5", + "vimeo/psalm": "^3.4.9" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2019-11-09T22:36:27+00:00" + }, + { + "name": "openlss/lib-array2xml", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nullivex/lib-array2xml.git", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "LSS": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bryan Tong", + "email": "bryan@nullivex.com", + "homepage": "https://www.nullivex.com" + }, + { + "name": "Tony Butler", + "email": "spudz76@gmail.com", + "homepage": "https://www.nullivex.com" + } + ], + "description": "Array2XML conversion library credit to lalit.org", + "homepage": "https://www.nullivex.com", + "keywords": [ + "array", + "array conversion", + "xml", + "xml conversion" + ], + "time": "2019-03-29T20:06:56+00:00" + }, + { + "name": "phar-io/manifest", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "6008a32fa23816a6ac71889c80da7d58c056c2bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/6008a32fa23816a6ac71889c80da7d58c056c2bb", + "reference": "6008a32fa23816a6ac71889c80da7d58c056c2bb", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^2.0", + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2019-10-11T06:20:36+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2018-08-07T13:53:10+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-09-12T14:27:41+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "5ad886e77d4a28df9fd0c81c9a3cc191799e8f5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/5ad886e77d4a28df9fd0c81c9a3cc191799e8f5f", + "reference": "5ad886e77d4a28df9fd0c81c9a3cc191799e8f5f", + "shasum": "" + }, + "require": { + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-10-07T19:23:43+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2019-10-03T11:07:50+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf", + "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.2", + "phpunit/php-file-iterator": "^2.0.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.1.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^4.2.2", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.2.2" + }, + "suggest": { + "ext-xdebug": "^2.7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2019-11-20T13:55:58+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "ee5d93c00b87b36e206f1e8407dfe3306f5fcb4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/ee5d93c00b87b36e206f1e8407dfe3306f5fcb4d", + "reference": "ee5d93c00b87b36e206f1e8407dfe3306f5fcb4d", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2019-10-23T09:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "190db5a4b930a73afbba041cd3015aeb10d444d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/190db5a4b930a73afbba041cd3015aeb10d444d4", + "reference": "190db5a4b930a73afbba041cd3015aeb10d444d4", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2019-10-23T09:04:52+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "5bc2030589cad93e6c73ce3ccee3f5e960604a0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5bc2030589cad93e6c73ce3ccee3f5e960604a0d", + "reference": "5bc2030589cad93e6c73ce3ccee3f5e960604a0d", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2019-10-23T09:04:36+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "8.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "67f9e35bffc0dd52d55d565ddbe4230454fd6a4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67f9e35bffc0dd52d55d565ddbe4230454fd6a4e", + "reference": "67f9e35bffc0dd52d55d565ddbe4230454fd6a4e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.2.0", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.2", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^7.0.7", + "phpunit/php-file-iterator": "^2.0.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.2", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.2", + "sebastian/exporter": "^3.1.1", + "sebastian/global-state": "^3.0.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", + "sebastian/version": "^2.0.1" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2019-11-06T09:42:23+00:00" + }, + { + "name": "psr/container", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/fc1bc363ecf887921e3897c7b1dad3587ae154eb", + "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2019-10-04T14:07:35+00:00" + }, + { + "name": "psr/log", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "5628725d0e4d687e29575eb41f9d5ee7de33a84c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/5628725d0e4d687e29575eb41f9d5ee7de33a84c", + "reference": "5628725d0e4d687e29575eb41f9d5ee7de33a84c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-12T16:45:05+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5872e3737247e650995ac60e98611f69bfe8c556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5872e3737247e650995ac60e98611f69bfe8c556", + "reference": "5872e3737247e650995ac60e98611f69bfe8c556", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2019-10-23T09:08:24+00:00" + }, + { + "name": "sebastian/comparator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "c57ba51c28b64ef8a4b14b40bceb2c5ca19e9406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c57ba51c28b64ef8a4b14b40bceb2c5ca19e9406", + "reference": "c57ba51c28b64ef8a4b14b40bceb2c5ca19e9406", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2019-10-28T09:22:49+00:00" + }, + { + "name": "sebastian/diff", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "16e54fbc971c14d98779b9c3b22572178ff9411f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/16e54fbc971c14d98779b9c3b22572178ff9411f", + "reference": "16e54fbc971c14d98779b9c3b22572178ff9411f", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2019-11-18T19:26:59+00:00" + }, + { + "name": "sebastian/environment", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2019-11-20T08:46:58+00:00" + }, + { + "name": "sebastian/exporter", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "10b761abeab7ea48c2b89f16a7fca10d2f544d25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/10b761abeab7ea48c2b89f16a7fca10d2f544d25", + "reference": "10b761abeab7ea48c2b89f16a7fca10d2f544d25", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2019-10-23T09:05:12+00:00" + }, + { + "name": "sebastian/global-state", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "95e10dd8f625c50dc0dcbeab936aadac79f017c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/95e10dd8f625c50dc0dcbeab936aadac79f017c7", + "reference": "95e10dd8f625c50dc0dcbeab936aadac79f017c7", + "shasum": "" + }, + "require": { + "php": "^7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2019-10-23T09:05:27+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "6096279595e26594a68c03571fba1d7c0253f19a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/6096279595e26594a68c03571fba1d7c0253f19a", + "reference": "6096279595e26594a68c03571fba1d7c0253f19a", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2019-10-23T09:08:54+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "aff2a6b4fffc8e9f0f1de6388f3d7bd0f729dddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/aff2a6b4fffc8e9f0f1de6388f3d7bd0f729dddc", + "reference": "aff2a6b4fffc8e9f0f1de6388f3d7bd0f729dddc", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2019-10-23T09:07:29+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "f95dcff26fa9fd4df1960c503d4180ec2f8172fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f95dcff26fa9fd4df1960c503d4180ec2f8172fd", + "reference": "f95dcff26fa9fd4df1960c503d4180ec2f8172fd", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2019-10-23T09:08:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "89893975fe3fcc2e60214471761af5e91cc7a933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/89893975fe3fcc2e60214471761af5e91cc7a933", + "reference": "89893975fe3fcc2e60214471761af5e91cc7a933", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2019-10-23T09:09:44+00:00" + }, + { + "name": "sebastian/type", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "b4b5b44e8b89f789356aa9cd9a1f05d78a9d819a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b4b5b44e8b89f789356aa9cd9a1f05d78a9d819a", + "reference": "b4b5b44e8b89f789356aa9cd9a1f05d78a9d819a", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2019-10-23T09:06:38+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "symfony/console", + "version": "4.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8", + "reference": "35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-11-13T07:39:40+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "a874bbf9135bd76175baa2c26d14312c9ef25543" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a874bbf9135bd76175baa2c26d14312c9ef25543", + "reference": "a874bbf9135bd76175baa2c26d14312c9ef25543", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-09-17T10:46:08+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "vimeo/psalm", + "version": "3.6.6", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "5e17a9af104de39321c47f73b253cece9df1cf2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/5e17a9af104de39321c47f73b253cece9df1cf2c", + "reference": "5e17a9af104de39321c47f73b253cece9df1cf2c", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.1", + "amphp/byte-stream": "^1.5", + "composer/xdebug-handler": "^1.1", + "felixfbecker/advanced-json-rpc": "^3.0.3", + "felixfbecker/language-server-protocol": "^1.4", + "netresearch/jsonmapper": "^1.0", + "nikic/php-parser": "4.2.*", + "ocramius/package-versions": "^1.2", + "openlss/lib-array2xml": "^1.0", + "php": "^7.1.3", + "sebastian/diff": "^3.0", + "symfony/console": "^3.3||^4.0", + "webmozart/glob": "^4.1", + "webmozart/path-util": "^2.3" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "ext-curl": "*", + "friendsofphp/php-cs-fixer": "^2.15", + "phpmyadmin/sql-parser": "^5.0", + "phpunit/phpunit": "^7.5 || ^8.0", + "psalm/plugin-phpunit": "^0.6", + "slevomat/coding-standard": "^5.0", + "squizlabs/php_codesniffer": "3.4.0", + "symfony/process": "^4.3" + }, + "suggest": { + "ext-igbinary": "^2.0.5" + }, + "bin": [ + "psalm", + "psalter", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\Plugin\\": "src/Psalm/Plugin", + "Psalm\\": "src/Psalm" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php" + ], + "time": "2019-11-14T19:44:29+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "vimeo/psalm": "<3.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-11-24T13:36:37+00:00" + }, + { + "name": "webmozart/glob", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/webmozart/glob.git", + "reference": "8da14867b709e8776d9f6272faaf844aefc695e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/glob/zipball/8da14867b709e8776d9f6272faaf844aefc695e3", + "reference": "8da14867b709e8776d9f6272faaf844aefc695e3", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0", + "webmozart/path-util": "^2.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1", + "symfony/filesystem": "^2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Glob\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A PHP implementation of Ant's glob.", + "time": "2016-08-15T15:31:26+00:00" + }, + { + "name": "webmozart/path-util", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "95a8f7ad150c2a3773ff3c3d04f557a24c99cfd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/95a8f7ad150c2a3773ff3c3d04f557a24c99cfd2", + "reference": "95a8f7ad150c2a3773ff3c3d04f557a24c99cfd2", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "time": "2016-08-15T15:31:42+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": { + "phpunit/phpunit": 0, + "vimeo/psalm": 0 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7", + "ext-mbstring": "*" + }, + "platform-dev": [] +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md b/src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md new file mode 100644 index 00000000..b9f6ad7d --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/docs/CONTRIBUTING.md @@ -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 diff --git a/src/Label/vendor/malios/php-to-ascii-table/psalm.xml b/src/Label/vendor/malios/php-to-ascii-table/psalm.xml new file mode 100644 index 00000000..42f355b2 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/psalm.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Label/vendor/malios/php-to-ascii-table/src/Builder.php b/src/Label/vendor/malios/php-to-ascii-table/src/Builder.php new file mode 100644 index 00000000..0e11e741 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/src/Builder.php @@ -0,0 +1,253 @@ +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; + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/src/Cell.php b/src/Label/vendor/malios/php-to-ascii-table/src/Cell.php new file mode 100644 index 00000000..9d779f06 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/src/Cell.php @@ -0,0 +1,105 @@ +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; + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php b/src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php new file mode 100644 index 00000000..701fc401 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/src/CellInterface.php @@ -0,0 +1,48 @@ +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; + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php b/src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php new file mode 100644 index 00000000..4e5d6743 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/src/RowInterface.php @@ -0,0 +1,45 @@ +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; + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php b/src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php new file mode 100644 index 00000000..6b71ab3c --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/src/TableInterface.php @@ -0,0 +1,58 @@ +addRow(['age' => 21, 'name' => 'John']); + + $person = new class implements \JsonSerializable { + + function jsonSerialize() + { + return [ + 'age' => 32, + 'name' => 'Bill' + ]; + } + }; + + $builder->addRow($person); + + $table = $builder->getTable(); + $rows = $table->getRows(); + + $this->assertEquals(21, $rows[0]->getCell('age')->getValue()); + $this->assertEquals('John', $rows[0]->getCell('name')->getValue()); + + $this->assertEquals(32, $rows[1]->getCell('age')->getValue()); + $this->assertEquals('Bill', $rows[1]->getCell('name')->getValue()); + } + + public function testAddInvalidRow() + { + $this->expectException(BuilderException::class); + + $person = new class { + public $name; + }; + + $person->name = 'Rick'; + + $builder = new Builder(); + $builder->addRow($person); + } + + public function testRenderEmptyTable() + { + $this->expectException(BuilderException::class); + + $builder = new Builder(); + $builder->renderTable(); + } + + public function testRender() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'name' => 'John', + 'age' => 23, + 'sex' => 'male' + ], + [ + 'name' => 'Catherine', + 'age' => 22, + 'sex' => 'female' + ], + [ + 'name' => 'Johnathan', + 'age' => 44, + 'sex' => 'male' + ] + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testRenderWithSomeEmptyCells() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'name' => 'John', + 'age' => 23, + 'sex' => 'male' + ], + [ + 'name' => 'Catherine', + 'sex' => 'female' + ], + [ + 'name' => 'Johnathan', + 'age' => 44, + ] + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testShowsOnlyVisibleColumns() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'name' => 'John', + 'age' => 23, + 'sex' => 'male' + ], + [ + 'name' => 'Catherine', + 'age' => 22, + 'sex' => 'female' + ], + [ + 'name' => 'Johnathan', + 'age' => 44, + 'sex' => 'male' + ] + ]); + + $builder->showColumns(['name', 'age']); + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testRenderTableWithFloatingPoint() + { + $builder = new 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 + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testRenderTableWithCyrillicWord() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'name' => 'John', + 'age' => 21 + ], + [ + 'name' => 'Иван', + 'age' => 23 + ] + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testRenderWithCyrillicColumnNames() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'имя' => 'Джон', + 'год' => 21 + ], + [ + 'имя' => 'Иван', + 'год' => 23 + ] + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + public function testRenderWithChineseColumnNames() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'language' => 'English', + 'greeting' => 'Hello, World' + ], + [ + 'language' => 'mixed', + 'greeting' => 'Hello, 世界' + ] + ]); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } + + public function testRenderWithTitle() + { + $builder = new Builder(); + $builder->addRows([ + [ + 'language' => 'English', + 'greeting' => 'Hello, World' + ], + [ + 'language' => 'mixed', + 'greeting' => 'Hello, 世界' + ] + ]); + $builder->setTitle('Greetings'); + + $result = $builder->renderTable(); + + $expected = <<assertEquals($expected, $result); + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php new file mode 100644 index 00000000..66b823db --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php @@ -0,0 +1,52 @@ +assertEquals('21', $cell->getValue()); + $this->assertEquals(2, $cell->getWidth()); + + $cell->setValue(123); + $this->assertEquals('123', $cell->getValue()); + $this->assertEquals(3, $cell->getWidth()); + + $ageObject = new class (2008) { + private $year; + + function __construct(int $year) + { + $this->year = $year; + } + + function __toString() + { + return strval(2017 - $this->year); + } + }; + + $cell->setValue($ageObject); + $this->assertEquals(1, $cell->getWidth()); + + $floatCell = new Cell('price', 100.00); + $this->assertEquals("100.00", $floatCell->getValue()); + + $floatCell->setValue(99.99); + $this->assertEquals("99.99", $floatCell->getValue()); + } + + public function testCellWidthWithMultiByteCharacters() + { + $cell = new Cell('name', 'Иван'); + $this->assertEquals(4, $cell->getWidth()); + + $cell = new Cell('message', 'Hello, 世界'); // 世界 - this string is with width 4 + $this->assertEquals(11, $cell->getWidth()); + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php new file mode 100644 index 00000000..f1bdd6ff --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php @@ -0,0 +1,24 @@ +addCell(new Cell('name', 'John')); + $row->addCell(new Cell('name', 'Rick')); + + $this->assertCount(1, $row->getCells()); + + $cell = $row->getCells()->get('name'); + + $this->assertEquals($cell->getColumnName(), 'name'); + $this->assertEquals($cell->getValue(), 'Rick'); + } +} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php new file mode 100644 index 00000000..86661e04 --- /dev/null +++ b/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php @@ -0,0 +1,87 @@ +setVisibleColumns(['name', 'age', 'location', 'sex']); + + $set = new Set(); + $set->add('name'); + $set->add('age'); + $set->add('location'); + $set->add('sex'); + + self::assertEquals(0, $set->diff($table->getVisibleColumns())->count()); + self::assertEquals(0, $table->getVisibleColumns()->diff($set)->count()); + } + + public function testGetVisibleColumnsWhenNotSet() + { + $row = new Row(); + $row->addCell(new Cell('name', 'Catherine')); + $row->addCell(new Cell('sex', 'female')); + $row->addCell(new Cell('height', 168)); + + $table = new Table(); + $table->addRow($row); + + $this->assertSame(['name', 'sex', 'height'], $table->getVisibleColumns()->toArray()); + } + + public function testGetAllColumns() + { + $row = new Row(); + $row->addCell(new Cell('name', 'Bill')); + $row->addCell(new Cell('age', 21)); + + $row2 = new Row(); + $row2->addCell(new Cell('name', 'John')); + $row2->addCell(new Cell('sex', 'male')); + + $row3 = new Row(); + $row3->addCell(new Cell('name', 'Catherine')); + $row3->addCell(new Cell('sex', 'female')); + $row3->addCell(new Cell('height', 168)); + + $table = new Table(); + $table->addRow($row); + $table->addRow($row2); + $table->addRow($row3); + + $this->assertSame(['name', 'age', 'sex', 'height'], $table->getAllColumns()->toArray()); + } + + public function testColumnWidth() + { + $row = new Row(); + $row->addCell(new Cell('name', 'Jon')); + $row->addCell(new Cell('age', 21)); + + $row2 = new Row(); + $row2->addCell(new Cell('name', 'John')); + $row2->addCell(new Cell('age', 32)); + + $row3 = new Row(); + $row3->addCell(new Cell('name', 'Johnathan')); + $row3->addCell(new Cell('age', 23)); + + $table = new Table(); + + $table->addRow($row); + $table->addRow($row2); + $table->addRow($row3); + + $this->assertEquals(3, $table->getColumnWidth('age')); + $this->assertEquals(9, $table->getColumnWidth('name')); + } +} diff --git a/src/Label/vendor/php-ds/php-ds/CHANGELOG.md b/src/Label/vendor/php-ds/php-ds/CHANGELOG.md new file mode 100644 index 00000000..2ab32ea8 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/CHANGELOG.md @@ -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` diff --git a/src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md b/src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md new file mode 100644 index 00000000..1bf340ec --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/CONTRIBUTING.md @@ -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. diff --git a/src/Label/vendor/php-ds/php-ds/LICENSE b/src/Label/vendor/php-ds/php-ds/LICENSE new file mode 100644 index 00000000..5f2a7778 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/LICENSE @@ -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. diff --git a/src/Label/vendor/php-ds/php-ds/README.md b/src/Label/vendor/php-ds/php-ds/README.md new file mode 100644 index 00000000..13f57a62 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/README.md @@ -0,0 +1,38 @@ +# Data Structures for PHP + +[![Build Status](https://github.com/php-ds/polyfill/workflows/CI/badge.svg)](https://github.com/php-ds/polyfill/actions?query=workflow%3A%22CI%22+branch%3Amaster) +[![Packagist](https://img.shields.io/packagist/v/php-ds/php-ds.svg)](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. diff --git a/src/Label/vendor/php-ds/php-ds/composer.json b/src/Label/vendor/php-ds/php-ds/composer.json new file mode 100644 index 00000000..37e803dd --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/composer.json @@ -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" + } + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Collection.php b/src/Label/vendor/php-ds/php-ds/src/Collection.php new file mode 100644 index 00000000..1172334c --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Collection.php @@ -0,0 +1,56 @@ + + */ +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 + */ + 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 + */ + public function toArray(): array; +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Deque.php b/src/Label/vendor/php-ds/php-ds/src/Deque.php new file mode 100644 index 00000000..905200c5 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Deque.php @@ -0,0 +1,29 @@ + + */ +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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Hashable.php b/src/Label/vendor/php-ds/php-ds/src/Hashable.php new file mode 100644 index 00000000..a98b986a --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Hashable.php @@ -0,0 +1,32 @@ + + */ +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 + */ + private $pairs = []; + + /** + * Creates a new instance. + * + * @param iterable $values + * + * @psalm-param iterable $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 + */ + 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 + */ + 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 + */ + 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 $values + * @psalm-return Map + */ + 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 $map + * @psalm-return Map + */ + 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 $map + * @psalm-return Map + */ + 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|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|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 + */ + 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 + */ + 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 + */ + 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> + */ + 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 $values + * + * @psalm-param iterable $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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 $map + * @psalm-return Map + */ + 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 $map + * @psalm-return Map + */ + 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> + */ + 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(); + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Pair.php b/src/Label/vendor/php-ds/php-ds/src/Pair.php new file mode 100644 index 00000000..e3a97b88 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Pair.php @@ -0,0 +1,158 @@ +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 + */ + 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) . ')'; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php b/src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php new file mode 100644 index 00000000..5cd71d3e --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/PriorityQueue.php @@ -0,0 +1,340 @@ + + */ +final class PriorityQueue implements Collection +{ + use Traits\GenericCollection; + use Traits\SquaredCapacity; + + public const MIN_CAPACITY = 8; + + /** + * @var array> + */ + 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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Queue.php b/src/Label/vendor/php-ds/php-ds/src/Queue.php new file mode 100644 index 00000000..b9aeff03 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Queue.php @@ -0,0 +1,195 @@ + + */ +final class Queue implements Collection, \ArrayAccess +{ + use Traits\GenericCollection; + + /** + * @var Deque internal deque to store values. + * + * @psalm-var Deque + */ + private $deque; + + /** + * Creates an instance using the values of an array or Traversable object. + * + * @param iterable $values + * + * @psalm-param iterable $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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Sequence.php b/src/Label/vendor/php-ds/php-ds/src/Sequence.php new file mode 100644 index 00000000..c3a32995 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Sequence.php @@ -0,0 +1,330 @@ + + */ +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 + */ + 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 + */ + 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 $values + * @psalm-return Sequence + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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); +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Set.php b/src/Label/vendor/php-ds/php-ds/src/Set.php new file mode 100644 index 00000000..cd732311 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Set.php @@ -0,0 +1,538 @@ + + */ +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 + */ + 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 $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 $set + * @psalm-return Set + */ + 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 $set + * @psalm-return Set + */ + 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 + */ + 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 $set + * @psalm-return Set + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + 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 $values + * @psalm-return Set + */ + 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 $set + * @psalm-return Set + */ + 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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Stack.php b/src/Label/vendor/php-ds/php-ds/src/Stack.php new file mode 100644 index 00000000..53b103fc --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Stack.php @@ -0,0 +1,198 @@ + + */ +final class Stack implements Collection, \ArrayAccess +{ + use Traits\GenericCollection; + + /** + * @var Vector internal vector to store values of the stack. + * + * @psalm-var Vector + */ + private $vector; + + /** + * Creates an instance using the values of an array or Traversable object. + * + * @param iterable $values + * + * @psalm-param iterable $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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php b/src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php new file mode 100644 index 00000000..f59834ec --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Traits/Capacity.php @@ -0,0 +1,130 @@ +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(); + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php b/src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php new file mode 100644 index 00000000..650230ce --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Traits/GenericCollection.php @@ -0,0 +1,75 @@ +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) . ')'; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php b/src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php new file mode 100644 index 00000000..57678308 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Traits/GenericSequence.php @@ -0,0 +1,419 @@ + + */ + private $array = []; + + /** + * @param iterable $values + * + * @psalm-param iterable $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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php b/src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php new file mode 100644 index 00000000..01bd25aa --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Traits/SquaredCapacity.php @@ -0,0 +1,58 @@ +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(); + } + } +} diff --git a/src/Label/vendor/php-ds/php-ds/src/Vector.php b/src/Label/vendor/php-ds/php-ds/src/Vector.php new file mode 100644 index 00000000..adc38dc4 --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/src/Vector.php @@ -0,0 +1,35 @@ + + */ +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; + } +} diff --git a/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php b/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php new file mode 100644 index 00000000..8fc0574a --- /dev/null +++ b/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php @@ -0,0 +1,7 @@ + Date: Fri, 28 Jul 2023 06:15:18 +0000 Subject: [PATCH 02/14] Multiple QSOs --- application/controllers/Labels.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 05014557..3796734c 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -187,13 +187,10 @@ class Labels extends CI_Controller { $text = ''; $current_callsign = ''; $qso_data = []; - $whole_qsos=[]; foreach($qsos as $qso) { if ($qso->COL_CALL !== $current_callsign) { if (!empty($qso_data)) { $this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos); - // $this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos); - array_push($whole_qsos,$qso_data); $qso_data = []; } $current_callsign = $qso->COL_CALL; @@ -210,8 +207,7 @@ class Labels extends CI_Controller { ]; } if (!empty($qso_data)) { - $this->makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos); - array_push($whole_qsos,$qso_data); + $this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos); } } // New begin @@ -231,7 +227,7 @@ function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label $count_qso++; if($count_qso == $qso_per_label){ - generateLabel($pdf, $current_callsign, $tableData); + generateLabel($pdf, $current_callsign, $tableData,$count_qso); $tableData = []; // reset the data $count_qso = 0; // reset the counter } @@ -239,19 +235,19 @@ function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label } // generate label for remaining QSOs if($count_qso > 0){ - $this->generateLabel($pdf, $current_callsign, $tableData); + $this->generateLabel($pdf, $current_callsign, $tableData,$count_qso); $preliminaryData = []; // reset the data } } -function generateLabel($pdf, $current_callsign, $tableData){ +function generateLabel($pdf, $current_callsign, $tableData,$numofqsos){ $builder = new \AsciiTable\Builder(); $builder->addRows($tableData); - $text = "Confirming QSO with "; + $text = "Confirming QSO".($numofqsos>1 ? 's' : '')." with "; $text .= $current_callsign; $text .= "\n"; $text .= $builder->renderTable(); - $text .= "\nThanks for the QSO"; + $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); $pdf->Add_Label($text); } From 4752b70649f8198b152f92c9b724d314bc1425b0 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 06:36:57 +0000 Subject: [PATCH 03/14] SAT-Addon --- application/controllers/Labels.php | 74 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 3796734c..a08d2870 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -212,43 +212,47 @@ class Labels extends CI_Controller { } // New begin -function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { - $tableData = []; - $count_qso = 0; + function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { + $tableData = []; + $count_qso = 0; + $qso=[]; + foreach ($preliminaryData as $key => $row) { + $qso=$row; + $rowData = [ + 'Date/UTC' => $row['time'], + 'Band' => $row['band'], + 'Mode' => $row['mode'], + 'RST' => $row['rst'], + ]; + $tableData[] = $rowData; + $count_qso++; - foreach ($preliminaryData as $key => $row) { - $rowData = [ - 'Date/UTC' => $row['time'], - 'Band' => $row['band'], - 'Mode' => $row['mode'], - 'RST' => $row['rst'], - ]; - $tableData[] = $rowData; - $count_qso++; + if($count_qso == $qso_per_label){ + generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso); + $tableData = []; // reset the data + $count_qso = 0; // reset the counter + } + unset($preliminaryData[$key]); + } + // generate label for remaining QSOs + if($count_qso > 0){ + $this->generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso); + $preliminaryData = []; // reset the data + } + } - if($count_qso == $qso_per_label){ - generateLabel($pdf, $current_callsign, $tableData,$count_qso); - $tableData = []; // reset the data - $count_qso = 0; // reset the counter - } - unset($preliminaryData[$key]); - } - // generate label for remaining QSOs - if($count_qso > 0){ - $this->generateLabel($pdf, $current_callsign, $tableData,$count_qso); - $preliminaryData = []; // reset the data - } -} - -function generateLabel($pdf, $current_callsign, $tableData,$numofqsos){ - $builder = new \AsciiTable\Builder(); - $builder->addRows($tableData); - $text = "Confirming QSO".($numofqsos>1 ? 's' : '')." with "; - $text .= $current_callsign; - $text .= "\n"; - $text .= $builder->renderTable(); - $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); - $pdf->Add_Label($text); +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']); + } + $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); + $pdf->Add_Label($text); } // New End From 71d861f8b7f47d1ee264d42b0bbf887f93c3cb58 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 06:49:50 +0000 Subject: [PATCH 04/14] Take care of max-lbl-count --- application/controllers/Labels.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index a08d2870..775cc840 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -228,7 +228,7 @@ class Labels extends CI_Controller { $count_qso++; if($count_qso == $qso_per_label){ - generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso); + $this->generateLabel($pdf, $current_callsign, $tableData,$count_qso,$qso); $tableData = []; // reset the data $count_qso = 0; // reset the counter } From 4bb448d369202b9f274732aa31dfaf5859ebaf6e Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 07:51:52 +0000 Subject: [PATCH 05/14] Removed font from settings. Fixt it to DejaVuSans --- application/controllers/Labels.php | 108 ++++++++-------------------- application/views/labels/create.php | 25 +------ application/views/labels/edit.php | 26 +------ 3 files changed, 33 insertions(+), 126 deletions(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 775cc840..f7193fc7 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -8,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 |-------------------------------------------------------------------------- @@ -16,7 +16,7 @@ class Labels extends CI_Controller { | This Controller handles all things Labels, creating, editing and printing | | - */ + */ function __construct() { parent::__construct(); @@ -35,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"; @@ -53,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); - + } /* @@ -63,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'); @@ -82,10 +82,10 @@ class Labels extends CI_Controller { { $this->load->model('labels_model'); $this->labels_model->addLabel(); - + redirect('labels'); } - + } public function printids() { @@ -104,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( @@ -145,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); } @@ -169,20 +171,6 @@ 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 = ''; @@ -210,7 +198,7 @@ class Labels extends CI_Controller { $this->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos); } } -// New begin + // New begin function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { $tableData = []; @@ -241,56 +229,22 @@ class Labels extends CI_Controller { } } -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']); - } - $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); - $pdf->Add_Label($text); -} - -// New End - - function makeLabel($pdf, $current_callsign, $qso_data, $numberofqsos) { - $text = 'To: ' . $current_callsign . "\n\n"; - $count = 0; - $qsotext = ''; - foreach ($qso_data as $key => $qso) { - $time = strtotime($qso['time']); - $myFormatForView = date("d/m/Y H:i", $time); - - 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']); - } - $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]); + 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']); } - - if ($qsotext != '') { - $text .= $qsotext; - $text .= "\n" . 'Thanks for QSOs.'; - $pdf->Add_Label($text); - } - + $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); + $pdf->Add_Label($text); } + // New End + public function edit($id) { $this->load->model('labels_model'); diff --git a/application/views/labels/create.php b/application/views/labels/create.php index 046d9674..daf88f55 100644 --- a/application/views/labels/create.php +++ b/application/views/labels/create.php @@ -111,29 +111,6 @@ -
- -
- -
-
- @@ -141,4 +118,4 @@ -
\ No newline at end of file +
diff --git a/application/views/labels/edit.php b/application/views/labels/edit.php index 076524d9..695fded7 100644 --- a/application/views/labels/edit.php +++ b/application/views/labels/edit.php @@ -110,30 +110,6 @@ - -
- -
- -
-
- @@ -141,4 +117,4 @@ -
\ No newline at end of file +
From df25d8c1ae461cf3d40465414afc89caf4c22721 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 08:21:37 +0000 Subject: [PATCH 06/14] Enhance sorting --- application/models/Labels_model.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/models/Labels_model.php b/application/models/Labels_model.php index c0c50494..0ec5d08a 100644 --- a/application/models/Labels_model.php +++ b/application/models/Labels_model.php @@ -123,6 +123,9 @@ 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_TIME_ON", "ASC"); + $this->db->order_by("COL_MODE", "ASC"); $query = $this->db->get($this->config->item('table_name')); return $query; @@ -139,4 +142,4 @@ class Labels_model extends CI_Model { return $query; } -} \ No newline at end of file +} From 77821a49ffc754d1aa082f49b9e437e76d046e9d Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 08:28:17 +0000 Subject: [PATCH 07/14] Split labels when SAT/Non-SAT --- application/controllers/Labels.php | 4 +++- application/models/Labels_model.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index f7193fc7..0ebf411b 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -174,14 +174,16 @@ class Labels extends CI_Controller { 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->finalizeData($pdf, $current_callsign, $qso_data, $numberofqsos); $qso_data = []; } $current_callsign = $qso->COL_CALL; + $current_sat = $qso->COL_SAT_NAME; } $qso_data[] = [ diff --git a/application/models/Labels_model.php b/application/models/Labels_model.php index 0ec5d08a..bdce7eb8 100644 --- a/application/models/Labels_model.php +++ b/application/models/Labels_model.php @@ -124,6 +124,7 @@ class Labels_model extends CI_Model { $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')); From 2e1329a1593004a5fb302a889961616027ef06b0 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 09:24:01 +0000 Subject: [PATCH 08/14] Added TNX/PSE to label --- application/controllers/Labels.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 0ebf411b..34ed4e58 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -194,6 +194,7 @@ 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)) { @@ -242,6 +243,7 @@ class Labels extends CI_Controller { $text .= "\n".'Satellite: '.$qso['sat'].' Mode: '.strtoupper($qso['sat_mode']); } $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); + $text .= " | ".($qso['qsl_recvd'] <> 'Y' ? 'TNX' : 'PSE')." QSL"; $pdf->Add_Label($text); } From 155b103e3ac08d53e76497e71315473f34e22a4b Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 09:30:33 +0000 Subject: [PATCH 09/14] removed demos --- src/Label/generatelabels-noalternate.php | 110 --------------------- src/Label/generatelabels.php | 120 ----------------------- 2 files changed, 230 deletions(-) delete mode 100644 src/Label/generatelabels-noalternate.php delete mode 100644 src/Label/generatelabels.php diff --git a/src/Label/generatelabels-noalternate.php b/src/Label/generatelabels-noalternate.php deleted file mode 100644 index 4b49de3a..00000000 --- a/src/Label/generatelabels-noalternate.php +++ /dev/null @@ -1,110 +0,0 @@ -AddPage(); -$fontName = 'DejaVuSans'; -$pdf->AddFont($fontName,'','DejaVuSansMono.ttf',true); -$pdf->AddFont($fontName,'B','DejaVuSansMono.ttf',true); -$pdf->SetFont($fontName,'',6); -$con = mysqli_connect("localhost","USERNAME","PASSWORD","DATABASE"); - -// Check connection -if (mysqli_connect_errno()) { - echo "Failed to connect to MySQL: " . mysqli_connect_error(); -} - -$sql = "SELECT c.COL_PRIMARY_KEY, c.COL_CALL, c.COL_TIME_ON, c.COL_MODE, c.COL_BAND, c.COL_RST_SENT, p.station_gridsquare, p.station_cnty, p.state, p.station_id FROM TABLE_HRD_CONTACTS_V01 c INNER JOIN station_profile p ON c.station_id=p.station_id WHERE c.COL_QSL_SENT LIKE 'R' ORDER BY c.COL_CALL,c.COL_TIME_ON;"; -$result = $con->query($sql); - -function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label) { - $tableData = []; - $count_qso = 0; - - foreach ($preliminaryData as $key => $row) { - $rowData = [ - 'Date/Time UTC' => $row['Date/Time UTC'], - 'Band' => $row['Band'], - 'Mode' => $row['Mode'], - 'RST' => $row['RST'], - 'My Grid' => $row['My Grid'], - 'My County' => $row['My County'], - ]; - $tableData[] = $rowData; - $count_qso++; - - if($count_qso == $qso_per_label){ - generateLabel($pdf, $current_callsign, $tableData); - $tableData = []; // reset the data - $count_qso = 0; // reset the counter - } - unset($preliminaryData[$key]); - } - // generate label for remaining QSOs - if($count_qso > 0){ - generateLabel($pdf, $current_callsign, $tableData); - $preliminaryData = []; // reset the data - } -} - -function generateLabel($pdf, $current_callsign, $tableData){ - $builder = new \AsciiTable\Builder(); - $builder->addRows($tableData); - $text = "Confirming QSO with "; - $text .= $current_callsign; - $text .= "\n"; - $text .= $builder->renderTable(); - $text .= "\nThanks for the QSO"; - $pdf->Add_Label($text); -} - -if ($result->num_rows > 0) { - $current_callsign = ''; - $preliminaryData = []; - - // output data of each row - while($row = $result->fetch_assoc()) { - if ($row['COL_CALL'] !== $current_callsign) { - while (!empty($preliminaryData)) { - finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label); - } - $current_callsign = $row['COL_CALL']; - } - - $time = strtotime($row["COL_TIME_ON"]); - $myFormatForView = date("Y-m-y H:i", $time); - - $band = $row['COL_BAND']; - $mode = $row['COL_MODE']; - $rst = $row['COL_RST_SENT']; - $grid = $row['station_gridsquare']; - $county = $row['station_cnty'] . ',' . $row['state']; - - - // Add the row of data to the preliminary data - $preliminaryData[] = [ - 'Date/Time UTC' => $myFormatForView, - 'Band' => $band, - 'Mode' => $mode, - 'RST' => $rst, - 'My Grid' => $grid, - 'My County' => $county, - ]; - } - - while (!empty($preliminaryData)) { - finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label); - } -} else { - echo "0 results"; -} - -$pdf->Output(); - -?> diff --git a/src/Label/generatelabels.php b/src/Label/generatelabels.php deleted file mode 100644 index 475f4af5..00000000 --- a/src/Label/generatelabels.php +++ /dev/null @@ -1,120 +0,0 @@ -AddPage(); -$fontName = 'DejaVuSans'; -$pdf->AddFont($fontName,'','DejaVuSansMono.ttf',true); -$pdf->AddFont($fontName,'B','DejaVuSansMono.ttf',true); -$pdf->SetFont($fontName,'',6); -$con = mysqli_connect("localhost","USERNAME","PASSWORD","DATABASE"); - -// Check connection -if (mysqli_connect_errno()) { - echo "Failed to connect to MySQL: " . mysqli_connect_error(); -} - -$sql = "SELECT c.COL_PRIMARY_KEY, c.COL_CALL, c.COL_TIME_ON, c.COL_MODE, c.COL_BAND, c.COL_RST_SENT, p.station_gridsquare, p.station_cnty, p.state, p.station_id FROM TABLE_HRD_CONTACTS_V01 c INNER JOIN station_profile p ON c.station_id=p.station_id WHERE c.COL_QSL_SENT LIKE 'R' ORDER BY c.COL_CALL,c.COL_TIME_ON;"; -$result = $con->query($sql); - -function finalizeData($pdf, $current_callsign, &$preliminaryData, $qso_per_label, &$hasNonAlternateCounty) { - $tableData = []; - $count_qso = 0; - - foreach ($preliminaryData as $key => $row) { - $rowData = [ - 'Date/Time UTC' => $row['Date/Time UTC'], - 'Band' => $row['Band'], - 'Mode' => $row['Mode'], - 'RST' => $row['RST'], - ]; - if ($hasNonAlternateCounty) { - $rowData['My Grid'] = $row['My Grid']; - $rowData['My County'] = $row['My County']; - } - $tableData[] = $rowData; - $count_qso++; - - if($count_qso == $qso_per_label){ - generateLabel($pdf, $current_callsign, $tableData); - $tableData = []; // reset the data - $count_qso = 0; // reset the counter - } - unset($preliminaryData[$key]); - } - // generate label for remaining QSOs - if($count_qso > 0){ - generateLabel($pdf, $current_callsign, $tableData); - $preliminaryData = []; // reset the data - } -} - -function generateLabel($pdf, $current_callsign, $tableData){ - $builder = new \AsciiTable\Builder(); - $builder->addRows($tableData); - $text = "Confirming QSO with "; - $text .= $current_callsign; - $text .= "\n"; - $text .= $builder->renderTable(); - $text .= "\nThanks for the QSO"; - $pdf->Add_Label($text); -} - -if ($result->num_rows > 0) { - $current_callsign = ''; - $preliminaryData = []; - $hasNonAlternateCounty = false; - - // output data of each row - while($row = $result->fetch_assoc()) { - if ($row['COL_CALL'] !== $current_callsign) { - while (!empty($preliminaryData)) { - finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label, $hasNonAlternateCounty); - } - $current_callsign = $row['COL_CALL']; - $hasNonAlternateCounty = false; - } - - $time = strtotime($row["COL_TIME_ON"]); - $myFormatForView = date("Y-m-y H:i", $time); - - $band = $row['COL_BAND']; - $mode = $row['COL_MODE']; - $rst = $row['COL_RST_SENT']; - $grid = $row['station_gridsquare']; - $county = $row['station_cnty'] . ',' . $row['state']; - - if ($county !== $alternate_county) { - $hasNonAlternateCounty = true; - } - - // Add the row of data to the preliminary data - $preliminaryData[] = [ - 'Date/Time UTC' => $myFormatForView, - 'Band' => $band, - 'Mode' => $mode, - 'RST' => $rst, - 'My Grid' => $grid, - 'My County' => $county, - ]; - } - - while (!empty($preliminaryData)) { - finalizeData($pdf, $current_callsign, $preliminaryData, $qso_per_label, $hasNonAlternateCounty); - } -} else { - echo "0 results"; -} - -$pdf->Output(); - -?> From c4df2d77d084de14a067b1926125afea90f3e274 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 09:31:39 +0000 Subject: [PATCH 10/14] flip PSE/TNX --- application/controllers/Labels.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 34ed4e58..d997e5c7 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -243,7 +243,7 @@ class Labels extends CI_Controller { $text .= "\n".'Satellite: '.$qso['sat'].' Mode: '.strtoupper($qso['sat_mode']); } $text .= "\nThanks for the QSO".($numofqsos>1 ? 's' : ''); - $text .= " | ".($qso['qsl_recvd'] <> 'Y' ? 'TNX' : 'PSE')." QSL"; + $text .= " | ".($qso['qsl_recvd'] == 'Y' ? 'TNX' : 'PSE')." QSL"; $pdf->Add_Label($text); } From 271c4ff20e9165b6be67e4a0db9ae90c8c357cb4 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 09:47:05 +0000 Subject: [PATCH 11/14] removing files --- src/Label/vendor/php-ds/php-ds/tests/bootstrap.php | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/Label/vendor/php-ds/php-ds/tests/bootstrap.php diff --git a/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php b/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php deleted file mode 100644 index 8fc0574a..00000000 --- a/src/Label/vendor/php-ds/php-ds/tests/bootstrap.php +++ /dev/null @@ -1,7 +0,0 @@ - Date: Fri, 28 Jul 2023 09:48:14 +0000 Subject: [PATCH 12/14] removed more unnecessary files --- .../php-to-ascii-table/tests/BuilderTest.php | 328 ------------------ .../php-to-ascii-table/tests/CellTest.php | 52 --- .../php-to-ascii-table/tests/RowTest.php | 24 -- .../php-to-ascii-table/tests/TableTest.php | 87 ----- 4 files changed, 491 deletions(-) delete mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/BuilderTest.php delete mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php delete mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php delete mode 100644 src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/BuilderTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/BuilderTest.php deleted file mode 100644 index b5dbfce3..00000000 --- a/src/Label/vendor/malios/php-to-ascii-table/tests/BuilderTest.php +++ /dev/null @@ -1,328 +0,0 @@ -addRow(['age' => 21, 'name' => 'John']); - - $person = new class implements \JsonSerializable { - - function jsonSerialize() - { - return [ - 'age' => 32, - 'name' => 'Bill' - ]; - } - }; - - $builder->addRow($person); - - $table = $builder->getTable(); - $rows = $table->getRows(); - - $this->assertEquals(21, $rows[0]->getCell('age')->getValue()); - $this->assertEquals('John', $rows[0]->getCell('name')->getValue()); - - $this->assertEquals(32, $rows[1]->getCell('age')->getValue()); - $this->assertEquals('Bill', $rows[1]->getCell('name')->getValue()); - } - - public function testAddInvalidRow() - { - $this->expectException(BuilderException::class); - - $person = new class { - public $name; - }; - - $person->name = 'Rick'; - - $builder = new Builder(); - $builder->addRow($person); - } - - public function testRenderEmptyTable() - { - $this->expectException(BuilderException::class); - - $builder = new Builder(); - $builder->renderTable(); - } - - public function testRender() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'name' => 'John', - 'age' => 23, - 'sex' => 'male' - ], - [ - 'name' => 'Catherine', - 'age' => 22, - 'sex' => 'female' - ], - [ - 'name' => 'Johnathan', - 'age' => 44, - 'sex' => 'male' - ] - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testRenderWithSomeEmptyCells() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'name' => 'John', - 'age' => 23, - 'sex' => 'male' - ], - [ - 'name' => 'Catherine', - 'sex' => 'female' - ], - [ - 'name' => 'Johnathan', - 'age' => 44, - ] - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testShowsOnlyVisibleColumns() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'name' => 'John', - 'age' => 23, - 'sex' => 'male' - ], - [ - 'name' => 'Catherine', - 'age' => 22, - 'sex' => 'female' - ], - [ - 'name' => 'Johnathan', - 'age' => 44, - 'sex' => 'male' - ] - ]); - - $builder->showColumns(['name', 'age']); - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testRenderTableWithFloatingPoint() - { - $builder = new 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 - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testRenderTableWithCyrillicWord() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'name' => 'John', - 'age' => 21 - ], - [ - 'name' => 'Иван', - 'age' => 23 - ] - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testRenderWithCyrillicColumnNames() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'имя' => 'Джон', - 'год' => 21 - ], - [ - 'имя' => 'Иван', - 'год' => 23 - ] - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - public function testRenderWithChineseColumnNames() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'language' => 'English', - 'greeting' => 'Hello, World' - ], - [ - 'language' => 'mixed', - 'greeting' => 'Hello, 世界' - ] - ]); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } - - public function testRenderWithTitle() - { - $builder = new Builder(); - $builder->addRows([ - [ - 'language' => 'English', - 'greeting' => 'Hello, World' - ], - [ - 'language' => 'mixed', - 'greeting' => 'Hello, 世界' - ] - ]); - $builder->setTitle('Greetings'); - - $result = $builder->renderTable(); - - $expected = <<assertEquals($expected, $result); - } -} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php deleted file mode 100644 index 66b823db..00000000 --- a/src/Label/vendor/malios/php-to-ascii-table/tests/CellTest.php +++ /dev/null @@ -1,52 +0,0 @@ -assertEquals('21', $cell->getValue()); - $this->assertEquals(2, $cell->getWidth()); - - $cell->setValue(123); - $this->assertEquals('123', $cell->getValue()); - $this->assertEquals(3, $cell->getWidth()); - - $ageObject = new class (2008) { - private $year; - - function __construct(int $year) - { - $this->year = $year; - } - - function __toString() - { - return strval(2017 - $this->year); - } - }; - - $cell->setValue($ageObject); - $this->assertEquals(1, $cell->getWidth()); - - $floatCell = new Cell('price', 100.00); - $this->assertEquals("100.00", $floatCell->getValue()); - - $floatCell->setValue(99.99); - $this->assertEquals("99.99", $floatCell->getValue()); - } - - public function testCellWidthWithMultiByteCharacters() - { - $cell = new Cell('name', 'Иван'); - $this->assertEquals(4, $cell->getWidth()); - - $cell = new Cell('message', 'Hello, 世界'); // 世界 - this string is with width 4 - $this->assertEquals(11, $cell->getWidth()); - } -} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php deleted file mode 100644 index f1bdd6ff..00000000 --- a/src/Label/vendor/malios/php-to-ascii-table/tests/RowTest.php +++ /dev/null @@ -1,24 +0,0 @@ -addCell(new Cell('name', 'John')); - $row->addCell(new Cell('name', 'Rick')); - - $this->assertCount(1, $row->getCells()); - - $cell = $row->getCells()->get('name'); - - $this->assertEquals($cell->getColumnName(), 'name'); - $this->assertEquals($cell->getValue(), 'Rick'); - } -} diff --git a/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php b/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php deleted file mode 100644 index 86661e04..00000000 --- a/src/Label/vendor/malios/php-to-ascii-table/tests/TableTest.php +++ /dev/null @@ -1,87 +0,0 @@ -setVisibleColumns(['name', 'age', 'location', 'sex']); - - $set = new Set(); - $set->add('name'); - $set->add('age'); - $set->add('location'); - $set->add('sex'); - - self::assertEquals(0, $set->diff($table->getVisibleColumns())->count()); - self::assertEquals(0, $table->getVisibleColumns()->diff($set)->count()); - } - - public function testGetVisibleColumnsWhenNotSet() - { - $row = new Row(); - $row->addCell(new Cell('name', 'Catherine')); - $row->addCell(new Cell('sex', 'female')); - $row->addCell(new Cell('height', 168)); - - $table = new Table(); - $table->addRow($row); - - $this->assertSame(['name', 'sex', 'height'], $table->getVisibleColumns()->toArray()); - } - - public function testGetAllColumns() - { - $row = new Row(); - $row->addCell(new Cell('name', 'Bill')); - $row->addCell(new Cell('age', 21)); - - $row2 = new Row(); - $row2->addCell(new Cell('name', 'John')); - $row2->addCell(new Cell('sex', 'male')); - - $row3 = new Row(); - $row3->addCell(new Cell('name', 'Catherine')); - $row3->addCell(new Cell('sex', 'female')); - $row3->addCell(new Cell('height', 168)); - - $table = new Table(); - $table->addRow($row); - $table->addRow($row2); - $table->addRow($row3); - - $this->assertSame(['name', 'age', 'sex', 'height'], $table->getAllColumns()->toArray()); - } - - public function testColumnWidth() - { - $row = new Row(); - $row->addCell(new Cell('name', 'Jon')); - $row->addCell(new Cell('age', 21)); - - $row2 = new Row(); - $row2->addCell(new Cell('name', 'John')); - $row2->addCell(new Cell('age', 32)); - - $row3 = new Row(); - $row3->addCell(new Cell('name', 'Johnathan')); - $row3->addCell(new Cell('age', 23)); - - $table = new Table(); - - $table->addRow($row); - $table->addRow($row2); - $table->addRow($row3); - - $this->assertEquals(3, $table->getColumnWidth('age')); - $this->assertEquals(9, $table->getColumnWidth('name')); - } -} From d0c55fe628c8b79f61627298b386eeeeb8683e28 Mon Sep 17 00:00:00 2001 From: int2001 Date: Fri, 28 Jul 2023 10:13:15 +0000 Subject: [PATCH 13/14] Time-Formatter included --- application/controllers/Labels.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index d997e5c7..5bf9dd68 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -209,8 +209,10 @@ class Labels extends CI_Controller { $qso=[]; foreach ($preliminaryData as $key => $row) { $qso=$row; + $time = strtotime($qso['time']); + $myFormatForView = date("Y-m-d H:i", $time); $rowData = [ - 'Date/UTC' => $row['time'], + 'Date/UTC' => $myFormatForView, 'Band' => $row['band'], 'Mode' => $row['mode'], 'RST' => $row['rst'], From 00c98609fd9c32095da3297c4cb6a06f3a8c27da Mon Sep 17 00:00:00 2001 From: phl0 Date: Fri, 28 Jul 2023 12:19:01 +0200 Subject: [PATCH 14/14] Minor changes to output --- application/controllers/Labels.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/controllers/Labels.php b/application/controllers/Labels.php index 5bf9dd68..30633250 100644 --- a/application/controllers/Labels.php +++ b/application/controllers/Labels.php @@ -212,7 +212,7 @@ class Labels extends CI_Controller { $time = strtotime($qso['time']); $myFormatForView = date("Y-m-d H:i", $time); $rowData = [ - 'Date/UTC' => $myFormatForView, + 'Date/Time (UTC)' => $myFormatForView, 'Band' => $row['band'], 'Mode' => $row['mode'], 'RST' => $row['rst'], @@ -242,7 +242,7 @@ class Labels extends CI_Controller { $text .= "\n"; $text .= $builder->renderTable(); if($qso['sat'] != "") { - $text .= "\n".'Satellite: '.$qso['sat'].' Mode: '.strtoupper($qso['sat_mode']); + $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";