package and depencies

This commit is contained in:
RafficMohammed
2023-01-08 02:57:24 +05:30
parent d5332eb421
commit 1d54b8bc7f
4309 changed files with 193331 additions and 172289 deletions

View File

@@ -0,0 +1,115 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Helper;
use PhpOffice\PhpSpreadsheet\Exception;
use PhpOffice\PhpSpreadsheet\Shared\Drawing;
use PhpOffice\PhpSpreadsheet\Style\Font;
class Dimension
{
public const UOM_CENTIMETERS = 'cm';
public const UOM_MILLIMETERS = 'mm';
public const UOM_INCHES = 'in';
public const UOM_PIXELS = 'px';
public const UOM_POINTS = 'pt';
public const UOM_PICA = 'pc';
/**
* Based on 96 dpi.
*/
const ABSOLUTE_UNITS = [
self::UOM_CENTIMETERS => 96.0 / 2.54,
self::UOM_MILLIMETERS => 96.0 / 25.4,
self::UOM_INCHES => 96.0,
self::UOM_PIXELS => 1.0,
self::UOM_POINTS => 96.0 / 72,
self::UOM_PICA => 96.0 * 12 / 72,
];
/**
* Based on a standard column width of 8.54 units in MS Excel.
*/
const RELATIVE_UNITS = [
'em' => 10.0 / 8.54,
'ex' => 10.0 / 8.54,
'ch' => 10.0 / 8.54,
'rem' => 10.0 / 8.54,
'vw' => 8.54,
'vh' => 8.54,
'vmin' => 8.54,
'vmax' => 8.54,
'%' => 8.54 / 100,
];
/**
* @var float|int If this is a width, then size is measured in pixels (if is set)
* or in Excel's default column width units if $unit is null.
* If this is a height, then size is measured in pixels ()
* or in points () if $unit is null.
*/
protected $size;
/**
* @var null|string
*/
protected $unit;
/**
* Phpstan bug has been fixed; this function allows us to
* pass Phpstan whether fixed or not.
*
* @param mixed $value
*/
private static function stanBugFixed($value): array
{
return is_array($value) ? $value : [null, null];
}
public function __construct(string $dimension)
{
[$size, $unit] = self::stanBugFixed(sscanf($dimension, '%[1234567890.]%s'));
$unit = strtolower(trim($unit ?? ''));
$size = (float) $size;
// If a UoM is specified, then convert the size to pixels for internal storage
if (isset(self::ABSOLUTE_UNITS[$unit])) {
$size *= self::ABSOLUTE_UNITS[$unit];
$this->unit = self::UOM_PIXELS;
} elseif (isset(self::RELATIVE_UNITS[$unit])) {
$size *= self::RELATIVE_UNITS[$unit];
$size = round($size, 4);
}
$this->size = $size;
}
public function width(): float
{
return (float) ($this->unit === null)
? $this->size
: round(Drawing::pixelsToCellDimension((int) $this->size, new Font(false)), 4);
}
public function height(): float
{
return (float) ($this->unit === null)
? $this->size
: $this->toUnit(self::UOM_POINTS);
}
public function toUnit(string $unitOfMeasure): float
{
$unitOfMeasure = strtolower($unitOfMeasure);
if (!array_key_exists($unitOfMeasure, self::ABSOLUTE_UNITS)) {
throw new Exception("{$unitOfMeasure} is not a vaid unit of measure");
}
$size = $this->size;
if ($this->unit === null) {
$size = Drawing::cellDimensionToPixels($size, new Font(false));
}
return $size / self::ABSOLUTE_UNITS[$unitOfMeasure];
}
}

View File

