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;
|
||||
}
|
||||
require_once 'db/config.php';
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use Shuchkin\SimpleXLSXGen;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
@ -12,7 +15,7 @@ try {
|
||||
|
||||
// Filtramos solo los pedidos que están en estado 'ROTULADO 📦' y son de la agencia 'SHALOM'
|
||||
$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
|
||||
WHERE p.estado = 'ROTULADO 📦'
|
||||
AND p.agencia LIKE '%SHALOM%'
|
||||
@ -30,35 +33,23 @@ try {
|
||||
$stmt->execute();
|
||||
$pedidos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$filename = "masivo_shalom";
|
||||
if ($type === 'terrestre') $filename .= "_terrestre";
|
||||
if ($type === 'aereo') $filename .= "_aereo";
|
||||
$filename .= ".xls";
|
||||
|
||||
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
header('Pragma: no-cache');
|
||||
header('Expires: 0');
|
||||
|
||||
$output = '<html><head><meta charset="utf-8">
|
||||
<style>
|
||||
.text { mso-number-format:"\@"; }
|
||||
.preserve-space { white-space: pre; }
|
||||
</style>
|
||||
</head><body>';
|
||||
$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>';
|
||||
$data = [];
|
||||
// Header
|
||||
$data[] = [
|
||||
'DESTINATARIO (DOC)',
|
||||
'TELF. DESTINATARIO',
|
||||
'CONTACTO (DOC)',
|
||||
'TELF. CONTACTO',
|
||||
'NRO GRR',
|
||||
'ORIGEN',
|
||||
'DESTINO',
|
||||
'MERCADERIA',
|
||||
'ALTO',
|
||||
'ANCHO',
|
||||
'LARGO',
|
||||
'PESO',
|
||||
'CANTIDAD'
|
||||
];
|
||||
|
||||
foreach ($pedidos as $pedido) {
|
||||
// Limpiar el DNI: solo números
|
||||
@ -72,31 +63,52 @@ try {
|
||||
$celular = substr($celular, 2);
|
||||
}
|
||||
|
||||
$celular = htmlspecialchars($celular);
|
||||
|
||||
$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
|
||||
$destino = mb_strtoupper($destino, 'UTF-8');
|
||||
$destino = htmlspecialchars($destino);
|
||||
|
||||
$output .= '<tr>';
|
||||
$output .= '<td class="text">' . $dni . '</td>'; // Solo el número de DNI con formato texto
|
||||
$output .= '<td class="text">' . $celular . '</td>'; // Teléfono con formato texto
|
||||
$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
|
||||
$output .= '<td class="preserve-space">' . $destino . '</td>'; // Destino
|
||||
$output .= '</tr>';
|
||||
$data[] = [
|
||||
(string)$dni,
|
||||
(string)$celular,
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'AV MEXICO CO',
|
||||
$destino,
|
||||
'PAQUETE XXS', // MERCADERIA
|
||||
'0.1', // ALTO
|
||||
'0.1', // ANCHO
|
||||
'0.1', // LARGO
|
||||
'0.1', // PESO
|
||||
'1' // CANTIDAD
|
||||
];
|
||||
}
|
||||
|
||||
$output .= '</tbody>';
|
||||
$output .= '</table>';
|
||||
$output .= '</body></html>';
|
||||
$filename = "masivo_shalom";
|
||||
if ($type === 'terrestre') $filename .= "_terrestre";
|
||||
if ($type === 'aereo') $filename .= "_aereo";
|
||||
$filename .= "_" . date('Y-m-d') . ".xlsx";
|
||||
|
||||
echo $output;
|
||||
SimpleXLSXGen::fromArray($data)->downloadAs($filename);
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
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 |