Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OpenSpout\Writer\Common\Manager;
6
 
7
use OpenSpout\Common\Helper\StringHelper;
8
use OpenSpout\Writer\Common\Entity\Sheet;
9
use OpenSpout\Writer\Exception\InvalidSheetNameException;
10
 
11
/**
12
 * @internal
13
 */
14
final class SheetManager
15
{
16
    /**
17
     * Sheet name should not exceed 31 characters.
18
     */
19
    public const MAX_LENGTH_SHEET_NAME = 31;
20
 
21
    /**
22
     * Invalid characters that cannot be contained in the sheet name.
23
     */
24
    private const INVALID_CHARACTERS_IN_SHEET_NAME = ['\\', '/', '?', '*', ':', '[', ']'];
25
 
26
    /** @var array<string, array<int, string>> Associative array [WORKBOOK_ID] => [[SHEET_INDEX] => [SHEET_NAME]] keeping track of sheets' name to enforce uniqueness per workbook */
27
    private static array $SHEETS_NAME_USED = [];
28
 
29
    private readonly StringHelper $stringHelper;
30
 
31
    /**
32
     * SheetManager constructor.
33
     */
34
    public function __construct(StringHelper $stringHelper)
35
    {
36
        $this->stringHelper = $stringHelper;
37
    }
38
 
39
    /**
40
     * Throws an exception if the given sheet's name is not valid.
41
     *
42
     * @see Sheet::setName for validity rules.
43
     *
44
     * @param Sheet $sheet The sheet whose future name is checked
45
     *
46
     * @throws InvalidSheetNameException if the sheet's name is invalid
47
     */
48
    public function throwIfNameIsInvalid(string $name, Sheet $sheet): void
49
    {
50
        $failedRequirements = [];
51
        $nameLength = $this->stringHelper->getStringLength($name);
52
 
53
        if (!$this->isNameUnique($name, $sheet)) {
54
            $failedRequirements[] = 'It should be unique';
55
        } elseif (0 === $nameLength) {
56
            $failedRequirements[] = 'It should not be blank';
57
        } else {
58
            if ($nameLength > self::MAX_LENGTH_SHEET_NAME) {
59
                $failedRequirements[] = 'It should not exceed 31 characters';
60
            }
61
 
62
            if ($this->doesContainInvalidCharacters($name)) {
63
                $failedRequirements[] = 'It should not contain these characters: \\ / ? * : [ or ]';
64
            }
65
 
66
            if ($this->doesStartOrEndWithSingleQuote($name)) {
67
                $failedRequirements[] = 'It should not start or end with a single quote';
68
            }
69
        }
70
 
71
        if (0 !== \count($failedRequirements)) {
72
            $errorMessage = "The sheet's name (\"{$name}\") is invalid. It did not respect these rules:\n - ";
73
            $errorMessage .= implode("\n - ", $failedRequirements);
74
 
75
            throw new InvalidSheetNameException($errorMessage);
76
        }
77
    }
78
 
79
    /**
80
     * @param string $workbookId Workbook ID associated to a Sheet
81
     */
82
    public function markWorkbookIdAsUsed(string $workbookId): void
83
    {
84
        if (!isset(self::$SHEETS_NAME_USED[$workbookId])) {
85
            self::$SHEETS_NAME_USED[$workbookId] = [];
86
        }
87
    }
88
 
89
    public function markSheetNameAsUsed(Sheet $sheet): void
90
    {
91
        self::$SHEETS_NAME_USED[$sheet->getAssociatedWorkbookId()][$sheet->getIndex()] = $sheet->getName();
92
    }
93
 
94
    /**
95
     * Returns whether the given name contains at least one invalid character.
96
     *
97
     * @return bool TRUE if the name contains invalid characters, FALSE otherwise
98
     */
99
    private function doesContainInvalidCharacters(string $name): bool
100
    {
101
        return str_replace(self::INVALID_CHARACTERS_IN_SHEET_NAME, '', $name) !== $name;
102
    }
103
 
104
    /**
105
     * Returns whether the given name starts or ends with a single quote.
106
     *
107
     * @return bool TRUE if the name starts or ends with a single quote, FALSE otherwise
108
     */
109
    private function doesStartOrEndWithSingleQuote(string $name): bool
110
    {
111
        $startsWithSingleQuote = (0 === $this->stringHelper->getCharFirstOccurrencePosition('\'', $name));
112
        $endsWithSingleQuote = ($this->stringHelper->getCharLastOccurrencePosition('\'', $name) === ($this->stringHelper->getStringLength($name) - 1));
113
 
114
        return $startsWithSingleQuote || $endsWithSingleQuote;
115
    }
116
 
117
    /**
118
     * Returns whether the given name is unique.
119
     *
120
     * @param Sheet $sheet The sheet whose future name is checked
121
     *
122
     * @return bool TRUE if the name is unique, FALSE otherwise
123
     */
124
    private function isNameUnique(string $name, Sheet $sheet): bool
125
    {
126
        foreach (self::$SHEETS_NAME_USED[$sheet->getAssociatedWorkbookId()] as $sheetIndex => $sheetName) {
127
            if ($sheetIndex !== $sheet->getIndex() && $sheetName === $name) {
128
                return false;
129
            }
130
        }
131
 
132
        return true;
133
    }
134
}