Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
<?php
function classLoader($class) {
$path = str_replace(
['\\', 'Asan' . DIRECTORY_SEPARATOR . 'PHPExcel' . DIRECTORY_SEPARATOR], [DIRECTORY_SEPARATOR, ''], $class
);
$file = __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . $path . '.php';
if (file_exists($file)) {
require_once $file;
}
}
spl_autoload_register('classLoader');

View File

@@ -0,0 +1,12 @@
<?php
/**
* Reader Interface
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Contract;
interface ReaderInterface extends \SeekableIterator, \Countable {
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* PHP Excel
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel;
use Asan\PHPExcel\Exception\ReaderException;
class Excel {
/**
* Load a file
*
* @param string $file
* @param callback|null $callback
* @param string|null $encoding
* @param string $ext
* @param string $logPath
*
* @throws ReaderException
* @return \Asan\PHPExcel\Reader\BaseReader
*/
public static function load($file, $callback = null, $encoding = null, $ext = '', $logPath = '') {
set_error_handler(function($errorNo, $errorMsg, $errorFile, $errorLine) use ($logPath) {
if ($logPath) {
if (!file_exists($logPath)) {
mkdir($logPath, 0755, true);
}
$content = sprintf(
"%s\t%s.%s\t%s\t%s", date("Y-m-d H:i:s"), self::class, 'ERROR',
"[$errorNo]$errorMsg in $errorFile:$errorLine", PHP_EOL
);
file_put_contents("$logPath/excel-" . date('Y-m-d'). '.log', $content, FILE_APPEND);
}
}, E_ALL ^ E_ERROR);
$ext = $ext ?: strtolower(pathinfo($file, PATHINFO_EXTENSION));
$format = self::getFormatByExtension($ext);
if (empty($format)) {
throw new ReaderException("Could not identify file format for file [$file] with extension [$ext]");
}
$class = __NAMESPACE__ . '\\Reader\\' . $format;
$reader = new $class;
if ($callback) {
if ($callback instanceof \Closure) {
// Do the callback
call_user_func($callback, $reader);
} elseif (is_string($callback)) {
// Set the encoding
$encoding = $callback;
}
}
if ($encoding && method_exists($reader, 'setInputEncoding')) {
$reader->setInputEncoding($encoding);
}
return $reader->load($file);
}
/**
* Identify file format
*
* @param string $ext
* @return string
*/
protected static function getFormatByExtension($ext) {
$formart = '';
switch ($ext) {
/*
|--------------------------------------------------------------------------
| Excel 2007
|--------------------------------------------------------------------------
*/
case 'xlsx':
case 'xlsm':
case 'xltx':
case 'xltm':
$formart = 'Xlsx';
break;
/*
|--------------------------------------------------------------------------
| Excel5
|--------------------------------------------------------------------------
*/
case 'xls':
case 'xlt':
$formart = 'Xls';
break;
/*
|--------------------------------------------------------------------------
| CSV
|--------------------------------------------------------------------------
*/
case 'csv':
case 'txt':
$formart = 'Csv';
break;
}
return $formart;
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Parser Exception
*
* @author Janson
* @create 2017-11-27
*/
namespace Asan\PHPExcel\Exception;
class ParserException extends \Exception {
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Reader Exception
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Exception;
class ReaderException extends \Exception {
}

View File

@@ -0,0 +1,839 @@
<?php
/**
* Excel2017 Parser
*
* @author Janson
* @create 2017-12-02
*/
namespace Asan\PHPExcel\Parser;
use Asan\PHPExcel\Exception\ParserException;
use Asan\PHPExcel\Exception\ReaderException;
class Excel2007 {
const CELL_TYPE_SHARED_STR = 's';
/**
* Temporary directory
*
* @var string
*/
protected $tmpDir;
/**
* ZipArchive reader
*
* @var \ZipArchive
*/
protected $zip;
/**
* Worksheet reader
*
* @var \XMLReader
*/
protected $worksheetXML;
/**
* SharedStrings reader
*
* @var \XMLReader
*/
protected $sharedStringsXML;
/**
* SharedStrings position
*
* @var array
*/
private $sharedStringsPosition = -1;
/**
* The current sheet of the file
*
* @var int
*/
private $sheetIndex = 0;
/**
* Ignore empty row
*
* @var bool
*/
private $ignoreEmpty = false;
/**
* Style xfs
*
* @var array
*/
private $styleXfs;
/**
* Number formats
*
* @var array
*/
private $formats;
/**
* Parsed number formats
*
* @var array
*/
private $parsedFormats;
/**
* Worksheets
*
* @var array
*/
private $sheets;
/**
* Default options for libxml loader
*
* @var int
*/
private static $libXmlLoaderOptions;
/**
* Base date
*
* @var \DateTime
*/
private static $baseDate;
private static $decimalSeparator = '.';
private static $thousandSeparator = ',';
private static $currencyCode = '';
private static $runtimeInfo = ['GMPSupported' => false];
/**
* Use ZipArchive reader to extract the relevant data streams from the ZipArchive file
*
* @throws ParserException|ReaderException
* @param string $file
*/
public function loadZip($file) {
$this->openFile($file);
// Setting base date
if (!self::$baseDate) {
self::$baseDate = new \DateTime;
self::$baseDate->setTimezone(new \DateTimeZone('UTC'));
self::$baseDate->setDate(1900, 1, 0);
self::$baseDate->setTime(0, 0, 0);
}
if (function_exists('gmp_gcd')) {
self::$runtimeInfo['GMPSupported'] = true;
}
}
/**
* Ignore empty row
*
* @param bool $ignoreEmpty
*
* @return $this
*/
public function ignoreEmptyRow($ignoreEmpty) {
$this->ignoreEmpty = $ignoreEmpty;
return $this;
}
/**
* Whether is ignore empty row
*
* @return bool
*/
public function isIgnoreEmptyRow() {
return $this->ignoreEmpty;
}
/**
* Set sheet index
*
* @param int $index
*
* @return $this
*/
public function setSheetIndex($index) {
if ($index != $this->sheetIndex) {
$this->sheetIndex = $index;
$this->getWorksheetXML();
}
return $this;
}
/**
* Get sheet index
*
* @return int
*/
public function getSheetIndex() {
return $this->sheetIndex;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @throws ReaderException
* @return array
*/
public function parseWorksheetInfo() {
if ($this->sheets === null) {
$workbookXML = simplexml_load_string(
$this->securityScan($this->zip->getFromName('xl/workbook.xml')), 'SimpleXMLElement', self::getLibXmlLoaderOptions()
);
$this->sheets = [];
if (isset($workbookXML->sheets) && $workbookXML->sheets) {
$xml = new \XMLReader();
$index = 0;
foreach ($workbookXML->sheets->sheet as $sheet) {
$info = [
'name' => (string)$sheet['name'], 'lastColumnLetter' => '', 'lastColumnIndex' => 0,
'totalRows' => 0, 'totalColumns' => 0
];
$this->zip->extractTo($this->tmpDir, $file = 'xl/worksheets/sheet' . (++$index) . '.xml');
$xml->open($this->tmpDir . '/' . $file, null, self::getLibXmlLoaderOptions());
$xml->setParserProperty(\XMLReader::DEFAULTATTRS, true);
$nonEmpty = false;
$columnLetter = '';
while ($xml->read()) {
if ($xml->name == 'row') {
if (!$this->ignoreEmpty && $xml->nodeType == \XMLReader::ELEMENT) {
$info['totalRows'] = (int)$xml->getAttribute('r');
} elseif ($xml->nodeType == \XMLReader::END_ELEMENT) {
if ($this->ignoreEmpty && $nonEmpty) {
$info['totalRows']++;
$nonEmpty = false;
}
if ($columnLetter > $info['lastColumnLetter']) {
$info['lastColumnLetter'] = $columnLetter;
}
}
} elseif ($xml->name == 'c' && $xml->nodeType == \XMLReader::ELEMENT) {
$columnLetter = preg_replace('{[^[:alpha:]]}S', '', $xml->getAttribute('r'));
} elseif ($this->ignoreEmpty && !$nonEmpty && $xml->name == 'v'
&& $xml->nodeType == \XMLReader::ELEMENT && trim($xml->readString()) !== '') {
$nonEmpty = true;
}
}
if ($info['lastColumnLetter']) {
$info['totalColumns'] = Format::columnIndexFromString($info['lastColumnLetter']);
$info['lastColumnIndex'] = $info['totalColumns'] - 1;
}
$this->sheets[] = $info;
}
$xml->close();
}
}
return $this->sheets;
}
/**
* Get shared string
*
* @param int $position
* @return string
*/
protected function getSharedString($position) {
$value = '';
$file = 'xl/sharedStrings.xml';
if ($this->sharedStringsXML === null) {
$this->sharedStringsXML = new \XMLReader();
$this->zip->extractTo($this->tmpDir, $file);
}
if ($this->sharedStringsPosition < 0 || $position < $this->sharedStringsPosition) {
$this->sharedStringsXML->open($this->tmpDir . '/' . $file, null, self::getLibXmlLoaderOptions());
$this->sharedStringsPosition = -1;
}
while ($this->sharedStringsXML->read()) {
$name = $this->sharedStringsXML->name;
$nodeType = $this->sharedStringsXML->nodeType;
if ($name == 'si') {
if ($nodeType == \XMLReader::ELEMENT) {
$this->sharedStringsPosition++;
} elseif ($position == $this->sharedStringsPosition && $nodeType == \XMLReader::END_ELEMENT) {
break;
}
} elseif ($name == 't' && $position == $this->sharedStringsPosition && $nodeType == \XMLReader::ELEMENT) {
$value .= trim($this->sharedStringsXML->readString());
}
}
return $value;
}
/**
* Parse styles info
*
* @throws ReaderException
*/
protected function parseStyles() {
if ($this->styleXfs === null) {
$stylesXML = simplexml_load_string(
$this->securityScan($this->zip->getFromName('xl/styles.xml')), 'SimpleXMLElement', self::getLibXmlLoaderOptions()
);
$this->styleXfs = $this->formats = [];
if ($stylesXML) {
if (isset($stylesXML->cellXfs->xf) && $stylesXML->cellXfs->xf) {
foreach ($stylesXML->cellXfs->xf as $xf) {
$numFmtId = isset($xf['numFmtId']) ? (int)$xf['numFmtId'] : 0;
if (isset($xf['applyNumberFormat']) || $numFmtId == 0) {
// If format ID >= 164, it is a custom format and should be read from styleSheet\numFmts
$this->styleXfs[] = $numFmtId;
} else {
// 0 for "General" format
$this->styleXfs[] = Format::FORMAT_GENERAL;
}
}
}
if (isset($stylesXML->numFmts->numFmt) && $stylesXML->numFmts->numFmt) {
foreach ($stylesXML->numFmts->numFmt as $numFmt) {
if (isset($numFmt['numFmtId'], $numFmt['formatCode'])) {
$this->formats[(int)$numFmt['numFmtId']] = (string)$numFmt['formatCode'];
}
}
}
}
}
}
/**
* Get worksheet XMLReader
*/
protected function getWorksheetXML() {
if ($this->worksheetXML === null) {
$this->worksheetXML = new \XMLReader();
}
$this->worksheetXML->open(
$this->tmpDir . '/xl/worksheets/sheet' . ($this->getSheetIndex() + 1) . '.xml',
null, self::getLibXmlLoaderOptions()
);
}
/**
* Get row data
*
* @param int $rowIndex
* @param int $columnLimit
*
* @throws ReaderException
* @return array|bool
*/
public function getRow($rowIndex, $columnLimit = 0) {
$this->parseStyles();
$rowIndex === 0 && $this->getWorksheetXML();
$sharedString = false;
$index = $styleId = 0;
$row = $columnLimit ? array_fill(0, $columnLimit, '') : [];
while ($canRead = $this->worksheetXML->read()) {
$name = $this->worksheetXML->name;
$type = $this->worksheetXML->nodeType;
// End of row
if ($name == 'row') {
if (!$this->ignoreEmpty && $type == \XMLReader::ELEMENT
&& $rowIndex+1 != (int)$this->worksheetXML->getAttribute('r')) {
$this->worksheetXML->moveToElement();
break;
}
if ($type == \XMLReader::END_ELEMENT) {
break;
}
}
if ($columnLimit > 0 && $index >= $columnLimit) {
continue;
}
switch ($name) {
// Cell
case 'c':
if ($type == \XMLReader::END_ELEMENT) {
continue;
}
$styleId = (int)$this->worksheetXML->getAttribute('s');
$letter = preg_replace('{[^[:alpha:]]}S', '', $this->worksheetXML->getAttribute('r'));
$index = Format::columnIndexFromString($letter) - 1;
// Determine cell type
$sharedString = false;
if ($this->worksheetXML->getAttribute('t') == self::CELL_TYPE_SHARED_STR) {
$sharedString = true;
}
break;
// Cell value
case 'v':
case 'is':
if ($type == \XMLReader::END_ELEMENT) {
continue;
}
$value = $this->worksheetXML->readString();
if ($sharedString) {
$value = $this->getSharedString($value);
}
// Format value if necessary
if ($value !== '' && $styleId && isset($this->styleXfs[$styleId])) {
$value = $this->formatValue($value, $styleId);
} elseif ($value && is_numeric($value)) {
$value = (float)$value;
}
$row[$index] = $value;
break;
}
}
if ($canRead === false) {
return false;
}
return $row;
}
/**
* Close ZipArchive、XMLReader and remove temp dir
*/
public function __destruct() {
if ($this->zip && $this->tmpDir) {
$this->zip->close();
}
if ($this->worksheetXML) {
$this->worksheetXML->close();
}
if ($this->sharedStringsXML) {
$this->sharedStringsXML->close();
}
$this->removeDir($this->tmpDir);
$this->zip = null;
$this->worksheetXML = null;
$this->sharedStringsXML = null;
$this->tmpDir = null;
}
/**
* Remove dir
*
* @param string $dir
*/
protected function removeDir($dir) {
if($dir && is_dir($dir)) {
$handle = opendir($dir);
while($item = readdir($handle)) {
if ($item != '.' && $item != '..') {
is_file($item = $dir . '/' . $item) ? unlink($item) : $this->removeDir($item);
}
}
closedir($handle);
rmdir($dir);
}
}
/**
* Formats the value according to the index
*
* @param string $value
* @param int $index Format index
*
* @throws \Exception
* @return string Formatted cell value
*/
private function formatValue($value, $index) {
if (!is_numeric($value)) {
return $value;
}
if (isset($this->styleXfs[$index]) && $this->styleXfs[$index] !== false) {
$index = $this->styleXfs[$index];
} else {
return $value;
}
// A special case for the "General" format
if ($index == 0) {
return is_numeric($value) ? (float)$value : $value;
}
$format = $this->parsedFormats[$index] ?? [];
if (empty($format)) {
$format = [
'code' => false, 'type' => false, 'scale' => 1, 'thousands' => false, 'currency' => false
];
if (isset(Format::$buildInFormats[$index])) {
$format['code'] = Format::$buildInFormats[$index];
} elseif (isset($this->formats[$index])) {
$format['code'] = str_replace('"', '', $this->formats[$index]);
}
// Format code found, now parsing the format
if ($format['code']) {
$sections = explode(';', $format['code']);
$format['code'] = $sections[0];
switch (count($sections)) {
case 2:
if ($value < 0) {
$format['code'] = $sections[1];
}
$value = abs($value);
break;
case 3:
case 4:
if ($value < 0) {
$format['code'] = $sections[1];
} elseif ($value == 0) {
$format['code'] = $sections[2];
}
$value = abs($value);
break;
}
}
// Stripping colors
$format['code'] = trim(preg_replace('/^\\[[a-zA-Z]+\\]/', '', $format['code']));
// Percentages
if (substr($format['code'], -1) == '%') {
$format['type'] = 'Percentage';
} elseif (preg_match('/(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format['code'])) {
$format['type'] = 'DateTime';
$format['code'] = trim(preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format['code']));
$format['code'] = strtolower($format['code']);
$format['code'] = strtr($format['code'], Format::$dateFormatReplacements);
if (strpos($format['code'], 'A') === false) {
$format['code'] = strtr($format['code'], Format::$dateFormatReplacements24);
} else {
$format['code'] = strtr($format['code'], Format::$dateFormatReplacements12);
}
} elseif ($format['code'] == '[$EUR ]#,##0.00_-') {
$format['type'] = 'Euro';
} else {
// Removing skipped characters
$format['code'] = preg_replace('/_./', '', $format['code']);
// Removing unnecessary escaping
$format['code'] = preg_replace("/\\\\/", '', $format['code']);
// Removing string quotes
$format['code'] = str_replace(['"', '*'], '', $format['code']);
// Removing thousands separator
if (strpos($format['code'], '0,0') !== false || strpos($format['code'], '#,#') !== false) {
$format['thousands'] = true;
}
$format['code'] = str_replace(['0,0', '#,#'], ['00', '##'], $format['code']);
// Scaling (Commas indicate the power)
$scale = 1;
$matches = [];
if (preg_match('/(0|#)(,+)/', $format['code'], $matches)) {
$scale = pow(1000, strlen($matches[2]));
// Removing the commas
$format['code'] = preg_replace(['/0,+/', '/#,+/'], ['0', '#'], $format['code']);
}
$format['scale'] = $scale;
if (preg_match('/#?.*\?\/\?/', $format['code'])) {
$format['type'] = 'Fraction';
} else {
$format['code'] = str_replace('#', '', $format['code']);
$matches = [];
if (preg_match('/(0+)(\.?)(0*)/', preg_replace('/\[[^\]]+\]/', '', $format['code']), $matches)) {
list(, $integer, $decimalPoint, $decimal) = $matches;
$format['minWidth'] = strlen($integer) + strlen($decimalPoint) + strlen($decimal);
$format['decimals'] = $decimal;
$format['precision'] = strlen($format['decimals']);
$format['pattern'] = '%0' . $format['minWidth'] . '.' . $format['precision'] . 'f';
}
}
$matches = [];
if (preg_match('/\[\$(.*)\]/u', $format['code'], $matches)) {
$currencyCode = explode('-', $matches[1]);
if ($currencyCode) {
$currencyCode = $currencyCode[0];
}
if (!$currencyCode) {
$currencyCode = self::$currencyCode;
}
$format['currency'] = $currencyCode;
}
$format['code'] = trim($format['code']);
}
$this->parsedFormats[$index] = $format;
}
// Applying format to value
if ($format) {
if ($format['code'] == '@') {
return (string)$value;
} elseif ($format['type'] == 'Percentage') { // Percentages
if ($format['code'] === '0%') {
$value = round(100*$value, 0) . '%';
} else {
$value = sprintf('%.2f%%', round(100*$value, 2));
}
} elseif ($format['type'] == 'DateTime') { // Dates and times
$days = (int)$value;
// Correcting for Feb 29, 1900
if ($days > 60) {
$days--;
}
// At this point time is a fraction of a day
$time = ($value - (int)$value);
// Here time is converted to seconds
// Some loss of precision will occur
$seconds = $time ? (int)($time*86400) : 0;
$value = clone self::$baseDate;
$value->add(new \DateInterval('P' . $days . 'D' . ($seconds ? 'T' . $seconds . 'S' : '')));
$value = $value->format($format['code']);
} elseif ($format['type'] == 'Euro') {
$value = 'EUR ' . sprintf('%1.2f', $value);
} else {
// Fractional numbers
if ($format['type'] == 'Fraction' && ($value != (int)$value)) {
$integer = floor(abs($value));
$decimal = fmod(abs($value), 1);
// Removing the integer part and decimal point
$decimal *= pow(10, strlen($decimal) - 2);
$decimalDivisor = pow(10, strlen($decimal));
if (self::$runtimeInfo['GMPSupported']) {
$GCD = gmp_strval(gmp_gcd($decimal, $decimalDivisor));
} else {
$GCD = self::GCD($decimal, $decimalDivisor);
}
$adjDecimal = $decimal/$GCD;
$adjDecimalDivisor = $decimalDivisor/$GCD;
if (strpos($format['code'], '0') !== false || strpos($format['code'], '#') !== false
|| substr($format['code'], 0, 3) == '? ?') {
// The integer part is shown separately apart from the fraction
$value = ($value < 0 ? '-' : '') . $integer ? $integer . ' '
: '' . $adjDecimal . '/' . $adjDecimalDivisor;
} else {
// The fraction includes the integer part
$adjDecimal += $integer * $adjDecimalDivisor;
$value = ($value < 0 ? '-' : '') . $adjDecimal . '/' . $adjDecimalDivisor;
}
} else {
// Scaling
$value = $value/$format['scale'];
if (!empty($format['minWidth']) && $format['decimals']) {
if ($format['thousands']) {
$value = number_format(
$value, $format['precision'], self::$decimalSeparator, self::$thousandSeparator
);
$value = preg_replace('/(0+)(\.?)(0*)/', $value, $format['code']);
} else {
if (preg_match('/[0#]E[+-]0/i', $format['code'])) {
// Scientific format
$value = sprintf('%5.2E', $value);
} else {
$value = sprintf($format['pattern'], $value);
$value = preg_replace('/(0+)(\.?)(0*)/', $value, $format['code']);
}
}
}
}
// currency/Accounting
if ($format['currency']) {
$value = preg_replace('', $format['currency'], $value);
}
}
}
return $value;
}
/**
* Greatest common divisor calculation in case GMP extension is not enabled
*
* @param int $number1
* @param int $number2
*
* @return int
*/
private static function GCD($number1, $number2) {
$number1 = abs($number1);
$number2 = abs($number2);
if ($number1 + $number2 == 0) {
return 0;
}
$number = 1;
while ($number1 > 0) {
$number = $number1;
$number1 = $number2 % $number1;
$number2 = $number;
}
return $number;
}
/**
* Open file for reading
*
* @param string $file
*
* @throws ParserException|ReaderException
*/
public function openFile($file) {
// Check if file exists
if (!file_exists($file) || !is_readable($file)) {
throw new ReaderException("Could not open file [$file] for reading! File does not exist.");
}
$this->zip = new \ZipArchive();
$xl = false;
if ($this->zip->open($file) === true) {
$this->tmpDir = sys_get_temp_dir() . '/' . uniqid();
// check if it is an OOXML archive
$rels = simplexml_load_string(
$this->securityScan($this->zip->getFromName('_rels/.rels')),
'SimpleXMLElement', self::getLibXmlLoaderOptions()
);
if ($rels !== false) {
foreach ($rels->Relationship as $rel) {
switch ($rel["Type"]) {
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
if ($rel["Target"] == 'xl/workbook.xml') {
$xl = true;
}
break;
}
}
}
}
if ($xl === false) {
throw new ParserException("The file [$file] is not recognised as a zip archive");
}
}
/**
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks
*
* @param string $xml
*
* @throws ReaderException
* @return string
*/
protected function securityScan($xml) {
$pattern = sprintf('/\\0?%s\\0?/', implode('\\0?', str_split('<!DOCTYPE')));
if (preg_match($pattern, $xml)) {
throw new ReaderException(
'Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'
);
}
return $xml;
}
/**
* Set default options for libxml loader
*
* @param int $options Default options for libxml loader
*/
public static function setLibXmlLoaderOptions($options = null) {
if (is_null($options) && defined(LIBXML_DTDLOAD)) {
$options = LIBXML_DTDLOAD | LIBXML_DTDATTR;
}
if (version_compare(PHP_VERSION, '5.2.11') >= 0) {
@libxml_disable_entity_loader($options == (LIBXML_DTDLOAD | LIBXML_DTDATTR));
}
self::$libXmlLoaderOptions = $options;
}
/**
* Get default options for libxml loader.
* Defaults to LIBXML_DTDLOAD | LIBXML_DTDATTR when not set explicitly.
*
* @return int Default options for libxml loader
*/
public static function getLibXmlLoaderOptions() {
if (is_null(self::$libXmlLoaderOptions) && defined(LIBXML_DTDLOAD)) {
self::setLibXmlLoaderOptions(LIBXML_DTDLOAD | LIBXML_DTDATTR);
}
if (version_compare(PHP_VERSION, '5.2.11') >= 0) {
@libxml_disable_entity_loader(self::$libXmlLoaderOptions == (LIBXML_DTDLOAD | LIBXML_DTDATTR));
}
return self::$libXmlLoaderOptions;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
<?php
/**
* OLE File Read
*
* @author Janson
* @create 2017-11-27
*/
namespace Asan\PHPExcel\Parser\Excel5;
use Asan\PHPExcel\Exception\ParserException;
use Asan\PHPExcel\Exception\ReaderException;
use Asan\PHPExcel\Parser\Format;
defined('IDENTIFIER_OLE') ||
define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1));
class OLERead {
// OLE identifier
const IDENTIFIER_OLE = IDENTIFIER_OLE;
// Size of a sector = 512 bytes
const BIG_BLOCK_SIZE = 0x200;
// Size of a short sector = 64 bytes
const SMALL_BLOCK_SIZE = 0x40;
// Size of a directory entry always = 128 bytes
const PROPERTY_STORAGE_BLOCK_SIZE = 0x80;
// Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams
const SMALL_BLOCK_THRESHOLD = 0x1000;
// header offsets
const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c;
const ROOT_START_BLOCK_POS = 0x30;
const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c;
const EXTENSION_BLOCK_POS = 0x44;
const NUM_EXTENSION_BLOCK_POS = 0x48;
const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c;
// property storage offsets (directory offsets)
const SIZE_OF_NAME_POS = 0x40;
const TYPE_POS = 0x42;
const START_BLOCK_POS = 0x74;
const SIZE_POS = 0x78;
public $workbook = null;
public $summaryInformation = null;
public $documentSummaryInformation = null;
protected $data = '';
protected $bigBlockChain = '';
protected $smallBlockChain = '';
protected $entry = '';
protected $props = [];
protected $rootEntry = 0;
protected $sbdStartBlock = 0;
protected $extensionBlock = 0;
protected $rootStartBlock = 0;
protected $numExtensionBlocks = 0;
protected $numBigBlockDepotBlocks = 0;
/**
* Read the file
*
* @throws ParserException|ReaderException
* @param string $file
*/
public function read($file) {
$this->openFile($file);
// Total number of sectors used for the SAT
$this->numBigBlockDepotBlocks = Format::getInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
// SecID of the first sector of the directory stream
$this->rootStartBlock = Format::getInt4d($this->data, self::ROOT_START_BLOCK_POS);
// SecID of the first sector of the SSAT (or -2 if not extant)
$this->sbdStartBlock = Format::getInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
$this->extensionBlock = Format::getInt4d($this->data, self::EXTENSION_BLOCK_POS);
// Total number of sectors used by MSAT
$this->numExtensionBlocks = Format::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
$bigBlockDepotBlocks = [];
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
$bbdBlocks = $this->numBigBlockDepotBlocks;
if ($this->numExtensionBlocks != 0) {
$bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS) / 4;
}
for ($i = 0; $i < $bbdBlocks; ++$i) {
$bigBlockDepotBlocks[$i] = Format::getInt4d($this->data, $pos);
$pos += 4;
}
for ($j = 0; $j < $this->numExtensionBlocks; ++$j) {
$pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE;
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
$bigBlockDepotBlocks[$i] = Format::getInt4d($this->data, $pos);
$pos += 4;
}
$bbdBlocks += $blocksToRead;
if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
$this->extensionBlock = Format::getInt4d($this->data, $pos);
}
}
$this->bigBlockChain = '';
$bbs = self::BIG_BLOCK_SIZE / 4;
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
$this->bigBlockChain .= substr($this->data, $pos, 4 * $bbs);
}
$sbdBlock = $this->sbdStartBlock;
$this->smallBlockChain = '';
while ($sbdBlock != -2) {
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
$this->smallBlockChain .= substr($this->data, $pos, 4 * $bbs);
$sbdBlock = Format::getInt4d($this->bigBlockChain, $sbdBlock * 4);
}
// read the directory stream
$block = $this->rootStartBlock;
$this->entry = $this->readData($block);
$this->readPropertySets();
}
/**
* Open file for reading
*
* @param string $file
*
* @throws ReaderException|ParserException
*/
public function openFile($file) {
// Check if file exists
if (!file_exists($file) || !is_readable($file)) {
throw new ReaderException("Could not open file [$file] for reading! File does not exist.");
}
// Get the file data
$this->data = file_get_contents($file);
// Check OLE identifier
if (empty($this->data) || substr($this->data, 0, 8) != self::IDENTIFIER_OLE) {
throw new ParserException("The file [$file] is not recognised as an OLE file");
}
}
/**
* Extract binary stream data.
*
* @param int $stream
*
* @return string|null
*/
public function getStream($stream) {
if ($stream === null) {
return null;
}
$streamData = '';
if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) {
$rootData = $this->readData($this->props[$this->rootEntry]['startBlock']);
$block = $this->props[$stream]['startBlock'];
while ($block != -2) {
$pos = $block * self::SMALL_BLOCK_SIZE;
$streamData .= substr($rootData, $pos, self::SMALL_BLOCK_SIZE);
$block = Format::getInt4d($this->smallBlockChain, $block * 4);
}
return $streamData;
}
$numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) {
++$numBlocks;
}
if ($numBlocks == 0) {
return '';
}
$block = $this->props[$stream]['startBlock'];
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = Format::getInt4d($this->bigBlockChain, $block * 4);
}
return $streamData;
}
/**
* Read a standard stream (by joining sectors using information from SAT).
*
* @param int $bl Sector ID where the stream starts
*
* @return string
*/
protected function readData($bl) {
$block = $bl;
$data = '';
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = Format::getInt4d($this->bigBlockChain, $block * 4);
}
return $data;
}
/**
* Read entries in the directory stream.
*/
protected function readPropertySets() {
$offset = 0;
// loop through entires, each entry is 128 bytes
$entryLen = strlen($this->entry);
while ($offset < $entryLen) {
// entry data (128 bytes)
$d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
// size in bytes of name
$nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS + 1]) << 8);
// type of entry
$type = ord($d[self::TYPE_POS]);
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
// sectorID of first sector of the short-stream container stream, if this entry is root entry
$startBlock = Format::getInt4d($d, self::START_BLOCK_POS);
$size = Format::getInt4d($d, self::SIZE_POS);
$name = str_replace("\x00", '', substr($d, 0, $nameSize));
$this->props[] = [
'name' => $name,
'type' => $type,
'startBlock' => $startBlock,
'size' => $size,
];
// tmp helper to simplify checks
$upName = strtoupper($name);
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) {
$this->workbook = count($this->props) - 1;
} elseif ($upName === 'ROOT ENTRY' || $upName === 'R') {
// Root entry
$this->rootEntry = count($this->props) - 1;
}
// Summary information
if ($name == chr(5) . 'SummaryInformation') {
$this->summaryInformation = count($this->props) - 1;
}
// Additional Document Summary information
if ($name == chr(5) . 'DocumentSummaryInformation') {
$this->documentSummaryInformation = count($this->props) - 1;
}
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* Excel5 RC4
*
* @author Janson
* @create 2017-11-29
*/
namespace Asan\PHPExcel\Parser\Excel5;
class RC4 {
// Context
private $s = [];
private $i = 0;
private $j = 0;
/**
* RC4 stream decryption/encryption constrcutor
*
* @param string $key Encryption key/passphrase
*/
public function __construct($key) {
$len = strlen($key);
for ($this->i = 0; $this->i < 256; $this->i++) {
$this->s[$this->i] = $this->i;
}
$this->j = 0;
for ($this->i = 0; $this->i < 256; $this->i++) {
$this->j = ($this->j + $this->s[$this->i] + ord($key[$this->i % $len])) % 256;
$t = $this->s[$this->i];
$this->s[$this->i] = $this->s[$this->j];
$this->s[$this->j] = $t;
}
$this->i = $this->j = 0;
}
/**
* Symmetric decryption/encryption function
*
* @param string $data Data to encrypt/decrypt
*
* @return string
*/
public function RC4($data) {
$len = strlen($data);
for ($c = 0; $c < $len; $c++) {
$this->i = ($this->i + 1) % 256;
$this->j = ($this->j + $this->s[$this->i]) % 256;
$t = $this->s[$this->i];
$this->s[$this->i] = $this->s[$this->j];
$this->s[$this->j] = $t;
$t = ($this->s[$this->i] + $this->s[$this->j]) % 256;
$data[$c] = chr(ord($data[$c]) ^ $this->s[$t]);
}
return $data;
}
}

