/home/kueuepay/www/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php
<?php

namespace PhpOffice\PhpSpreadsheet\Worksheet;

use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;

class Table
{
    /**
     * Table Name.
     *
     * @var string
     */
    private $name;

    /**
     * Show Header Row.
     *
     * @var bool
     */
    private $showHeaderRow = true;

    /**
     * Show Totals Row.
     *
     * @var bool
     */
    private $showTotalsRow = false;

    /**
     * Table Range.
     *
     * @var string
     */
    private $range = '';

    /**
     * Table Worksheet.
     *
     * @var null|Worksheet
     */
    private $workSheet;

    /**
     * Table allow filter.
     *
     * @var bool
     */
    private $allowFilter = true;

    /**
     * Table Column.
     *
     * @var Table\Column[]
     */
    private $columns = [];

    /**
     * Table Style.
     *
     * @var TableStyle
     */
    private $style;

    /**
     * Table AutoFilter.
     *
     * @var AutoFilter
     */
    private $autoFilter;

    /**
     * Create a new Table.
     *
     * @param AddressRange|array<int>|string $range
     *            A simple string containing a Cell range like 'A1:E10' is permitted
     *              or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
     *              or an AddressRange object.
     * @param string $name (e.g. Table1)
     */
    public function __construct($range = '', string $name = '')
    {
        $this->style = new TableStyle();
        $this->autoFilter = new AutoFilter($range);
        $this->setRange($range);
        $this->setName($name);
    }

    /**
     * Get Table name.
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Set Table name.
     *
     * @throws PhpSpreadsheetException
     */
    public function setName(string $name): self
    {
        $name = trim($name);

        if (!empty($name)) {
            if (strlen($name) === 1 && in_array($name, ['C', 'c', 'R', 'r'])) {
                throw new PhpSpreadsheetException('The table name is invalid');
            }
            if (StringHelper::countCharacters($name) > 255) {
                throw new PhpSpreadsheetException('The table name cannot be longer than 255 characters');
            }
            // Check for A1 or R1C1 cell reference notation
            if (
                preg_match(Coordinate::A1_COORDINATE_REGEX, $name) ||
                preg_match('/^R\[?\-?[0-9]*\]?C\[?\-?[0-9]*\]?$/i', $name)
            ) {
                throw new PhpSpreadsheetException('The table name can\'t be the same as a cell reference');
            }
            if (!preg_match('/^[\p{L}_\\\\]/iu', $name)) {
                throw new PhpSpreadsheetException('The table name must begin a name with a letter, an underscore character (_), or a backslash (\)');
            }
            if (!preg_match('/^[\p{L}_\\\\][\p{L}\p{M}0-9\._]+$/iu', $name)) {
                throw new PhpSpreadsheetException('The table name contains invalid characters');
            }

            $this->checkForDuplicateTableNames($name, $this->workSheet);
            $this->updateStructuredReferences($name);
        }

        $this->name = $name;

        return $this;
    }

