Autosave: 20260516-003633
|
Before Width: | Height: | Size: 373 KiB |
BIN
assets/uploads/vouchers/6a065123cd904-987.png
Normal file
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 365 KiB |
BIN
assets/uploads/vouchers/6a0656974ed8f-153.png
Normal file
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 393 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 160 KiB |
BIN
assets/uploads/vouchers/6a07772927899-Screenshot_341.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
assets/uploads/vouchers/6a07814db2836-Screenshot_342.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
assets/uploads/vouchers/6a07835ddd8ef-Screenshot_343.png
Normal file
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 355 KiB |
|
After Width: | Height: | Size: 311 KiB |
BIN
assets/uploads/vouchers/6a0791cba4882-1787.png
Normal file
|
After Width: | Height: | Size: 415 KiB |
BIN
assets/uploads/vouchers/6a0792665505b-640.png
Normal file
|
After Width: | Height: | Size: 349 KiB |
BIN
assets/uploads/vouchers/6a0793286d90e-700.png
Normal file
|
After Width: | Height: | Size: 361 KiB |
BIN
assets/uploads/vouchers/6a0793e78c53d-448.png
Normal file
|
After Width: | Height: | Size: 369 KiB |
BIN
assets/uploads/vouchers/6a07949d343ea-648.png
Normal file
|
After Width: | Height: | Size: 370 KiB |
BIN
assets/uploads/vouchers/6a07951bbf9c0-947.png
Normal file
|
After Width: | Height: | Size: 367 KiB |
BIN
assets/uploads/vouchers/6a07a0832530c-Screenshot_344.png
Normal file
|
After Width: | Height: | Size: 235 KiB |
BIN
assets/uploads/vouchers/6a07aa4be8ee8-476.png
Normal file
|
After Width: | Height: | Size: 293 KiB |
5
composer.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"shuchkin/simplexlsxgen": "^1.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
72
composer.lock
generated
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"_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": "7b99e2d4bb14267c09672e3efc5786bd",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "shuchkin/simplexlsxgen",
|
||||||
|
"version": "1.5.17",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shuchkin/simplexlsxgen.git",
|
||||||
|
"reference": "162a4a9b929611d69dbd6f1a7f42af483a87b537"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shuchkin/simplexlsxgen/zipball/162a4a9b929611d69dbd6f1a7f42af483a87b537",
|
||||||
|
"reference": "162a4a9b929611d69dbd6f1a7f42af483a87b537",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-zlib": "*",
|
||||||
|
"php": ">=5.4"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/SimpleXLSXGen.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sergey Shuchkin (SMSPILOT)",
|
||||||
|
"email": "sergey.shuchkin@gmail.com",
|
||||||
|
"homepage": "https://shuchkin.ru/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Export data to Excel XLSx file. PHP XLSX generator.",
|
||||||
|
"homepage": "https://github.com/shuchkin/simplexlsxgen",
|
||||||
|
"keywords": [
|
||||||
|
"backend",
|
||||||
|
"creator",
|
||||||
|
"excel",
|
||||||
|
"generator",
|
||||||
|
"php",
|
||||||
|
"writer",
|
||||||
|
"xlsx"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shuchkin/simplexlsxgen/issues",
|
||||||
|
"source": "https://github.com/shuchkin/simplexlsxgen/tree/1.5.17"
|
||||||
|
},
|
||||||
|
"time": "2026-05-03T13:04:04+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.3.0"
|
||||||
|
}
|
||||||
@ -5,6 +5,9 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
require_once 'db/config.php';
|
require_once 'db/config.php';
|
||||||
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
|
use Shuchkin\SimpleXLSXGen;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
@ -12,7 +15,7 @@ try {
|
|||||||
|
|
||||||
// Filtramos solo los pedidos que están en estado 'ROTULADO 📦' y son de la agencia 'SHALOM'
|
// Filtramos solo los pedidos que están en estado 'ROTULADO 📦' y son de la agencia 'SHALOM'
|
||||||
$query = "
|
$query = "
|
||||||
SELECT p.dni_cliente, p.celular, p.sede_envio, p.agencia
|
SELECT p.dni_cliente, p.celular, p.sede_envio, p.agencia, p.producto, p.cantidad
|
||||||
FROM pedidos p
|
FROM pedidos p
|
||||||
WHERE p.estado = 'ROTULADO 📦'
|
WHERE p.estado = 'ROTULADO 📦'
|
||||||
AND p.agencia LIKE '%SHALOM%'
|
AND p.agencia LIKE '%SHALOM%'
|
||||||
@ -30,35 +33,23 @@ try {
|
|||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$pedidos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$pedidos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$filename = "masivo_shalom";
|
$data = [];
|
||||||
if ($type === 'terrestre') $filename .= "_terrestre";
|
// Header
|
||||||
if ($type === 'aereo') $filename .= "_aereo";
|
$data[] = [
|
||||||
$filename .= ".xls";
|
'DESTINATARIO (DOC)',
|
||||||
|
'TELF. DESTINATARIO',
|
||||||
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
|
'CONTACTO (DOC)',
|
||||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
'TELF. CONTACTO',
|
||||||
header('Pragma: no-cache');
|
'NRO GRR',
|
||||||
header('Expires: 0');
|
'ORIGEN',
|
||||||
|
'DESTINO',
|
||||||
$output = '<html><head><meta charset="utf-8">
|
'MERCADERIA',
|
||||||
<style>
|
'ALTO',
|
||||||
.text { mso-number-format:"\@"; }
|
'ANCHO',
|
||||||
.preserve-space { white-space: pre; }
|
'LARGO',
|
||||||
</style>
|
'PESO',
|
||||||
</head><body>';
|
'CANTIDAD'
|
||||||
$output .= '<table border="1">';
|
];
|
||||||
$output .= '<thead>';
|
|
||||||
$output .= '<tr>';
|
|
||||||
$output .= '<th>DESTINATARIO (DOC)</th>';
|
|
||||||
$output .= '<th>TELF. DESTINATARIO</th>';
|
|
||||||
$output .= '<th>CONTACTO (DOC)</th>';
|
|
||||||
$output .= '<th>TELF. CONTACTO</th>';
|
|
||||||
$output .= '<th>NRO GRR</th>';
|
|
||||||
$output .= '<th>ORIGEN</th>';
|
|
||||||
$output .= '<th>DESTINO</th>';
|
|
||||||
$output .= '</tr>';
|
|
||||||
$output .= '</thead>';
|
|
||||||
$output .= '<tbody>';
|
|
||||||
|
|
||||||
foreach ($pedidos as $pedido) {
|
foreach ($pedidos as $pedido) {
|
||||||
// Limpiar el DNI: solo números
|
// Limpiar el DNI: solo números
|
||||||
@ -72,31 +63,52 @@ try {
|
|||||||
$celular = substr($celular, 2);
|
$celular = substr($celular, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
$celular = htmlspecialchars($celular);
|
|
||||||
|
|
||||||
$destino_raw = str_ireplace('shalom:', '', $pedido['sede_envio'] ?? '');
|
$destino_raw = str_ireplace('shalom:', '', $pedido['sede_envio'] ?? '');
|
||||||
$parts = explode('/', $destino_raw);
|
|
||||||
$destino = trim(end($parts));
|
// Buscamos la última parte después del slash
|
||||||
|
$last_slash_pos = mb_strrpos($destino_raw, '/');
|
||||||
|
if ($last_slash_pos !== false) {
|
||||||
|
$destino = mb_substr($destino_raw, $last_slash_pos + 1);
|
||||||
|
} else {
|
||||||
|
$destino = $destino_raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo quitamos UN espacio al inicio y UN espacio al final si existen,
|
||||||
|
// para respetar espacios dobles internos o intencionales.
|
||||||
|
if (str_starts_with($destino, ' ')) {
|
||||||
|
$destino = substr($destino, 1);
|
||||||
|
}
|
||||||
|
if (str_ends_with($destino, ' ')) {
|
||||||
|
$destino = substr($destino, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
// Convertir a mayúsculas
|
// Convertir a mayúsculas
|
||||||
$destino = mb_strtoupper($destino, 'UTF-8');
|
$destino = mb_strtoupper($destino, 'UTF-8');
|
||||||
$destino = htmlspecialchars($destino);
|
|
||||||
|
|
||||||
$output .= '<tr>';
|
$data[] = [
|
||||||
$output .= '<td class="text">' . $dni . '</td>'; // Solo el número de DNI con formato texto
|
(string)$dni,
|
||||||
$output .= '<td class="text">' . $celular . '</td>'; // Teléfono con formato texto
|
(string)$celular,
|
||||||
$output .= '<td></td>'; // Contacto vacío
|
'',
|
||||||
$output .= '<td></td>'; // Telf Contacto vacío
|
'',
|
||||||
$output .= '<td></td>'; // NRO GRR vacío
|
'',
|
||||||
$output .= '<td>AV MEXICO CO</td>'; // ORIGEN fijo
|
'AV MEXICO CO',
|
||||||
$output .= '<td class="preserve-space">' . $destino . '</td>'; // Destino
|
$destino,
|
||||||
$output .= '</tr>';
|
'PAQUETE XXS', // MERCADERIA
|
||||||
|
'0.1', // ALTO
|
||||||
|
'0.1', // ANCHO
|
||||||
|
'0.1', // LARGO
|
||||||
|
'0.1', // PESO
|
||||||
|
'1' // CANTIDAD
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$output .= '</tbody>';
|
$filename = "masivo_shalom";
|
||||||
$output .= '</table>';
|
if ($type === 'terrestre') $filename .= "_terrestre";
|
||||||
$output .= '</body></html>';
|
if ($type === 'aereo') $filename .= "_aereo";
|
||||||
|
$filename .= "_" . date('Y-m-d') . ".xlsx";
|
||||||
|
|
||||||
echo $output;
|
SimpleXLSXGen::fromArray($data)->downloadAs($filename);
|
||||||
|
exit;
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
header('HTTP/1.1 500 Internal Server Error');
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
|||||||
25
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
$err,
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInit7443bc322605554a2a2e26076e20764b::getLoader();
|
||||||
585
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,585 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, string[]>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool[]
|
||||||
|
* @psalm-var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var self[]
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ?string $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] Array of classname => path
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $classMap Class to filename map
|
||||||
|
* @psalm-param array<string, string> $classMap
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param string[]|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param string[]|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param string[]|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param string[]|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return self[]
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
359
vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints((string) $constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||||
|
self::$installed = $installed[count($installed) - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array()) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
||||||
11
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
'Shuchkin\\SimpleXLSXGen' => $vendorDir . '/shuchkin/simplexlsxgen/src/SimpleXLSXGen.php',
|
||||||
|
);
|
||||||
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
9
vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
38
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInit7443bc322605554a2a2e26076e20764b
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInit7443bc322605554a2a2e26076e20764b', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInit7443bc322605554a2a2e26076e20764b', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInit7443bc322605554a2a2e26076e20764b::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInit7443bc322605554a2a2e26076e20764b
|
||||||
|
{
|
||||||
|
public static $classMap = array (
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
'Shuchkin\\SimpleXLSXGen' => __DIR__ . '/..' . '/shuchkin/simplexlsxgen/src/SimpleXLSXGen.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->classMap = ComposerStaticInit7443bc322605554a2a2e26076e20764b::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "shuchkin/simplexlsxgen",
|
||||||
|
"version": "1.5.17",
|
||||||
|
"version_normalized": "1.5.17.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shuchkin/simplexlsxgen.git",
|
||||||
|
"reference": "162a4a9b929611d69dbd6f1a7f42af483a87b537"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/shuchkin/simplexlsxgen/zipball/162a4a9b929611d69dbd6f1a7f42af483a87b537",
|
||||||
|
"reference": "162a4a9b929611d69dbd6f1a7f42af483a87b537",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-zlib": "*",
|
||||||
|
"php": ">=5.4"
|
||||||
|
},
|
||||||
|
"time": "2026-05-03T13:04:04+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/SimpleXLSXGen.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sergey Shuchkin (SMSPILOT)",
|
||||||
|
"email": "sergey.shuchkin@gmail.com",
|
||||||
|
"homepage": "https://shuchkin.ru/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Export data to Excel XLSx file. PHP XLSX generator.",
|
||||||
|
"homepage": "https://github.com/shuchkin/simplexlsxgen",
|
||||||
|
"keywords": [
|
||||||
|
"backend",
|
||||||
|
"creator",
|
||||||
|
"excel",
|
||||||
|
"generator",
|
||||||
|
"php",
|
||||||
|
"writer",
|
||||||
|
"xlsx"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/shuchkin/simplexlsxgen/issues",
|
||||||
|
"source": "https://github.com/shuchkin/simplexlsxgen/tree/1.5.17"
|
||||||
|
},
|
||||||
|
"install-path": "../shuchkin/simplexlsxgen"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"dev-package-names": []
|
||||||
|
}
|
||||||
32
vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => '__root__',
|
||||||
|
'pretty_version' => 'dev-master',
|
||||||
|
'version' => 'dev-master',
|
||||||
|
'reference' => 'a897557f9b2c5450ce9f867e5945bb040d282791',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'__root__' => array(
|
||||||
|
'pretty_version' => 'dev-master',
|
||||||
|
'version' => 'dev-master',
|
||||||
|
'reference' => 'a897557f9b2c5450ce9f867e5945bb040d282791',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'shuchkin/simplexlsxgen' => array(
|
||||||
|
'pretty_version' => '1.5.17',
|
||||||
|
'version' => '1.5.17.0',
|
||||||
|
'reference' => '162a4a9b929611d69dbd6f1a7f42af483a87b537',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../shuchkin/simplexlsxgen',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
26
vendor/composer/platform_check.php
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 50400)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.4.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
|
||||||
|
);
|
||||||
|
}
|
||||||
219
vendor/shuchkin/simplexlsxgen/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
# 1.5.17 (2026-05-03)
|
||||||
|
* datetime detection priority, thx [Ced](https://github.com/cauzanne) [#176](https://github.com/shuchkin/simplexlsxgen/issues/176)
|
||||||
|
|
||||||
|
# 1.5.16 (2026-04-22)
|
||||||
|
* setColWidth accepts column letters and ranges, e.g. setColWidth('A', 35) or setColWidth('A:C', 15), thx [Albert](https://github.com/lazaroagomez) [#171](https://github.com/shuchkin/simplexlsxgen/issues/171)
|
||||||
|
|
||||||
|
# 1.5.15 (2026-03-12)
|
||||||
|
* fixed formatted numbers, thx [Roland](https://github.com/mrextreme) [#174](https://github.com/shuchkin/simplexlsxgen/issues/174#issuecomment-4045694443)
|
||||||
|
|
||||||
|
# 1.5.14 (2026-03-11)
|
||||||
|
* real numbers as General
|
||||||
|
|
||||||
|
# 1.5.13 (2026-03-09)
|
||||||
|
* long numbers right alignment, thx [ErikLtz](https://github.com/ErikLtz) [#173](https://github.com/shuchkin/simplexlsxgen/issues/173)
|
||||||
|
|
||||||
|
# 1.5.12 (2025-10-24)
|
||||||
|
* added tag ```<rotation90>```, thx [wawaclem](https://github.com/wawaclem)
|
||||||
|
|
||||||
|
# 1.5.11 (2025-08-09)
|
||||||
|
* added ::rawArray()
|
||||||
|
|
||||||
|
|
||||||
|
# 1.5.10 (2025-07-08)
|
||||||
|
* added cell comments
|
||||||
|
|
||||||
|
# 1.4.15 (2025-05-28)
|
||||||
|
* added custom dateformats [via nf= work](https://github.com/shuchkin/simplexlsxgen/pull/166), thx [scravy](https://github.com/scravy)
|
||||||
|
|
||||||
|
# 1.4.14 (2025-03-07)
|
||||||
|
* fixed [empty cells and selection](https://github.com/shuchkin/simplexlsxgen/issues/164) issue, thx [denisboccardo](https://github.com/denisboccardo)
|
||||||
|
|
||||||
|
# 1.4.13 (2024-10-13)
|
||||||
|
* fixed [formula and style](https://github.com/shuchkin/simplexlsxgen/issues/156) issue, when skpped `v="value"` in formula tag
|
||||||
|
|
||||||
|
## 1.4.12 (2024-07-28)
|
||||||
|
* tag ```<raw>``` for styled raw values
|
||||||
|
|
||||||
|
## 1.4.11 (2024-02-07)
|
||||||
|
* hyperlinks to local files
|
||||||
|
* num2name static now
|
||||||
|
|
||||||
|
## 1.4.10 (2023-12-31)
|
||||||
|
* added SimpleXLSXGen::create($title = null) to create empty book with title
|
||||||
|
* added SimpleXLSXGen::save to save xlsx in current folder as `title`.xslx or `curdate`.xlsx
|
||||||
|
* SimpleXLSXGen::esc and SimpleXLSXGen::date2excel static now
|
||||||
|
* added examples SimpleXLSXGen::create, SimpleXSLXGen::raw, SimpleXLSXGen:save in README.md
|
||||||
|
* fixed [fpassthru disabled issue](https://github.com/shuchkin/simplexlsxgen/issues/116)
|
||||||
|
* fixed empty book, A1 empty now, text _No data_ removed
|
||||||
|
* thx [Javier](https://github.com/xaviermdq)
|
||||||
|
|
||||||
|
## 1.3.20 (2023-12-12)
|
||||||
|
* force little endian numbers in zip headers
|
||||||
|
|
||||||
|
## 1.3.18 (2023-12-02)
|
||||||
|
* simple linebreaks
|
||||||
|
|
||||||
|
## 1.3.17 (2023-10-02)
|
||||||
|
* fixed [issue 128](https://github.com/shuchkin/simplexlsxgen/issues/128) date2excel type cast
|
||||||
|
|
||||||
|
## 1.3.16 (2023-09-12)
|
||||||
|
* preserve leading or traling spaces
|
||||||
|
|
||||||
|
## 1.3.15 (2023-04-19)
|
||||||
|
* added meta: setTitle, setSubject, setAuthor, setCompany, setManager, setKeywords, setDescription, setCategory, setApplication, setLastModifiedBy. Thx [Oleg Kosarev](https://github.com/DevOlegKosarev)
|
||||||
|
|
||||||
|
## 1.3.14 (2023-04-18)
|
||||||
|
* fixed "This action doesn't work on multiple selection" error
|
||||||
|
|
||||||
|
## 1.3.13 (2023-04-11)
|
||||||
|
* ```$xlsx->rightToLeft()``` - RTL mode. Column A is on the far right, Column B is one column left of Column A, and so on. Also, information in cells is displayed in the Right to Left format.
|
||||||
|
|
||||||
|
## 1.3.12 (2023-03-31)
|
||||||
|
* ```<style font-size="32">Big Text</style>``` - font size in cells, thx [Andrew Robinson](https://github.com/mrjemson)
|
||||||
|
|
||||||
|
## 1.3.11 (2023-03-28)
|
||||||
|
* freezePanes( corner_cell ) - freezePanes to keep an area of a worksheet visible while you scroll, corner_cell is not included, thx [Javier](https://github.com/xaviermdq)
|
||||||
|
|
||||||
|
## 1.3.10 (2022-12-14)
|
||||||
|
* added borders ```<style border="medium">Black Border</style>``` see colored [examples](https://github.com/shuchkin/simplexlsxgen#formatting)
|
||||||
|
* added formulas ```<f v="100">SUM(B1:B10)</f>``` see [examples](https://github.com/shuchkin/simplexlsxgen#data-types)
|
||||||
|
* added internal links ```<a href="sheet2!A1">Go to page 2</a>```
|
||||||
|
* added custom number formats ```<style nf=""£"#,##0.00">500</style>```
|
||||||
|
* added 3 currencies ```$data = [ ['$100.23', '2000.00 €', '1200.30 ₽'] ];```
|
||||||
|
|
||||||
|
## 1.2.16 (2022-08-12)
|
||||||
|
* added `autoFilter( $range )`
|
||||||
|
```php
|
||||||
|
$xlsx->autoFilter('A2:B10');
|
||||||
|
```
|
||||||
|
* fixed `0%` bug
|
||||||
|
|
||||||
|
## 1.2.15 (2022-07-05)
|
||||||
|
* added wrap words in long strings `<wraptext>long long line</wraptext>`
|
||||||
|
|
||||||
|
## 1.2.14 (2022-06-10)
|
||||||
|
* added example [JS array to Excel (AJAX)](https://github.com/shuchkin/simplexlsxgen#js-array-to-excel-ajax)
|
||||||
|
|
||||||
|
## 1.2.13 (2022-06-01)
|
||||||
|
* setColWidth(num_col_started_1, size_in_chars) - set column width
|
||||||
|
|
||||||
|
## 1.2.12 (2022-05-17)
|
||||||
|
* Vertical align (tags top,middle,bottom) `<bottom>12345</bottom>`
|
||||||
|
|
||||||
|
## 1.2.11 (2022-05-01)
|
||||||
|
* Row height `<style height="50">Custom row height 50</style>`
|
||||||
|
|
||||||
|
|
||||||
|
## 1.2.10 (2022-04-24)
|
||||||
|
* Added colors `<style color="#FFFF00" bgcolor="#00FF00">Yellow text on blue background</style>`, thx [mrjemson](https://github.com/mrjemson)
|
||||||
|
|
||||||
|
## 1.1.12 (2022-03-15)
|
||||||
|
* Added `$xlsx->mergeCells('A1:C1')`
|
||||||
|
|
||||||
|
## 1.1.11 (2022-02-05)
|
||||||
|
* sheet name maximum length is 31 chars, mb_substr used now
|
||||||
|
* license fixed
|
||||||
|
|
||||||
|
## 1.1.10 (2022-02-05)
|
||||||
|
* namespace added, use Shuchkin\SimpleXLSXGen
|
||||||
|
|
||||||
|
## 1.0.23 (2022-02-01)
|
||||||
|
* fixed dates if year < 1900 and time only cells, thx [fapth](https://github.com/shuchkin/simplexlsxgen/issues/51)
|
||||||
|
|
||||||
|
## 1.0.22 (2021-10-29)
|
||||||
|
* Escape \x00 and \x0B (vertical tab)
|
||||||
|
|
||||||
|
## 1.0.21 (2021-09-03)
|
||||||
|
* Fixed saveAs / downloadAs / etc methods more than once
|
||||||
|
|
||||||
|
## 1.0.20 (2021-07-29)
|
||||||
|
* Fixed sheet names duplicates (Page, Page (1), Page (2)...)
|
||||||
|
|
||||||
|
## 1.0.19 (2021-07-28)
|
||||||
|
* Fixed sheet names duplicates
|
||||||
|
|
||||||
|
## 1.0.18 (2021-07-28)
|
||||||
|
* Fixed email regex
|
||||||
|
|
||||||
|
## 1.0.17 (2021-07-28)
|
||||||
|
* Fixed " and & in sheets names
|
||||||
|
|
||||||
|
## 1.0.16 (2021-07-01)
|
||||||
|
* Fixed "&" in hyperlinks
|
||||||
|
|
||||||
|
## 1.0.15 (2021-06-22)
|
||||||
|
* Fixed *mailto* hyperlinks detection
|
||||||
|
|
||||||
|
## 1.0.14 (2021-06-08)
|
||||||
|
* Added *mailto* hyperlinks support (thx Howard Martin)
|
||||||
|
```php
|
||||||
|
SimpleXLSXGen::fromArray([
|
||||||
|
['Mailto hyperlink', '<a href="mailto:sergey.shuchkin@gmail.com">Please email me</a>']
|
||||||
|
])->saveAs('test.xlsx');
|
||||||
|
```
|
||||||
|
## 1.0.13 (2021-05-29)
|
||||||
|
* Fixed hyperlinks in several sheets
|
||||||
|
* Added [Opencollective donation link](https://opencollective.com/simplexlsx)
|
||||||
|
|
||||||
|
## 1.0.12 (2021-05-19)
|
||||||
|
* Fixed hyperlink regex
|
||||||
|
|
||||||
|
## 1.0.11 (2021-05-14)
|
||||||
|
* Fixed 0.00% format, thx [marcrobledo](https://github.com/shuchkin/simplexlsxgen/pull/34), more examples in README.md
|
||||||
|
|
||||||
|
## 1.0.10 (2021-05-03)
|
||||||
|
Stable release
|
||||||
|
|
||||||
|
* Added hyperlinks and minimal formatting
|
||||||
|
|
||||||
|
## 0.9.25 (2021-02-26)
|
||||||
|
* Added PHP Datetime object values in a cells
|
||||||
|
|
||||||
|
## 0.9.24 (2021-02-26)
|
||||||
|
* Percent support
|
||||||
|
|
||||||
|
|
||||||
|
## 0.9.23 (2021-01-25)
|
||||||
|
* Fix local floats in XML
|
||||||
|
|
||||||
|
## 0.9.22 (2020-11-04)
|
||||||
|
* Added multiple sheets support, thx [Savino59](https://github.com/Savino59), class ready for extend now
|
||||||
|
|
||||||
|
## 0.9.21 (2020-10-17)
|
||||||
|
* Updated images
|
||||||
|
|
||||||
|
## 0.9.20 (2020-10-04)
|
||||||
|
* Disable type detection if string started with chr(0)
|
||||||
|
|
||||||
|
## 0.9.19 (2020-08-23)
|
||||||
|
* Numbers like SKU right aligned now
|
||||||
|
|
||||||
|
## 0.9.18 (2020-08-22)
|
||||||
|
* Fixed fast shared strings index
|
||||||
|
|
||||||
|
## 0.9.17 (2020-08-21)
|
||||||
|
* Fixed real numbers in 123.45 format detection, fast shared strings index (thx fredriksundin)
|
||||||
|
|
||||||
|
## 0.9.16 (2020-07-29)
|
||||||
|
* Fixed time detection in HH:MM:SS format
|
||||||
|
|
||||||
|
## 0.9.15 (2020-07-14)
|
||||||
|
* Escape of shared strings for special chars in cells [#1](https://github.com/shuchkin/simplexlsxgen/issues/1)
|
||||||
|
|
||||||
|
## 0.9.14 (2020-05-31)
|
||||||
|
* Fixed num2name A-Z,AA-AZ column names, thx Ertan Yusufoglu
|
||||||
|
|
||||||
|
## 0.9.13 (2020-05-21)
|
||||||
|
* If string more 160 chars, save as inlineStr
|
||||||
|
|
||||||
|
## 0.9.12 (2020-05-21)
|
||||||
|
* Readme fixed
|
||||||
|
|
||||||
|
## 0.9.11 (2020-05-21)
|
||||||
|
* Removed XML unimportant attributes
|
||||||
|
|
||||||
|
## 0.9.10 (2020-05-20)
|
||||||
|
* Initial release
|
||||||
261
vendor/shuchkin/simplexlsxgen/README.md
vendored
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
# SimpleXLSXGen
|
||||||
|
[<img src="https://img.shields.io/github/license/shuchkin/simplexlsxgen" />](https://github.com/shuchkin/simplexlsxgen/blob/master/license.md) [<img src="https://img.shields.io/github/stars/shuchkin/simplexlsxgen" />](https://github.com/shuchkin/simplexlsxgen/stargazers) [<img src="https://img.shields.io/github/forks/shuchkin/simplexlsxgen" />](https://github.com/shuchkin/simplexlsxgen/network) [<img src="https://img.shields.io/github/issues/shuchkin/simplexlsxgen" />](https://github.com/shuchkin/simplexlsxgen/issues)
|
||||||
|
|
||||||
|
Export data to Excel XLSX file. PHP XLSX generator. No external tools and libraries.
|
||||||
|
- XLSX reader [here](https://github.com/shuchkin/simplexlsx)
|
||||||
|
- XLS reader [here](https://github.com/shuchkin/simplexls)
|
||||||
|
- CSV reader/writer [here](https://github.com/shuchkin/simplecsv)
|
||||||
|
|
||||||
|
**Sergey Shuchkin** <sergey.shuchkin@gmail.com> 2020-2025<br/>
|
||||||
|
|
||||||
|
*Hey, bro, please ★ the package for my motivation :) and [donate](https://opencollective.com/simplexlsx) for more motivation!*
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
```php
|
||||||
|
$books = [
|
||||||
|
['ISBN', 'title', 'author', 'publisher', 'ctry' ],
|
||||||
|
[618260307, 'The Hobbit', 'J. R. R. Tolkien', 'Houghton Mifflin', 'USA'],
|
||||||
|
[908606664, 'Slinky Malinki', 'Lynley Dodd', 'Mallinson Rendel', 'NZ']
|
||||||
|
];
|
||||||
|
$xlsx = Shuchkin\SimpleXLSXGen::fromArray( $books );
|
||||||
|
$xlsx->saveAs('books.xlsx'); // or downloadAs('books.xlsx') or $xlsx_content = (string) $xlsx
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
## Installation
|
||||||
|
The recommended way to install this library is [through Composer](https://getcomposer.org).
|
||||||
|
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
|
||||||
|
|
||||||
|
This will install the latest supported version:
|
||||||
|
```bash
|
||||||
|
$ composer require shuchkin/simplexlsxgen
|
||||||
|
```
|
||||||
|
or download class [here](https://github.com/shuchkin/simplexlsxgen/blob/master/src/SimpleXLSXGen.php)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
Use UTF-8 encoded strings.
|
||||||
|
### Data types
|
||||||
|
```php
|
||||||
|
$data = [
|
||||||
|
['Integer', 123],
|
||||||
|
['Float', 12.35],
|
||||||
|
['Percent', '12%'],
|
||||||
|
['Currency $', '$500.67'],
|
||||||
|
['Currency €', '200 €'],
|
||||||
|
['Currency ₽', '1200.30 ₽'],
|
||||||
|
['Currency (other)', '<style nf=""£"#,##0.00">500</style>'],
|
||||||
|
['Currency Float (other)', '<style nf="#,##0.00\ [$£-1];[Red]#,##0.00\ [$£-1]">500.250</style>'],
|
||||||
|
['Datetime', '2020-05-20 02:38:00'],
|
||||||
|
['Date', '2020-05-20'],
|
||||||
|
['Time', '02:38:00'],
|
||||||
|
['Datetime PHP', new DateTime('2021-02-06 21:07:00')],
|
||||||
|
['String', 'Very long UTF-8 string in autoresized column'],
|
||||||
|
['Formula', '<f v="135.35">SUM(B1:B2)</f>'],
|
||||||
|
['Hyperlink', 'https://github.com/shuchkin/simplexlsxgen'],
|
||||||
|
['Hyperlink + Anchor', '<a href="https://github.com/shuchkin/simplexlsxgen">SimpleXLSXGen</a>'],
|
||||||
|
['Internal link', '<a href="sheet2!A1">Go to second page</a>'],
|
||||||
|
['RAW string', "\0" . '2020-10-04 16:02:00'],
|
||||||
|
['Formatted RAW string', '<b><i><raw>2024-07-28 16:02:00</raw></i></b>'],
|
||||||
|
];
|
||||||
|
SimpleXLSXGen::fromArray($data)->saveAs('datatypes.xlsx');
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
```php
|
||||||
|
$data = [
|
||||||
|
['Normal', '12345.67'],
|
||||||
|
['Bold', '<b>12345.67</b>'],
|
||||||
|
['Italic', '<i>12345.67</i>'],
|
||||||
|
['Underline', '<u>12345.67</u>'],
|
||||||
|
['Strike', '<s>12345.67</s>'],
|
||||||
|
['Bold + Italic', '<b><i>12345.67</i></b>'],
|
||||||
|
['Hyperlink', 'https://github.com/shuchkin/simplexlsxgen'],
|
||||||
|
['Italic + Hyperlink + Anchor', '<i><a href="https://github.com/shuchkin/simplexlsxgen">SimpleXLSXGen</a></i>'],
|
||||||
|
['Green', '<style color="#00FF00">12345.67</style>'],
|
||||||
|
['Bold Red Text', '<b><style color="#FF0000">12345.67</style></b>'],
|
||||||
|
['Size 32 Font', '<style font-size="32">Big Text</style>'],
|
||||||
|
['Blue Text and Yellow Fill', '<style bgcolor="#FFFF00" color="#0000FF">12345.67</style>'],
|
||||||
|
['Border color', '<style border="#000000">Black Thin Border</style>'],
|
||||||
|
['<top>Border style</top>','<style border="medium"><wraptext>none, thin, medium, dashed, dotted, thick, double, hair, mediumDashed, dashDot,mediumDashDot, dashDotDot, mediumDashDotDot, slantDashDot</wraptext></style>'],
|
||||||
|
['Border sides', '<style border="none dotted#0000FF medium#FF0000 double">Top No + Right Dotted + Bottom medium + Left double</style>'],
|
||||||
|
['Left', '<left>12345.67</left>'],
|
||||||
|
['Center', '<center>12345.67</center>'],
|
||||||
|
['Right', '<right>Right Text</right>'],
|
||||||
|
['Center + Bold', '<center><b>Name</b></center>'],
|
||||||
|
['Row height', '<style height="50">Row Height = 50</style>'],
|
||||||
|
['Top', '<style height="50"><top>Top</top></style>'],
|
||||||
|
['Middle + Center', '<style height="50"><middle><center>Middle + Center</center></middle></style>'],
|
||||||
|
['Bottom + Right', '<style height="50"><bottom><right>Bottom + Right</right></bottom></style>'],
|
||||||
|
['<center>MERGE CELLS MERGE CELLS MERGE CELLS MERGE CELLS MERGE CELLS</center>', null],
|
||||||
|
['<top>Word wrap</top>', "<wraptext>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book</wraptext>"],
|
||||||
|
['Linebreaks', "Line 1\nLine 2\nLine 3"],
|
||||||
|
['Comments', '<!-- Comment without author -->No Author'],
|
||||||
|
['Comments + author + linebreaks', "<!-- Alex Pushkin: Born 6 June 1799 Moscow\r\nDied 10 February 1837 (aged 37) Saint Petersburg-->Pushkin"],
|
||||||
|
['<rotation90>Rotation 90</rotation90>', 'Rotated header'],
|
||||||
|
];
|
||||||
|
SimpleXLSXGen::fromArray($data)
|
||||||
|
->setDefaultFont('Courier New')
|
||||||
|
->setDefaultFontSize(14)
|
||||||
|
->setColWidth(1, 35) // or ->setColWidth('A', 35)
|
||||||
|
->setColWidth('B:C', 20) // column letters and ranges also work
|
||||||
|
->mergeCells('A20:B20')
|
||||||
|
->saveAs('styles_and_tags.xlsx');
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
### RAW Strings
|
||||||
|
Prefix #0 cell value (use double quotes) or use ::raw() ::rawArray() methods or tag ```<raw>```
|
||||||
|
```php
|
||||||
|
$PushkinDOB = '1799-07-06';
|
||||||
|
$data = [
|
||||||
|
['Datetime as raw string', "\0" . '2023-01-09 11:16:34'],
|
||||||
|
['Date as raw string', "\0" . $PushkinDOB],
|
||||||
|
['Disable type detection', "\0" . '+12345'],
|
||||||
|
['Method ::raw, insert greater/less them simbols', SimpleXLSXGen::raw('20- short term: <6 month')],
|
||||||
|
['Formatted raw', '<b><center><raw>+123456 <tag><tag2></raw></center></b>'],
|
||||||
|
];
|
||||||
|
SimpleXLSXGen::fromArray($data)
|
||||||
|
->saveAs('test_rawstrings.xlsx');
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
['test', 'raw', 'array'],
|
||||||
|
['2025-08-09 14:36:34', '< tag >', 1]
|
||||||
|
];
|
||||||
|
$raw_data = SimpleXLSXGen::rawArray($data);
|
||||||
|
SimpleXLSXGen::fromArray($raw_data)->saveAs('test_raw_array.xlsx');
|
||||||
|
```
|
||||||
|
### More examples
|
||||||
|
```php
|
||||||
|
// Fluid interface, output to browser for download
|
||||||
|
Shuchkin\SimpleXLSXGen::fromArray( $books )->downloadAs('table.xlsx');
|
||||||
|
|
||||||
|
// Fluid interface, multiple sheets
|
||||||
|
Shuchkin\SimpleXLSXGen::fromArray( $books, 'My books' )->addSheet( $books2 )->download();
|
||||||
|
|
||||||
|
// Alternative interface, sheet name, get xlsx content
|
||||||
|
$xlsx_cache = (string) (new Shuchkin\SimpleXLSXGen)->addSheet( $books, 'Modern style');
|
||||||
|
|
||||||
|
// Classic interface
|
||||||
|
use Shuchkin\SimpleXLSXGen;
|
||||||
|
$xlsx = new SimpleXLSXGen();
|
||||||
|
$xlsx->addSheet( $books, 'Catalog 2021' );
|
||||||
|
$xlsx->addSheet( $books2, 'Stephen King catalog');
|
||||||
|
$xlsx->downloadAs('books_2021.xlsx');
|
||||||
|
exit();
|
||||||
|
|
||||||
|
// Empty book with title
|
||||||
|
$xlsx = SimpleXLSX::create('My books');
|
||||||
|
$xlsx->addSheet( $books );
|
||||||
|
$xlsx->save(); // ./My books.xlsx
|
||||||
|
|
||||||
|
// Hyperlinks
|
||||||
|
$xlsx = SimpleXLSX::fromArray([
|
||||||
|
['internal link', '<a href="\'My books 2\'!A1">Go to second sheet</a>'],
|
||||||
|
['http', 'https://example.com/'], // autodetect
|
||||||
|
['http + hash', 'https://en.wikipedia.org/wiki/Office_Open_XML#References'], // autodetect
|
||||||
|
['external anchor', '<a href="https://en.wikipedia.org/wiki/Office_Open_XML#References">Open XML</a>'],
|
||||||
|
['relative link', '<a href="books.xlsx">books</a>'],
|
||||||
|
['relative link + cell addr', '<a href="..\books.xlsx#\'Sheet 2\'!A1">link to second sheet in other book</a>'],
|
||||||
|
['mailto', 'info@example.com'], // autodetect
|
||||||
|
['mailto 2', '<a href="mailto:info@example.com">Please email me</a>'],
|
||||||
|
])->addSheet([['Second sheet']], 'My books 2')->saveAs('hyperlinks.xlsx');
|
||||||
|
|
||||||
|
// Autofilter
|
||||||
|
$xlsx->autoFilter('A1:B10');
|
||||||
|
|
||||||
|
// Freeze rows and columns from top-left corner up to, but not including,
|
||||||
|
// the row and column of the indicated cell
|
||||||
|
$xlsx->freezePanes('B2'); // B1 - freeze first column, A2 - freeze top row
|
||||||
|
|
||||||
|
// RTL mode
|
||||||
|
// Column A is on the far right, Column B is one column left of Column A, and so on.
|
||||||
|
// Also, information in cells is displayed in the Right to Left format.
|
||||||
|
$xlsx->rightToLeft();
|
||||||
|
|
||||||
|
// Set Meta Data Files
|
||||||
|
// this data in propertis Files and Info file in Office
|
||||||
|
$xlsx->setAuthor('John Doe <john@example.com>')
|
||||||
|
->setCompany('JD LLC <jd@mexample.com>')
|
||||||
|
->setManager('Jane Doe <jane@example.com>')
|
||||||
|
->setLastModifiedBy("John Doe <john@example.com>")
|
||||||
|
->setTitle('My Books')
|
||||||
|
->setSubject('My bookshelf')
|
||||||
|
->setKeywords('Tolkien,Rowling,Kipling')
|
||||||
|
->setDescription('Cool books worn by time')
|
||||||
|
->setCategory('Books')
|
||||||
|
->setLanguage('en-US')
|
||||||
|
->setApplication('Shuchkin\SimpleXLSXGen')
|
||||||
|
```
|
||||||
|
### JS array to Excel (AJAX)
|
||||||
|
```php
|
||||||
|
<?php // array2excel.php
|
||||||
|
if (isset($_POST['array2excel'])) {
|
||||||
|
require __DIR__.'/simplexlsxgen/src/SimpleXLSXGen.php';
|
||||||
|
$data = json_decode($_POST['array2excel'], false);
|
||||||
|
\Shuchkin\SimpleXLSXGen::fromArray($data)->downloadAs('file.xlsx');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>JS array to Excel</title>
|
||||||
|
</head>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function array2excel() {
|
||||||
|
var books = [
|
||||||
|
["ISBN", "title", "author", "publisher", "ctry"],
|
||||||
|
[618260307, "The Hobbit", "J. R. R. Tolkien", "Houghton Mifflin", "USA"],
|
||||||
|
[908606664, "Slinky Malinki", "Lynley Dodd", "Mallinson Rendel", "NZ"]
|
||||||
|
];
|
||||||
|
var json = JSON.stringify(books);
|
||||||
|
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onload = function () {
|
||||||
|
if (this.status === 200) {
|
||||||
|
var file = new Blob([this.response], {type: this.getResponseHeader('Content-Type')});
|
||||||
|
var fileURL = URL.createObjectURL(file);
|
||||||
|
var filename = "", m;
|
||||||
|
var disposition = this.getResponseHeader('Content-Disposition');
|
||||||
|
if (disposition && (m = /"([^"]+)"/.exec(disposition)) !== null) {
|
||||||
|
filename = m[1];
|
||||||
|
}
|
||||||
|
var a = document.createElement("a");
|
||||||
|
if (typeof a.download === 'undefined') {
|
||||||
|
window.location = fileURL;
|
||||||
|
} else {
|
||||||
|
a.href = fileURL;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Error: " + this.status + " " + this.statusText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.open('POST', "array2excel.php");
|
||||||
|
request.responseType = "blob";
|
||||||
|
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
request.send("array2excel=" + encodeURIComponent(json));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body>
|
||||||
|
<input type="button" onclick="array2excel()" value="array2excel" />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debug
|
||||||
|
```php
|
||||||
|
ini_set('error_reporting', E_ALL );
|
||||||
|
ini_set('display_errors', 1 );
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
['Debug', 123]
|
||||||
|
];
|
||||||
|
|
||||||
|
Shuchkin\SimpleXLSXGen::fromArray( $data )->saveAs('debug.xlsx');
|
||||||
|
```
|
||||||
BIN
vendor/shuchkin/simplexlsxgen/books.png
vendored
Normal file
|
After Width: | Height: | Size: 22 KiB |
24
vendor/shuchkin/simplexlsxgen/composer.json
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "shuchkin/simplexlsxgen",
|
||||||
|
"description": "Export data to Excel XLSx file. PHP XLSX generator.",
|
||||||
|
"keywords": ["php", "excel", "xlsx", "generator", "writer", "creator", "backend"],
|
||||||
|
"homepage": "https://github.com/shuchkin/simplexlsxgen",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sergey Shuchkin (SMSPILOT)",
|
||||||
|
"email": "sergey.shuchkin@gmail.com",
|
||||||
|
"homepage": "https://shuchkin.ru/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/SimpleXLSXGen.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-zlib": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
vendor/shuchkin/simplexlsxgen/composer.lock
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"_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": "9e2d3c362fd0bf028d5ee5081bdf5e4b",
|
||||||
|
"packages": [],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-zlib": "*"
|
||||||
|
},
|
||||||
|
"platform-dev": []
|
||||||
|
}
|
||||||
BIN
vendor/shuchkin/simplexlsxgen/datatypes.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
1
vendor/shuchkin/simplexlsxgen/examples/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.xlsx
|
||||||
12
vendor/shuchkin/simplexlsxgen/examples/custom-date-format.php
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once(implode(DIRECTORY_SEPARATOR, [__DIR__, '..', 'src', 'SimpleXLSXGen.php']));
|
||||||
|
|
||||||
|
$xlsx = new \Shuchkin\SimpleXLSXGen();
|
||||||
|
|
||||||
|
$xlsx->addSheet([
|
||||||
|
["foo", "bar"],
|
||||||
|
["something", '<style nf="DD.MM.YYYY">2024-01-01</style>'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$xlsx->saveAs(basename(__FILE__, ".php") . '.xlsx');
|
||||||
21
vendor/shuchkin/simplexlsxgen/license.md
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020-2022 Sergey Shuchkin sergey.shuchkin@gmail.com
|
||||||
|
|
||||||
|
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.
|
||||||
1377
vendor/shuchkin/simplexlsxgen/src/SimpleXLSXGen.php
vendored
Normal file
BIN
vendor/shuchkin/simplexlsxgen/styles.png
vendored
Normal file
|
After Width: | Height: | Size: 178 KiB |