View File

@@ -0,0 +1,278 @@
<?php
/**
* Format helper
*
* @author Janson
* @create 2017-11-27
*/
namespace Asan\PHPExcel\Parser;
use Asan\PHPExcel\Exception\ParserException;
class Format {
//Base date of 1st Jan 1900 = 1.0
const CALENDAR_WINDOWS_1900 = 1900;
//Base date of 2nd Jan 1904 = 1.0
const CALENDAR_MAC_1904 = 1904;
// Pre-defined formats
const FORMAT_GENERAL = 'General';
const FORMAT_TEXT = '@';
const FORMAT_PERCENTAGE = '0%';
const FORMAT_PERCENTAGE_00 = '0.00%';
const FORMAT_CURRENCY_EUR_SIMPLE = '[$EUR ]#,##0.00_-';
public static $buildInFormats = [
0 => self::FORMAT_GENERAL,
1 => '0',
2 => '0.00',
3 => '#,##0',
4 => '#,##0.00',
5 => '"$"#,##0_),("$"#,##0)',
6 => '"$"#,##0_),[Red]("$"#,##0)',
7 => '"$"#,##0.00_),("$"#,##0.00)',
8 => '"$"#,##0.00_),[Red]("$"#,##0.00)',
9 => '0%',
10 => '0.00%',
//11 => '0.00E+00',
12 => '# ?/?',
13 => '# ??/??',
14 => 'yyyy/m/d',
15 => 'd-mmm-yy',
16 => 'd-mmm',
17 => 'mmm-yy',
18 => 'h:mm AM/PM',
19 => 'h:mm:ss AM/PM',
20 => 'h:mm',
21 => 'h:mm:ss',
22 => 'yyyy/m/d h:mm',
// 补充
28 => 'm月d日',
31 => 'yyyy年m月d日',
32 => 'h时i分',
33 => 'h时i分ss秒',
34 => 'AM/PM h时i分',
35 => 'AM/PM h时i分ss秒',
55 => 'AM/PM h时i分',
56 => 'AM/PM h时i分ss秒',
58 => 'm月d日',
37 => '#,##0_),(#,##0)',
38 => '#,##0_),[Red](#,##0)',
39 => '#,##0.00_),(#,##0.00)',
40 => '#,##0.00_),[Red](#,##0.00)',
41 => '_("$"* #,##0_),_("$"* (#,##0),_("$"* "-"_),_(@_)',
42 => '_(* #,##0_),_(* (#,##0),_(* "-"_),_(@_)',
43 => '_(* #,##0.00_),_(* (#,##0.00),_(* "-"??_),_(@_)',
44 => '_("$"* #,##0.00_),_("$"* \(#,##0.00\),_("$"* "-"??_),_(@_)',
45 => 'mm:ss',
46 => '[h]:mm:ss',
47 => 'mm:ss.0',
48 => '##0.0E+0',
49 => '@',
// CHT
27 => 'yyyy年m月',
30 => 'm/d/yy',
36 => '[$-404]e/m/d',
50 => '[$-404]e/m/d',
57 => 'yyyy年m月',
// THA
59 => 't0',
60 => 't0.00',
61 => 't#,##0',
62 => 't#,##0.00',
67 => 't0%',
68 => 't0.00%',
69 => 't# ?/?',
70 => 't# ??/??'
];
/**
* Search/replace values to convert Excel date/time format masks to PHP format masks
*
* @var array
*/
public static $dateFormatReplacements = [
// first remove escapes related to non-format characters
'\\' => '',
// 12-hour suffix
'am/pm' => 'A',
// 2-digit year
'e' => 'Y',
'yyyy' => 'Y',
'yy' => 'y',
// first letter of month - no php equivalent
'mmmmm' => 'M',
// full month name
'mmmm' => 'F',
// short month name
'mmm' => 'M',
// mm is minutes if time, but can also be month w/leading zero
// so we try to identify times be the inclusion of a : separator in the mask
// It isn't perfect, but the best way I know how
':mm' => ':i',
'mm:' => 'i:',
// month leading zero
'mm' => 'm',
'm' => 'n',
// full day of week name
'dddd' => 'l',
// short day of week name
'ddd' => 'D',
// days leading zero
'dd' => 'd',
'd' => 'j',
// seconds
'ss' => 's',
// fractional seconds - no php equivalent
'.s' => ''
];
/**
* Search/replace values to convert Excel date/time format masks hours to PHP format masks (24 hr clock)
*
* @var array
*/
public static $dateFormatReplacements24 = [
'hh' => 'H',
'h' => 'G'
];
/**
* Search/replace values to convert Excel date/time format masks hours to PHP format masks (12 hr clock)
*
* @var array
*/
public static $dateFormatReplacements12 = [
'hh' => 'h',
'h' => 'g'
];
/**
* Column index from string
*
* @param string $label
*
* @throws \Exception
* @return int
*/
public static function columnIndexFromString($label = 'A') {
// Using a lookup cache adds a slight memory overhead, but boosts speed
// caching using a static within the method is faster than a class static,
// though it's additional memory overhead
static $indexCache = [];
if (isset($indexCache[$label])) {
return $indexCache[$label];
}
// It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array rather
// than use ord() and make it case insensitive to get rid of the strtoupper() as well. Because it's a static,
// there's no significant memory overhead either
static $columnLookup = [
'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10,
'K' => 11, 'L' => 12, 'M' => 13, 'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19,
'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26, 'a' => 1, 'b' => 2, 'c' => 3,
'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8, 'i' => 9, 'j' => 10, 'k' => 11, 'l' => 12, 'm' => 13,
'n' => 14, 'o' => 15, 'p' => 16, 'q' => 17, 'r' => 18, 's' => 19, 't' => 20, 'u' => 21, 'v' => 22,
'w' => 23, 'x' => 24, 'y' => 25, 'z' => 26
];
// We also use the language construct isset() rather than the more costly strlen() function to match the length
// of $pString for improved performance
if (!isset($indexCache[$label])) {
if (!isset($label[0]) || isset($label[3])) {
throw new ParserException('Column string can not be empty or longer than 3 characters');
}
if (!isset($label[1])) {
$indexCache[$label] = $columnLookup[$label];
} elseif (!isset($label[2])) {
$indexCache[$label] = $columnLookup[$label[0]] * 26 + $columnLookup[$label[1]];
} else {
$indexCache[$label] = $columnLookup[$label[0]] * 676 + $columnLookup[$label[1]] * 26
+ $columnLookup[$label[2]];
}
}
return $indexCache[$label];
}
/**
* String from columnindex
*
* @param int $column
* @return string
*/
public static function stringFromColumnIndex($column = 0) {
// Using a lookup cache adds a slight memory overhead, but boosts speed
// caching using a static within the method is faster than a class static,
// though it's additional memory overhead
static $stringCache = [];
if (!isset($stringCache[$column])) {
// Determine column string
if ($column < 26) {
$stringCache[$column] = chr(65 + $column);
} elseif ($column < 702) {
$stringCache[$column] = chr(64 + ($column / 26)) . chr(65 + $column % 26);
} else {
$stringCache[$column] = chr(64 + (($column - 26) / 676)) . chr(65 + ((($column - 26) % 676) / 26))
. chr(65 + $column % 26);
}
}
return $stringCache[$column];
}
/**
* Read 16-bit unsigned integer
*
* @param string $data
* @param int $pos
* @return int
*/
public static function getUInt2d($data, $pos) {
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8);
}
/**
* Read 32-bit signed integer
*
* @param string $data
* @param int $pos
* @return int
*/
public static function getInt4d($data, $pos) {
// FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$ord24 = ord($data[$pos + 3]);
if ($ord24 >= 128) {
// negative number
$ord24 = -abs((256 - $ord24) << 24);
} else {
$ord24 = ($ord24 & 127) << 24;
}
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $ord24;
}
}