    /**
     * @throws PhpSpreadsheetException
     */
    private function checkForDuplicateTableNames(string $name, ?Worksheet $worksheet): void
    {
        // Remember that table names are case-insensitive
        $tableName = StringHelper::strToLower($name);

        if ($worksheet !== null && StringHelper::strToLower($this->name) !== $name) {
            $spreadsheet = $worksheet->getParentOrThrow();

            foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
                foreach ($sheet->getTableCollection() as $table) {
                    if (StringHelper::strToLower($table->getName()) === $tableName && $table != $this) {
                        throw new PhpSpreadsheetException("Spreadsheet already contains a table named '{$this->name}'");
                    }
                }
            }
        }
    }

    private function updateStructuredReferences(string $name): void
    {
        if ($this->workSheet === null || $this->name === null || $this->name === '') {
            return;
        }

        // Remember that table names are case-insensitive
        if (StringHelper::strToLower($this->name) !== StringHelper::strToLower($name)) {
            // We need to check all formula cells that might contain fully-qualified Structured References
            //    that refer to this table, and update those formulae to reference the new table name
            $spreadsheet = $this->workSheet->getParentOrThrow();
            foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
                $this->updateStructuredReferencesInCells($sheet, $name);
            }
            $this->updateStructuredReferencesInNamedFormulae($spreadsheet, $name);
        }
    }

    private function updateStructuredReferencesInCells(Worksheet $worksheet, string $newName): void
    {
        $pattern = '/' . preg_quote($this->name, '/') . '\[/mui';

        foreach ($worksheet->getCoordinates(false) as $coordinate) {
            $cell = $worksheet->getCell($coordinate);
            if ($cell->getDataType() === DataType::TYPE_FORMULA) {
                $formula = $cell->getValue();
                if (preg_match($pattern, $formula) === 1) {
                    $formula = preg_replace($pattern, "{$newName}[", $formula);
                    $cell->setValueExplicit($formula, DataType::TYPE_FORMULA);
                }
            }
        }
    }

    private function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $newName): void
    {
        $pattern = '/' . preg_quote($this->name, '/') . '\[/mui';

        foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
            $formula = $namedFormula->getValue();
            if (preg_match($pattern, $formula) === 1) {
                $formula = preg_replace($pattern, "{$newName}[", $formula);
                $namedFormula->setValue($formula); // @phpstan-ignore-line
            }
        }
    }

    /**
     * Get show Header Row.
     */
    public function getShowHeaderRow(): bool
    {
        return $this->showHeaderRow;
    }

    /**
     * Set show Header Row.
     */
    public function setShowHeaderRow(bool $showHeaderRow): self
    {
        $this->showHeaderRow = $showHeaderRow;

        return $this;
    }

    /**
     * Get show Totals Row.
     */
    public function getShowTotalsRow(): bool
    {
        return $this->showTotalsRow;
    }

    /**
     * Set show Totals Row.
     */
    public function setShowTotalsRow(bool $showTotalsRow): self
    {
        $this->showTotalsRow = $showTotalsRow;

        return $this;
    }

    /**
     * Get allow filter.
     * If false, autofiltering is disabled for the table, if true it is enabled.
     */
    public function getAllowFilter(): bool
    {
        return $this->allowFilter;
    }

    /**
     * Set show Autofiltering.
     * Disabling autofiltering has the same effect as hiding the filter button on all the columns in the table.
     */
    public function setAllowFilter(bool $allowFilter): self
    {
        $this->allowFilter = $allowFilter;

        return $this;
    }

    /**
     * Get Table Range.
     */
    public function getRange(): string
    {
        return $this->range;
    }

    /**
     * Set Table Cell Range.
     *
     * @param AddressRange|array<int>|string $range
     *            A simple string containing a Cell range like 'A1:E10' is permitted
     *              or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
     *              or an AddressRange object.
     */
    public function setRange($range = ''): self
    {
        // extract coordinate
        if ($range !== '') {
            [, $range] = Worksheet::extractSheetTitle(Validations::validateCellRange($range), true);
        }
        if (empty($range)) {
            //    Discard all column rules
            $this->columns = [];
            $this->range = '';

            return $this;
        }

        if (strpos($range, ':') === false) {
            throw new PhpSpreadsheetException('Table must be set on a range of cells.');
        }

        [$width, $height] = Coordinate::rangeDimension($range);
        if ($width < 1 || $height < 1) {
            throw new PhpSpreadsheetException('The table range must be at least 1 column and row');
        }

        $this->range = $range;
        $this->autoFilter->setRange($range);

        //    Discard any column rules that are no longer valid within this range
        [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
        foreach ($this->columns as $key => $value) {
            $colIndex = Coordinate::columnIndexFromString($key);
            if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) {
                unset($this->columns[$key]);
            }
        }

        return $this;
    }

    /**
     * Set Table Cell Range to max row.
     */
    public function setRangeToMaxRow(): self
    {
        if ($this->workSheet !== null) {
            $thisrange = $this->range;
            $range = (string) preg_replace('/\\d+$/', (string) $this->workSheet->getHighestRow(), $thisrange);
            if ($range !== $thisrange) {
                $this->setRange($range);
            }
        }

        return $this;
    }

    /**
     * Get Table's Worksheet.
     */
    public function getWorksheet(): ?Worksheet
    {
        return $this->workSheet;
    }

    /**
     * Set Table's Worksheet.
     */
    public function setWorksheet(?Worksheet $worksheet = null): self
    {
        if ($this->name !== '' && $worksheet !== null) {
            $spreadsheet = $worksheet->getParentOrThrow();
            $tableName = StringHelper::strToUpper($this->name);

            foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
                foreach ($sheet->getTableCollection() as $table) {
                    if (StringHelper::strToUpper($table->getName()) === $tableName) {
                        throw new PhpSpreadsheetException("Workbook already contains a table named '{$this->name}'");
                    }
                }
            }
        }

        $this->workSheet = $worksheet;
        $this->autoFilter->setParent($worksheet);

        return $this;
    }

    /**
     * Get all Table Columns.
     *
     * @return Table\Column[]
     */
    public function getColumns(): array
    {
        return $this->columns;
    }

    /**
     * Validate that the specified column is in the Table range.
     *
     * @param string $column Column name (e.g. A)
     *
     * @return int The column offset within the table range
     */
    public function isColumnInRange(string $column): int
    {
        if (empty($this->range)) {
            throw new PhpSpreadsheetException('No table range is defined.');
        }

        $columnIndex = Coordinate::columnIndexFromString($column);
        [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
        if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) {
            throw new PhpSpreadsheetException('Column is outside of current table range.');
        }

        return $columnIndex - $rangeStart[0];
    }

    /**
     * Get a specified Table Column Offset within the defined Table range.
     *
     * @param string $column Column name (e.g. A)
     *
     * @return int The offset of the specified column within the table range
     */
    public function getColumnOffset($column): int
    {
        return $this->isColumnInRange($column);
    }

    /**
     * Get a specified Table Column.
     *
     * @param string $column Column name (e.g. A)
     */
    public function getColumn($column): Table\Column
    {
        $this->isColumnInRange($column);

        if (!isset($this->columns[$column])) {
            $this->columns[$column] = new Table\Column($column, $this);
        }

        return $this->columns[$column];
    }

    /**
     * Get a specified Table Column by it's offset.
     *
     * @param int $columnOffset Column offset within range (starting from 0)
     */
    public function getColumnByOffset($columnOffset): Table\Column
    {
        [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
        $pColumn = Coordinate::stringFromColumnIndex($rangeStart[0] + $columnOffset);

        return $this->getColumn($pColumn);
    }

    /**
     * Set Table.
     *
     * @param string|Table\Column $columnObjectOrString
     *            A simple string containing a Column ID like 'A' is permitted
     */
    public function setColumn($columnObjectOrString): self
    {
        if ((is_string($columnObjectOrString)) && (!empty($columnObjectOrString))) {
            $column = $columnObjectOrString;
        } elseif (is_object($columnObjectOrString) && ($columnObjectOrString instanceof Table\Column)) {
            $column = $columnObjectOrString->getColumnIndex();
        } else {
            throw new PhpSpreadsheetException('Column is not within the table range.');
        }
        $this->isColumnInRange($column);

        if (is_string($columnObjectOrString)) {
            $this->columns[$columnObjectOrString] = new Table\Column($columnObjectOrString, $this);
        } else {
            $columnObjectOrString->setTable($this);
            $this->columns[$column] = $columnObjectOrString;
        }
        ksort($this->columns);

        return $this;
    }

    /**
     * Clear a specified Table Column.
     *
     * @param string $column Column name (e.g. A)
     */
    public function clearColumn($column): self
    {
        $this->isColumnInRange($column);

        if (isset($this->columns[$column])) {
            unset($this->columns[$column]);
        }

        return $this;
    }

    /**
     * Shift an Table Column Rule to a different column.
     *
     * Note: This method bypasses validation of the destination column to ensure it is within this Table range.
     *        Nor does it verify whether any column rule already exists at $toColumn, but will simply override any existing value.
     *        Use with caution.
     *
     * @param string $fromColumn Column name (e.g. A)
     * @param string $toColumn Column name (e.g. B)
     */
    public function shiftColumn($fromColumn, $toColumn): self
    {
        $fromColumn = strtoupper($fromColumn);
        $toColumn = strtoupper($toColumn);

        if (($fromColumn !== null) && (isset($this->columns[$fromColumn])) && ($toColumn !== null)) {
            $this->columns[$fromColumn]->setTable();
            $this->columns[$fromColumn]->setColumnIndex($toColumn);
            $this->columns[$toColumn] = $this->columns[$fromColumn];
            $this->columns[$toColumn]->setTable($this);
            unset($this->columns[$fromColumn]);

            ksort($this->columns);
        }

        return $this;
    }

    /**
     * Get table Style.
     */
    public function getStyle(): Table\TableStyle
    {
        return $this->style;
    }

    /**
     * Set table Style.
     */
    public function setStyle(TableStyle $style): self
    {
        $this->style = $style;

        return $this;
    }

    /**
     * Get AutoFilter.
     */
    public function getAutoFilter(): AutoFilter
    {
        return $this->autoFilter;
    }

    /**
     * Set AutoFilter.
     */
    public function setAutoFilter(AutoFilter $autoFilter): self
    {
        $this->autoFilter = $autoFilter;

        return $this;
    }

    /**
     * Implement PHP __clone to create a deep clone, not just a shallow copy.
     */
    public function __clone()
    {
        $vars = get_object_vars($this);
        foreach ($vars as $key => $value) {
            if (is_object($value)) {
                if ($key === 'workSheet') {
                    //    Detach from worksheet
                    $this->{$key} = null;
                } else {
                    $this->{$key} = clone $value;
                }
            } elseif ((is_array($value)) && ($key === 'columns')) {
                //    The columns array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table objects
                $this->{$key} = [];
                foreach ($value as $k => $v) {
                    $this->{$key}[$k] = clone $v;
                    // attach the new cloned Column to this new cloned Table object
                    $this->{$key}[$k]->setTable($this);
                }
            } else {
                $this->{$key} = $value;
            }
        }
    }

    /**
     * toString method replicates previous behavior by returning the range if object is
     * referenced as a property of its worksheet.
     */
    public function __toString()
    {
        return (string) $this->range;
    }
}
Kueue Pay | Contactless Payment System
top