@@ -12,7 +12,7 @@ use PhpOffice\PhpSpreadsheet\Style\Font;
class Html
{
protected static $colourMap = [
private const COLOUR_MAP = [
'aliceblue' => 'f0f8ff',
'antiquewhite' => 'faebd7',
'antiquewhite1' => 'ffefdb',
@@ -532,25 +532,34 @@ class Html
'yellowgreen' => '9acd32',
];
protected $face;
/** @var ?string */
private $face;
protected $size;
/** @var ?string */
private $size;
protected $color;
/** @var ?string */
private $color;
protected $bold = false;
/** @var bool */
private $bold = false;
protected $italic = false;
/** @var bool */
private $italic = false;
protected $underline = false;
/** @var bool */
private $underline = false;
protected $superscript = false;
/** @var bool */
private $superscript = false;
protected $subscript = false;
/** @var bool */
private $subscript = false;
protected $strikethrough = false;
/** @var bool */
private $strikethrough = false;
protected $startTagCallbacks = [
private const START_TAG_CALLBACKS = [
'font' => 'startFontTag',
'b' => 'startBoldTag',
'strong' => 'startBoldTag',
@@ -563,7 +572,7 @@ class Html
'sub' => 'startSubscriptTag',
];
protected $endTagCallbacks = [
private const END_TAG_CALLBACKS = [
'font' => 'endFontTag',
'b' => 'endBoldTag',
'strong' => 'endBoldTag',
@@ -584,16 +593,18 @@ class Html
'h6' => 'breakTag',
];
protected $stack = [];
/** @var array */
private $stack = [];
protected $stringData = '';
/** @var string */
private $stringData = '';
/**
* @var RichText
*/
protected $richTextObject;
private $richTextObject;
protected function initialise(): void
private function initialise(): void
{
$this->face = $this->size = $this->color = null;
$this->bold = $this->italic = $this->underline = $this->superscript = $this->subscript = $this->strikethrough = false;
@@ -619,6 +630,7 @@ class Html
// Load the HTML file into the DOM object
// Note the use of error suppression, because typically this will be an html fragment, so not fully valid markup
$prefix = '<?xml encoding="UTF-8">';
/** @scrutinizer ignore-unhandled */
@$dom->loadHTML($prefix . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// Discard excess white space
$dom->preserveWhiteSpace = false;
@@ -632,7 +644,7 @@ class Html
return $this->richTextObject;
}
protected function cleanWhitespace(): void
private function cleanWhitespace(): void
{
foreach ($this->richTextObject->getRichTextElements() as $key => $element) {
$text = $element->getText();
@@ -641,12 +653,12 @@ class Html
$text = ltrim($text);
}
// Trim any spaces immediately after a line break
$text = preg_replace('/\n */mu', "\n", $text);
$text = (string) preg_replace('/\n */mu', "\n", $text);
$element->setText($text);
}
}
protected function buildTextRun(): void
private function buildTextRun(): void
{
$text = $this->stringData;
if (trim($text) === '') {
@@ -654,39 +666,42 @@ class Html
}
$richtextRun = $this->richTextObject->createTextRun($this->stringData);
if ($this->face) {
$richtextRun->getFont()->setName($this->face);
}
if ($this->size) {
$richtextRun->getFont()->setSize($this->size);
}
if ($this->color) {
$richtextRun->getFont()->setColor(new Color('ff' . $this->color));
}
if ($this->bold) {
$richtextRun->getFont()->setBold(true);
}
if ($this->italic) {
$richtextRun->getFont()->setItalic(true);
}
if ($this->underline) {
$richtextRun->getFont()->setUnderline(Font::UNDERLINE_SINGLE);
}
if ($this->superscript) {
$richtextRun->getFont()->setSuperscript(true);
}
if ($this->subscript) {
$richtextRun->getFont()->setSubscript(true);
}
if ($this->strikethrough) {
$richtextRun->getFont()->setStrikethrough(true);
$font = $richtextRun->getFont();
if ($font !== null) {
if ($this->face) {
$font->setName($this->face);
}
if ($this->size) {
$font->setSize($this->size);
}
if ($this->color) {
$font->setColor(new Color('ff' . $this->color));
}
if ($this->bold) {
$font->setBold(true);
}
if ($this->italic) {
$font->setItalic(true);
}
if ($this->underline) {
$font->setUnderline(Font::UNDERLINE_SINGLE);
}
if ($this->superscript) {
$font->setSuperscript(true);
}
if ($this->subscript) {
$font->setSubscript(true);
}
if ($this->strikethrough) {
$font->setStrikethrough(true);
}
}
$this->stringData = '';
}
protected function rgbToColour($rgb)
private function rgbToColour(string $rgbValue): string
{
preg_match_all('/\d+/', $rgb, $values);
preg_match_all('/\d+/', $rgbValue, $values);
foreach ($values[0] as &$value) {
$value = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
}
@@ -694,107 +709,110 @@ class Html
return implode('', $values[0]);
}
public static function colourNameLookup(string $rgb): string
public static function colourNameLookup(string $colorName): string
{
return self::$colourMap[$rgb] ?? '';
return self::COLOUR_MAP[$colorName] ?? '';
}
protected function startFontTag($tag): void
private function startFontTag(DOMElement $tag): void
{
foreach ($tag->attributes as $attribute) {
$attributeName = strtolower($attribute->name);
$attributeValue = $attribute->value;
$attrs = $tag->attributes;
if ($attrs !== null) {
foreach ($attrs as $attribute) {
$attributeName = strtolower($attribute->name);
$attributeValue = $attribute->value;
if ($attributeName == 'color') {
if (preg_match('/rgb\s*\(/', $attributeValue)) {
$this->$attributeName = $this->rgbToColour($attributeValue);
} elseif (strpos(trim($attributeValue), '#') === 0) {
$this->$attributeName = ltrim($attributeValue, '#');
if ($attributeName == 'color') {
if (preg_match('/rgb\s*\(/', $attributeValue)) {
$this->$attributeName = $this->rgbToColour($attributeValue);
} elseif (strpos(trim($attributeValue), '#') === 0) {
$this->$attributeName = ltrim($attributeValue, '#');
} else {
$this->$attributeName = static::colourNameLookup($attributeValue);
}
} else {
$this->$attributeName = $this->colourNameLookup($attributeValue);
$this->$attributeName = $attributeValue;
}
} else {
$this->$attributeName = $attributeValue;
}
}
}
protected function endFontTag(): void
private function endFontTag(): void
{
$this->face = $this->size = $this->color = null;
}
protected function startBoldTag(): void
private function startBoldTag(): void
{
$this->bold = true;
}
protected function endBoldTag(): void
private function endBoldTag(): void
{
$this->bold = false;
}
protected function startItalicTag(): void
private function startItalicTag(): void
{
$this->italic = true;
}
protected function endItalicTag(): void
private function endItalicTag(): void
{
$this->italic = false;
}
protected function startUnderlineTag(): void
private function startUnderlineTag(): void
{
$this->underline = true;
}
protected function endUnderlineTag(): void
private function endUnderlineTag(): void
{
$this->underline = false;
}
protected function startSubscriptTag(): void
private function startSubscriptTag(): void
{
$this->subscript = true;
}
protected function endSubscriptTag(): void
private function endSubscriptTag(): void
{
$this->subscript = false;
}
protected function startSuperscriptTag(): void
private function startSuperscriptTag(): void
{
$this->superscript = true;
}
protected function endSuperscriptTag(): void
private function endSuperscriptTag(): void
{
$this->superscript = false;
}
protected function startStrikethruTag(): void
private function startStrikethruTag(): void
{
$this->strikethrough = true;
}
protected function endStrikethruTag(): void
private function endStrikethruTag(): void
{
$this->strikethrough = false;
}
protected function breakTag(): void
private function breakTag(): void
{
$this->stringData .= "\n";
}
protected function parseTextNode(DOMText $textNode): void
private function parseTextNode(DOMText $textNode): void
{
$domText = preg_replace(
$domText = (string) preg_replace(
'/\s+/u',
' ',
str_replace(["\r", "\n"], ' ', $textNode->nodeValue)
str_replace(["\r", "\n"], ' ', $textNode->nodeValue ?? '')
);
$this->stringData .= $domText;
$this->buildTextRun();
@@ -803,30 +821,31 @@ class Html
/**
* @param string $callbackTag
*/
protected function handleCallback(DOMElement $element, $callbackTag, array $callbacks): void
private function handleCallback(DOMElement $element, $callbackTag, array $callbacks): void
{
if (isset($callbacks[$callbackTag])) {
$elementHandler = $callbacks[$callbackTag];
if (method_exists($this, $elementHandler)) {
/** @phpstan-ignore-next-line */
call_user_func([$this, $elementHandler], $element);
}
}
}
protected function parseElementNode(DOMElement $element): void
private function parseElementNode(DOMElement $element): void
{
$callbackTag = strtolower($element->nodeName);
$this->stack[] = $callbackTag;
$this->handleCallback($element, $callbackTag, $this->startTagCallbacks);
$this->handleCallback($element, $callbackTag, self::START_TAG_CALLBACKS);
$this->parseElements($element);
array_pop($this->stack);
$this->handleCallback($element, $callbackTag, $this->endTagCallbacks);
$this->handleCallback($element, $callbackTag, self::END_TAG_CALLBACKS);
}
protected function parseElements(DOMNode $element): void
private function parseElements(DOMNode $element): void
{
foreach ($element->childNodes as $child) {
if ($child instanceof DOMText) {

View File

@@ -4,8 +4,8 @@ namespace PhpOffice\PhpSpreadsheet\Helper;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Writer\IWriter;
use PhpOffice\PhpSpreadsheet\Writer\Pdf;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RecursiveRegexIterator;
@@ -71,12 +71,17 @@ class Sample
/**
* Returns an array of all known samples.
*
* @return string[] [$name => $path]
* @return string[][] [$name => $path]
*/
public function getSamples()
{
// Populate samples
$baseDir = realpath(__DIR__ . '/../../../samples');
if ($baseDir === false) {
// @codeCoverageIgnoreStart
throw new RuntimeException('realpath returned false');
// @codeCoverageIgnoreEnd
}
$directory = new RecursiveDirectoryIterator($baseDir);
$iterator = new RecursiveIteratorIterator($directory);
$regex = new RegexIterator($iterator, '/^.+\.php$/', RecursiveRegexIterator::GET_MATCH);
@@ -84,9 +89,14 @@ class Sample
$files = [];
foreach ($regex as $file) {
$file = str_replace(str_replace('\\', '/', $baseDir) . '/', '', str_replace('\\', '/', $file[0]));
if (is_array($file)) {
// @codeCoverageIgnoreStart
throw new RuntimeException('str_replace returned array');
// @codeCoverageIgnoreEnd
}
$info = pathinfo($file);
$category = str_replace('_', ' ', $info['dirname']);
$name = str_replace('_', ' ', preg_replace('/(|\.php)/', '', $info['filename']));
$category = str_replace('_', ' ', $info['dirname'] ?? '');
$name = str_replace('_', ' ', (string) preg_replace('/(|\.php)/', '', $info['filename']));
if (!in_array($category, ['.', 'boostrap', 'templates'])) {
if (!isset($files[$category])) {
$files[$category] = [];
@@ -119,19 +129,19 @@ class Sample
foreach ($writers as $writerType) {
$path = $this->getFilename($filename, mb_strtolower($writerType));
$writer = IOFactory::createWriter($spreadsheet, $writerType);
if ($writer instanceof Pdf) {
// PDF writer needs temporary directory
$tempDir = $this->getTemporaryFolder();
$writer->setTempDir($tempDir);
}
$callStartTime = microtime(true);
$writer->save($path);
$this->logWrite($writer, $path, $callStartTime);
$this->logWrite($writer, $path, /** @scrutinizer ignore-type */ $callStartTime);
}
$this->logEndingNotes();
}
protected function isDirOrMkdir(string $folder): bool
{
return \is_dir($folder) || \mkdir($folder);
}
/**
* Returns the temporary directory and make sure it exists.
*
@@ -140,10 +150,8 @@ class Sample
private function getTemporaryFolder()
{
$tempFolder = sys_get_temp_dir() . '/phpspreadsheet';
if (!is_dir($tempFolder)) {
if (!mkdir($tempFolder) && !is_dir($tempFolder)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $tempFolder));
}
if (!$this->isDirOrMkdir($tempFolder)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $tempFolder));
}
return $tempFolder;
@@ -161,7 +169,7 @@ class Sample
{
$originalExtension = pathinfo($filename, PATHINFO_EXTENSION);
return $this->getTemporaryFolder() . '/' . str_replace('.' . $originalExtension, '.' . $extension, basename($filename));
return $this->getTemporaryFolder() . '/' . str_replace('.' . /** @scrutinizer ignore-type */ $originalExtension, '.' . $extension, basename($filename));
}
/**
@@ -174,17 +182,49 @@ class Sample
public function getTemporaryFilename($extension = 'xlsx')
{
$temporaryFilename = tempnam($this->getTemporaryFolder(), 'phpspreadsheet-');
if ($temporaryFilename === false) {
// @codeCoverageIgnoreStart
throw new RuntimeException('tempnam returned false');
// @codeCoverageIgnoreEnd
}
unlink($temporaryFilename);
return $temporaryFilename . '.' . $extension;
}
public function log($message): void
public function log(string $message): void
{
$eol = $this->isCli() ? PHP_EOL : '<br />';
echo date('H:i:s ') . $message . $eol;
}
public function titles(string $category, string $functionName, ?string $description = null): void
{
$this->log(sprintf('%s Functions:', $category));
$description === null
? $this->log(sprintf('Function: %s()', rtrim($functionName, '()')))
: $this->log(sprintf('Function: %s() - %s.', rtrim($functionName, '()'), rtrim($description, '.')));
}
public function displayGrid(array $matrix): void
{
$renderer = new TextGrid($matrix, $this->isCli());
echo $renderer->render();
}
public function logCalculationResult(
Worksheet $worksheet,
string $functionName,
string $formulaCell,
?string $descriptionCell = null
): void {
if ($descriptionCell !== null) {
$this->log($worksheet->getCell($descriptionCell)->getValue());
}
$this->log($worksheet->getCell($formulaCell)->getValue());
$this->log(sprintf('%s() Result is ', $functionName) . $worksheet->getCell($formulaCell)->getCalculatedValue());
}
/**
* Log ending notes.
*/

View File

@@ -0,0 +1,52 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Helper;
class Size
{
const REGEXP_SIZE_VALIDATION = '/^(?P<size>\d*\.?\d+)(?P<unit>pt|px|em)?$/i';
/**
* @var bool
*/
protected $valid;
/**
* @var string
*/
protected $size = '';
/**
* @var string
*/
protected $unit = '';
public function __construct(string $size)
{
$this->valid = (bool) preg_match(self::REGEXP_SIZE_VALIDATION, $size, $matches);
if ($this->valid) {
$this->size = $matches['size'];
$this->unit = $matches['unit'] ?? 'pt';
}
}
public function valid(): bool
{
return $this->valid;
}
public function size(): string
{
return $this->size;
}
public function unit(): string
{
return $this->unit;
}
public function __toString()
{
return $this->size . $this->unit;
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Helper;
class TextGrid
{
/**
* @var bool
*/
private $isCli = true;
/**
* @var array
*/
protected $matrix;
/**
* @var array
*/
protected $rows;
/**
* @var array
*/
protected $columns;
/**
* @var string
*/
private $gridDisplay;
public function __construct(array $matrix, bool $isCli = true)
{
$this->rows = array_keys($matrix);
$this->columns = array_keys($matrix[$this->rows[0]]);
$matrix = array_values($matrix);
array_walk(
$matrix,
function (&$row): void {
$row = array_values($row);
}
);
$this->matrix = $matrix;
$this->isCli = $isCli;
}
public function render(): string
{
$this->gridDisplay = $this->isCli ? '' : '<code>';
$maxRow = max($this->rows);
$maxRowLength = strlen((string) $maxRow) + 1;
$columnWidths = $this->getColumnWidths();
$this->renderColumnHeader($maxRowLength, $columnWidths);
$this->renderRows($maxRowLength, $columnWidths);
$this->renderFooter($maxRowLength, $columnWidths);
$this->gridDisplay .= $this->isCli ? '' : '</code>';
return $this->gridDisplay;
}
private function renderRows(int $maxRowLength, array $columnWidths): void
{
foreach ($this->matrix as $row => $rowData) {
$this->gridDisplay .= '|' . str_pad((string) $this->rows[$row], $maxRowLength, ' ', STR_PAD_LEFT) . ' ';
$this->renderCells($rowData, $columnWidths);
$this->gridDisplay .= '|' . PHP_EOL;
}
}
private function renderCells(array $rowData, array $columnWidths): void
{
foreach ($rowData as $column => $cell) {
$cell = ($this->isCli) ? (string) $cell : htmlentities((string) $cell);
$this->gridDisplay .= '| ';
$this->gridDisplay .= str_pad($cell, $columnWidths[$column] + 1, ' ');
}
}
private function renderColumnHeader(int $maxRowLength, array $columnWidths): void
{
$this->gridDisplay .= str_repeat(' ', $maxRowLength + 2);
foreach ($this->columns as $column => $reference) {
$this->gridDisplay .= '+-' . str_repeat('-', $columnWidths[$column] + 1);
}
$this->gridDisplay .= '+' . PHP_EOL;
$this->gridDisplay .= str_repeat(' ', $maxRowLength + 2);
foreach ($this->columns as $column => $reference) {
$this->gridDisplay .= '| ' . str_pad((string) $reference, $columnWidths[$column] + 1, ' ');
}
$this->gridDisplay .= '|' . PHP_EOL;
$this->renderFooter($maxRowLength, $columnWidths);
}
private function renderFooter(int $maxRowLength, array $columnWidths): void
{
$this->gridDisplay .= '+' . str_repeat('-', $maxRowLength + 1);
foreach ($this->columns as $column => $reference) {
$this->gridDisplay .= '+-';
$this->gridDisplay .= str_pad((string) '', $columnWidths[$column] + 1, '-');
}
$this->gridDisplay .= '+' . PHP_EOL;
}
private function getColumnWidths(): array
{
$columnCount = count($this->matrix, COUNT_RECURSIVE) / count($this->matrix);
$columnWidths = [];
for ($column = 0; $column < $columnCount; ++$column) {
$columnWidths[] = $this->getColumnWidth(array_column($this->matrix, $column));
}
return $columnWidths;
}
private function getColumnWidth(array $columnData): int
{
$columnWidth = 0;
$columnData = array_values($columnData);
foreach ($columnData as $columnValue) {
if (is_string($columnValue)) {
$columnWidth = max($columnWidth, strlen($columnValue));
} elseif (is_bool($columnValue)) {
$columnWidth = max($columnWidth, strlen($columnValue ? 'TRUE' : 'FALSE'));
}
$columnWidth = max($columnWidth, strlen((string) $columnWidth));
}
return $columnWidth;
}
}