View File

@@ -0,0 +1,162 @@
<?php
/**
* Reader Abstract
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Reader;
use Asan\PHPExcel\Contract\ReaderInterface;
abstract class BaseReader implements ReaderInterface {
/**
* Generator
*
* @var \Generator
*/
protected $generator;
/**
* File row count
*
* @var int
*/
protected $count;
/**
* Max row number
*
* @var int
*/
protected $rowLimit;
/**
* Max column number
*
* @var int
*/
protected $columnLimit;
/**
* Return the current element
*
* @return array
*/
public function current() {
return $this->generator->current();
}
/**
* Move forward to next element
*/
public function next() {
$this->generator->next();
}
/**
* Return the key of the current element
*
* @return int
*/
public function key() {
return $this->generator->key();
}
/**
* Checks if current position is valid
*
* @return bool
*/
public function valid() {
return $this->generator->valid();
}
/**
* Rewind the Iterator to the first element
*/
public function rewind() {
$this->generator = $this->makeGenerator();
}
/**
* Make the generator
*/
protected function makeGenerator() {
}
/**
* Ignore empty row
*
* @param bool $ignoreEmpty
*/
public function ignoreEmptyRow($ignoreEmpty = false) {
}
/**
* Set row limit
*
* @param int $limit
* @return $this
*/
public function setRowLimit($limit = null) {
$this->rowLimit = $limit;
return $this;
}
/**
* Get row limit
*
* @return int
*/
public function getRowLimit() {
return $this->rowLimit;
}
/**
* Set column limit
*
* @param int $limit
* @return $this
*/
public function setColumnLimit($limit = null) {
$this->columnLimit = $limit;
return $this;
}
/**
* Takes a row and traverses the file to that row
*
* @param int $row
*/
public function seek($row) {
if ($row <= 0) {
throw new \InvalidArgumentException("Row $row is invalid");
}
$key = $this->key();
if ($key !== --$row) {
if ($row < $key || is_null($key) || $row == 0) {
$this->rewind();
}
while ($this->valid() && $row > $this->key()) {
$this->next();
}
}
}
/**
* Get column limit
*
* @return int
*/
public function getColumnLimit() {
return $this->columnLimit;
}
}