Quick Steps to NFC Pay

Getting started with NFC Pay is simple and quick. Register your account, add your cards, and you're ready to make payments in no time. Whether you're paying at a store, sending money to a friend, or managing your merchant transactions, NFC Pay makes it easy and secure.

1

Register Your Account

Download the NFC Pay app and sign up with your email or phone number. Complete the registration process by verifying your identity, and set up your secure PIN to protect your account.

2

Add Your Cards

Link your debit or credit cards to your NFC Pay wallet. Simply scan your card or enter the details manually, and you’re set to load funds, shop, and pay with ease.

3

Make Payment

To pay, simply tap your phone or scan the QR code at checkout. You can also transfer money to other users with a few taps. Enjoy fast, contactless payments with top-notch security.

Advanced Security Features Designed to Protect Your Information Effectively

NFC Pay prioritizes your security with advanced features that safeguard every transaction. From SMS or email verification to end-to-end encryption, we've implemented robust measures to ensure your data is always protected. Our security systems are designed to prevent unauthorized access and provide you with a safe and reliable payment experience.

img

SMS or Email Verification

Receive instant alerts for every transaction to keep track of your account activities.

img

KYC Solution

Verify your identity through our Know Your Customer process to prevent fraud and enhance security.

img

Two Factor Authentication

