Move Sheet to Common/Entity (#438)

... and introduce a SheetManager
This commit is contained in:
Adrien Loison authored and GitHub committed 2017-05-30 16:49:07 +02:00
1 parent 30366e6a5d
commit 3bb4fd3d48
14 files changed
+252 -112

No files matched your search

@@ -0,0 +1,149 @@
<?php
namespace Box\Spout\Writer\Common\Manager;
use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Exception\InvalidSheetNameException;
/**
* Class SheetManager
* Sheet manager
*
* @package Box\Spout\Writer\Common\Manager
*/
class SheetManager
{
/** Sheet name should not exceed 31 characters */
const MAX_LENGTH_SHEET_NAME = 31;
/** @var array Invalid characters that cannot be contained in the sheet name */
private static $INVALID_CHARACTERS_IN_SHEET_NAME = ['\\', '/', '?', '*', ':', '[', ']'];
/** @var array Associative array [WORKBOOK_ID] => [[SHEET_INDEX] => [SHEET_NAME]] keeping track of sheets' name to enforce uniqueness per workbook */
private static $SHEETS_NAME_USED = [];
/** @var StringHelper */
private $stringHelper;
/**
* SheetManager constructor.
*
* @param StringHelper $stringHelper
*/
public function __construct(StringHelper $stringHelper)
{
$this->stringHelper = $stringHelper;
}
/**
* Throws an exception if the given sheet's name is not valid.
* @see Sheet::setName for validity rules.
*
* @param string $name
* @param Sheet $sheet The sheet whose future name is checked
* @return void
* @throws \Box\Spout\Writer\Exception\InvalidSheetNameException If the sheet's name is invalid.
*/
public function throwIfNameIsInvalid($name, Sheet $sheet)
{
if (!is_string($name)) {
$actualType = gettype($name);
$errorMessage = "The sheet's name is invalid. It must be a string ($actualType given).";
throw new InvalidSheetNameException($errorMessage);
}
$failedRequirements = [];
$nameLength = $this->stringHelper->getStringLength($name);
if (!$this->isNameUnique($name, $sheet)) {
$failedRequirements[] = 'It should be unique';
} else {
if ($nameLength === 0) {
$failedRequirements[] = 'It should not be blank';
} else {
if ($nameLength > self::MAX_LENGTH_SHEET_NAME) {
$failedRequirements[] = 'It should not exceed 31 characters';
}
if ($this->doesContainInvalidCharacters($name)) {
$failedRequirements[] = 'It should not contain these characters: \\ / ? * : [ or ]';
}
if ($this->doesStartOrEndWithSingleQuote($name)) {
$failedRequirements[] = 'It should not start or end with a single quote';
}
}
}
if (count($failedRequirements) !== 0) {
$errorMessage = "The sheet's name (\"$name\") is invalid. It did not respect these rules:\n - ";
$errorMessage .= implode("\n - ", $failedRequirements);
throw new InvalidSheetNameException($errorMessage);
}
}
/**
* Returns whether the given name contains at least one invalid character.
* @see Sheet::$INVALID_CHARACTERS_IN_SHEET_NAME for the full list.
*
* @param string $name
* @return bool TRUE if the name contains invalid characters, FALSE otherwise.
*/
private function doesContainInvalidCharacters($name)
{
return (str_replace(self::$INVALID_CHARACTERS_IN_SHEET_NAME, '', $name) !== $name);
}
/**
* Returns whether the given name starts or ends with a single quote
*
* @param string $name
* @return bool TRUE if the name starts or ends with a single quote, FALSE otherwise.
*/
private function doesStartOrEndWithSingleQuote($name)
{
$startsWithSingleQuote = ($this->stringHelper->getCharFirstOccurrencePosition('\'', $name) === 0);
$endsWithSingleQuote = ($this->stringHelper->getCharLastOccurrencePosition('\'', $name) === ($this->stringHelper->getStringLength($name) - 1));
return ($startsWithSingleQuote || $endsWithSingleQuote);
}
/**
* Returns whether the given name is unique.
*
* @param string $name
* @param Sheet $sheet The sheet whose future name is checked
* @return bool TRUE if the name is unique, FALSE otherwise.
*/
private function isNameUnique($name, Sheet $sheet)
{
foreach (self::$SHEETS_NAME_USED[$sheet->getAssociatedWorkbookId()] as $sheetIndex => $sheetName) {
if ($sheetIndex !== $sheet->getIndex() && $sheetName === $name) {
return false;
}
}
return true;
}
/**
* @param int $workbookId Workbook ID associated to a Sheet
* @return void
*/
public function markWorkbookIdAsUsed($workbookId)
{
if (!isset(self::$SHEETS_NAME_USED[$workbookId])) {
self::$SHEETS_NAME_USED[$workbookId] = [];
}
}
/**
* @param Sheet $sheet
* @return void
*/
public function markSheetNameAsUsed(Sheet $sheet)
{
self::$SHEETS_NAME_USED[$sheet->getAssociatedWorkbookId()][$sheet->getIndex()] = $sheet->getName();
}
}
@@ -6,7 +6,7 @@ use Box\Spout\Common\Exception\IOException;
use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface;
use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface;
use Box\Spout\Writer\Common\Sheet;
use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Common\Entity\Workbook;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Exception\SheetNotFoundException;
@@ -113,7 +113,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
$worksheets = $this->getWorksheets();
$newSheetIndex = count($worksheets);
$sheet = new Sheet($newSheetIndex, $this->workbook->getInternalId());
$sheet = $this->entityFactory->createSheet($newSheetIndex, $this->workbook->getInternalId());
$worksheetFilePath = $this->getWorksheetFilePath($sheet);
$worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
@@ -3,7 +3,7 @@
namespace Box\Spout\Writer\Common\Manager;
use Box\Spout\Common\Exception\IOException;
use Box\Spout\Writer\Common\Sheet;
use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Common\Entity\Workbook;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Exception\SheetNotFoundException;