View File

@@ -0,0 +1,319 @@
<?php
/**
* Csv Reader
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Reader;
use Asan\PHPExcel\Exception\ReaderException;
class Csv extends BaseReader {
/**
* File handle
*
* @var resource
*/
protected $fileHandle;
/**
* File read start
*
* @var int
*/
protected $start = 0;
/**
* Input encoding
*
* @var string
*/
protected $inputEncoding;
/**
* Delimiter
*
* @var string
*/
protected $delimiter;
/**
* Enclosure
*
* @var string
*/
protected $enclosure = '"';
/**
* Ignore empty row
*
* @var bool
*/
protected $ignoreEmpty = false;
/**
* Loads Excel from file
*
* @param string $file
*
* @throws ReaderException
* @return $this
*/
public function load($file) {
$lineEnding = ini_get('auto_detect_line_endings');
ini_set('auto_detect_line_endings', true);
// Open file
$this->openFile($file);
$this->autoDetection();
$this->generator = $this->makeGenerator();
ini_set('auto_detect_line_endings', $lineEnding);
return $this;
}
/**
* Count elements of the selected sheet
*
* @return int
*/
public function count() {
if ($this->count === null) {
$position = ftell($this->fileHandle);
$this->count = iterator_count($this->makeGenerator(true));
fseek($this->fileHandle, $position);
}
return $this->count;
}
/**
* Make the generator
*
* @param bool $calculate
* @return \Generator
*/
protected function makeGenerator($calculate = false) {
fseek($this->fileHandle, $this->start);
$finish = 0;
while (($row = fgetcsv($this->fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) {
if ($this->ignoreEmpty && (empty($row) || trim(implode('', $row)) === '')) {
continue;
}
if ($calculate) {
yield;
continue;
}
if ($this->rowLimit > 0 && ++$finish > $this->rowLimit) {
break;
}
if ($this->columnLimit > 0) {
$row = array_slice($row, 0, $this->columnLimit);
}
foreach ($row as &$value) {
if ($value != '') {
if (is_numeric($value)) {
$value = (float)$value;
}
// Convert encoding if necessary
if ($this->inputEncoding !== 'UTF-8') {
$value = mb_convert_encoding($value, 'UTF-8', $this->inputEncoding);
}
}
}
unset($value);
yield $row;
}
}
/**
* Detect the file delimiter and encoding
*/
protected function autoDetection() {
if (($this->delimiter !== null && $this->inputEncoding !== null)
|| ($line = fgets($this->fileHandle)) === false) {
return;
}
if ($this->delimiter === null) {
$this->delimiter = ',';
if ((strlen(trim($line, "\r\n")) == 5) && (stripos($line, 'sep=') === 0)) {
$this->delimiter = substr($line, 4, 1);
}
}
if ($this->inputEncoding === null) {
$this->inputEncoding = 'UTF-8';
if (($bom = substr($line, 0, 4)) == "\xFF\xFE\x00\x00" || $bom == "\x00\x00\xFE\xFF") {
$this->start = 4;
$this->inputEncoding = 'UTF-32';
} elseif (($bom = substr($line, 0, 2)) == "\xFF\xFE" || $bom == "\xFE\xFF") {
$this->start = 2;
$this->inputEncoding = 'UTF-16';
} elseif (($bom = substr($line, 0, 3)) == "\xEF\xBB\xBF") {
$this->start = 3;
}
if (!$this->start) {
$encoding = mb_detect_encoding($line, 'ASCII, UTF-8, GB2312, GBK');
if ($encoding) {
if ($encoding == 'EUC-CN') {
$encoding = 'GB2312';
} elseif ($encoding == 'CP936') {
$encoding = 'GBK';
}
$this->inputEncoding = $encoding;
}
}
}
fseek($this->fileHandle, $this->start);
}
/**
* Ignore empty row
*
* @param bool $ignoreEmpty
*
* @return $this
*/
public function ignoreEmptyRow($ignoreEmpty = false) {
$this->ignoreEmpty = $ignoreEmpty;
return $this;
}
/**
* Set input encoding
*
* @param string $encoding
* @return $this
*/
public function setInputEncoding($encoding = 'UTF-8') {
$this->inputEncoding = $encoding;
return $this;
}
/**
* Get input encoding
*
* @return string
*/
public function getInputEncoding() {
return $this->inputEncoding;
}
/**
* Set delimiter
*
* @param string $delimiter Delimiter, defaults to ,
* @return $this
*/
public function setDelimiter($delimiter = ',') {
$this->delimiter = $delimiter;
return $this;
}
/**
* Get delimiter
*
* @return string
*/
public function getDelimiter() {
return $this->delimiter;
}
/**
* Set enclosure
*
* @param string $enclosure Enclosure, defaults to "
* @return $this
*/
public function setEnclosure($enclosure = '"') {
if ($enclosure == '') {
$enclosure = '"';
}
$this->enclosure = $enclosure;
return $this;
}
/**
* Get enclosure
*
* @return string
*/
public function getEnclosure() {
return $this->enclosure;
}
/**
* Can the current Reader read the file?
*
* @param string $file
*
* @return bool
*/
public function canRead($file) {
try {
$this->openFile($file);
} catch (\Exception $e) {
return false;
}
fclose($this->fileHandle);
return true;
}
/**
* Open file for reading
*
* @param string $file
*
* @throws ReaderException
*/
protected function openFile($file) {
// Check if file exists
if (!file_exists($file) || !is_readable($file)) {
throw new ReaderException("Could not open file [$file] for reading! File does not exist.");
}
// Open file
$this->fileHandle = fopen($file, 'r');
if ($this->fileHandle === false) {
throw new ReaderException("Could not open file [$file] for reading.");
}
}
/**
* Close file and release generator
*/
public function __destruct() {
if ($this->fileHandle) {
fclose($this->fileHandle);
}
$this->generator = null;
}
}

View File

@@ -0,0 +1,163 @@
<?php
/**
* Xls Reader
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Reader;
use Asan\PHPExcel\Parser\Excel5;
use Asan\PHPExcel\Parser\Excel5\OLERead;
class Xls extends BaseReader {
/**
* Xls parser
*
* @var Excel5
*/
protected $parser;
/**
* File row、column count
*
* @var array|int
*/
protected $count;
public function __construct() {
$this->parser = new Excel5();
}
/**
* Loads Excel from file
*
* @param string $file
*
* @return $this
*/
public function load($file) {
$this->parser->loadOLE($file);
$this->generator = $this->makeGenerator();
return $this;
}
/**
* Count elements of the selected sheet
*
* @param bool $all
* @return int|array
*/
public function count($all = false) {
if ($this->count === null) {
$row = $column = 0;
if ($sheet = $this->sheets($this->parser->getSheetIndex())) {
$row = $sheet['totalRows'] ?? 0;
$column = $sheet['totalColumns'] ?? 0;
}
$this->count = [
$this->rowLimit > 0 ? min($row, $this->rowLimit) : $row,
$this->columnLimit > 0 ? min($column, $this->columnLimit) : $column
];
}
return $all ? $this->count : $this->count[0];
}
/**
* Get the work sheets info
*
* @param int $index
* @return array
*/
public function sheets($index = null) {
$sheets = $this->parser->parseWorksheetInfo();
if ($index !== null) {
return $sheets[$index] ?? [];
}
return $sheets;
}
/**
* Make the generator
*
* @return \Generator
*/
protected function makeGenerator() {
list($rowLimit, $columnLimit) = $this->count(true);
$line = $finish = 0;
while ($finish < $rowLimit && ($row = $this->parser->getRow($line++, $columnLimit)) !== false) {
if ($this->parser->isIgnoreEmptyRow() && trim(implode('', $row)) === '') {
continue;
}
$finish++;
yield $row;
}
}
/**
* Ignore empty row
*
* @param bool $ignoreEmpty
*
* @return $this
*/
public function ignoreEmptyRow($ignoreEmpty = false) {
$this->parser->ignoreEmptyRow($ignoreEmpty);
return $this;
}
/**
* Set sheet index
*
* @param int $index
* @return $this
*/
public function setSheetIndex($index) {
if ($index != $this->parser->getSheetIndex()) {
$this->parser->setSheetIndex($index);
$this->count = null;
$this->rewind();
}
return $this;
}
/**
* Can the current Reader read the file?
*
* @param string $file
*
* @return bool
*/
public function canRead($file) {
try {
// Use ParseXL for the hard work.
$ole = new OLERead();
// open file
$ole->openFile($file);
} catch (\Exception $e) {
return false;
}
return true;
}
/**
* Release parser and generator
*/
public function __destruct() {
$this->parser = null;
$this->generator = null;
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* Xlsx Reader
*
* @author Janson
* @create 2017-11-23
*/
namespace Asan\PHPExcel\Reader;
use Asan\PHPExcel\Parser\Excel2007;
class Xlsx extends BaseReader {
/**
* Xls parser
*
* @var Excel2007
*/
protected $parser;
/**
* File row、column count
*
* @var array|int
*/
protected $count;
public function __construct() {
$this->parser = new Excel2007();
}
/**
* Loads Excel from file
*
* @param string $file
*
* @return $this
*/
public function load($file) {
$this->parser->loadZip($file);
$this->generator = $this->makeGenerator();
return $this;
}
/**
* Count elements of an object
*
* @param bool $all
* @return int|array
*/
public function count($all = false) {
if ($this->count === null) {
$row = $column = 0;
if ($sheet = $this->sheets($this->parser->getSheetIndex())) {
$row = $sheet['totalRows'] ?? 0;
$column = $sheet['totalColumns'] ?? 0;
}
$this->count = [
$this->rowLimit > 0 ? min($row, $this->rowLimit) : $row,
$this->columnLimit > 0 ? min($column, $this->columnLimit) : $column
];
}
return $all ? $this->count : $this->count[0];
}
/**
* Get the work sheets info
*
* @param int $index
* @return array
*/
public function sheets($index = null) {
$sheets = $this->parser->parseWorksheetInfo();
if ($index !== null) {
return $sheets[$index] ?? [];
}
return $sheets;
}
/**
* Make the generator
*
* @return \Generator
*/
protected function makeGenerator() {
list($rowLimit, $columnLimit) = $this->count(true);
$line = $finish = 0;
while ($finish < $rowLimit && ($row = $this->parser->getRow($line++, $columnLimit)) !== false) {
if ($this->parser->isIgnoreEmptyRow() && trim(implode('', $row)) === '') {
continue;
}
$finish++;
yield $row;
}
}
/**
* Ignore empty row
*
* @param bool $ignoreEmpty
*
* @return $this
*/
public function ignoreEmptyRow($ignoreEmpty = false) {
$this->parser->ignoreEmptyRow($ignoreEmpty);
return $this;
}
/**
* Set sheet index
*
* @param int $index
* @return $this
*/
public function setSheetIndex($index = 0) {
if ($index != $this->parser->getSheetIndex()) {
$this->parser->setSheetIndex($index);
$this->count = null;
$this->rewind();
}
return $this;
}
/**
* Can the current Reader read the file?
*
* @param string $file
*
* @return bool
*/
public function canRead($file) {
try {
$parser = new Excel2007();
// open file
$parser->openFile($file);
} catch (\Exception $e) {
return false;
}
return true;
}
/**
* Release parser and generator
*/
public function __destruct() {
$this->parser = null;
$this->generator = null;
}
}

View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit08d888cc0ebe5ec4e5236ffc732c0960::getLoader();

View File

@@ -0,0 +1,481 @@
<?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
{
private $vendorDir;
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
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 array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
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 array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
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 array|string $paths The PSR-0 base directories
*/
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 array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
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
*/
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
*/
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
*/
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
*/
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.
*/
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($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;
}
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;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

View File

@@ -0,0 +1,337 @@
<?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 it's presence, you can require `composer-runtime-api ^2.0`
*/
class InstalledVersions
{
private static $installed;
private static $canGetVendors;
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 || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
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($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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
*/
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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: 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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: 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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: 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')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
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') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,10 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Asan\\PHPExcel\\' => array($vendorDir . '/asan/phpexcel/src'),
);

View File

@@ -0,0 +1,57 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit08d888cc0ebe5ec4e5236ffc732c0960
{
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('ComposerAutoloaderInit08d888cc0ebe5ec4e5236ffc732c0960', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit08d888cc0ebe5ec4e5236ffc732c0960', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit08d888cc0ebe5ec4e5236ffc732c0960::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

View File

@@ -0,0 +1,36 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit08d888cc0ebe5ec4e5236ffc732c0960
{
public static $prefixLengthsPsr4 = array (
'A' =>
array (
'Asan\\PHPExcel\\' => 14,
),
);
public static $prefixDirsPsr4 = array (
'Asan\\PHPExcel\\' =>
array (
0 => __DIR__ . '/..' . '/asan/phpexcel/src',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit08d888cc0ebe5ec4e5236ffc732c0960::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit08d888cc0ebe5ec4e5236ffc732c0960::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit08d888cc0ebe5ec4e5236ffc732c0960::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,50 @@
{
"packages": [
{
"name": "asan/phpexcel",
"version": "v2.0.1",
"version_normalized": "2.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/Janson-Leung/PHPExcel.git",
"reference": "07ddc15b44c1f3ee967ded35cffeab5fec49a215"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Janson-Leung/PHPExcel/zipball/07ddc15b44c1f3ee967ded35cffeab5fec49a215",
"reference": "07ddc15b44c1f3ee967ded35cffeab5fec49a215",
"shasum": ""
},
"require": {
"php": ">=7.0"
},
"time": "2018-07-23T01:42:26+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Asan\\PHPExcel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Janson Leung",
"homepage": "https://github.com/Janson-Leung"
}
],
"description": "A lightweight PHP library for reading spreadsheet files",
"homepage": "https://github.com/Janson-Leung/PHPExcel",
"support": {
"issues": "https://github.com/Janson-Leung/PHPExcel/issues",
"source": "https://github.com/Janson-Leung/PHPExcel/tree/master"
},
"install-path": "../asan/phpexcel"
}
],
"dev": true,
"dev-package-names": []
}

View File

@@ -0,0 +1,32 @@
<?php return array(
'root' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6582fe4c96d02e645921e4fb4300f84719b6b503',
'name' => '__root__',
'dev' => true,
),
'versions' => array(
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6582fe4c96d02e645921e4fb4300f84719b6b503',
'dev_requirement' => false,
),
'asan/phpexcel' => array(
'pretty_version' => 'v2.0.1',
'version' => '2.0.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../asan/phpexcel',
'aliases' => array(),
'reference' => '07ddc15b44c1f3ee967ded35cffeab5fec49a215',
'dev_requirement' => false,
),
),
);

View File

@@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70000)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}