Dramatically supply transparent backward deliverables before caward comp internal or "organic" sources.

img

End-to-End Encryption

All your data and transactions are encrypted, ensuring that your sensitive information remains private.

img

Behavior Tracking

Monitor unusual activity patterns to detect and prevent suspicious behavior in real-time.

Top Reasons to Choose Us for Reliable and Expert Solutions

With NFC Pay, you get a trusted platform backed by proven expertise and a commitment to quality. We put our customers first, offering innovative solutions tailored to your needs, ensuring every transaction is secure, swift, and seamless.

1

Proven Expertise

Our team brings years of experience in the digital payments industry to provide reliable services.

2

Commitment to Quality

We prioritize excellence, ensuring that every aspect of our platform meets the highest standards.

3

Customer-Centric Approach

Your needs drive our solutions, and we are dedicated to delivering a superior user experience.

4

Innovative Solutions

We continuously evolve, integrating the latest technologies to enhance your payment experience.

Customer Feedback: Real Experiences from Satisfied Clients and Partners

Hear from our users who trust NFC Pay for their everyday transactions. Our commitment to security, ease of use, and exceptional service shines through in their experiences. See why our clients choose NFC Pay for their payment needs and how it has transformed the way they manage their finances.

"NFC Pay has made my transactions incredibly simple and secure. The intuitive interface and quick payment options are game-changers for my business"

"I love how NFC Pay prioritizes security without compromising on convenience. The two-factor authentication and instant alerts give me peace of mind every time I use it."

"Setting up my merchant account was a breeze, and now I can accept payments effortlessly. NFC Pay has truly streamlined my operations, saving me time and hassle."

Get the NFC Pay App for Seamless Transactions Anytime, Anywhere

Unlock the full potential of NFC Pay by downloading our app, designed to bring secure, swift, and smart transactions to your fingertips. Whether you're paying at a store, transferring money to friends, or managing your business payments, the NFC Pay app makes it effortless. Available on both iOS and Android, it's your all-in-one solution for convenient and reliable digital payments. Download now and experience the future of payments!

img