[TASK] Improve duplicate exception code check
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / Importer / ExtensionListUtility.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility\Importer;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Core\Database\ConnectionPool;
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Importer object for extension list
21 */
22 class ExtensionListUtility implements \SplObserver
23 {
24 /**
25 * Keeps instance of a XML parser.
26 *
27 * @var \TYPO3\CMS\Extensionmanager\Utility\Parser\AbstractExtensionXmlParser
28 */
29 protected $parser;
30
31 /**
32 * Keeps number of processed version records.
33 *
34 * @var int
35 */
36 protected $sumRecords = 0;
37
38 /**
39 * Keeps record values to be inserted into database.
40 *
41 * @var array
42 */
43 protected $arrRows = [];
44
45 /**
46 * Keeps fieldnames of tx_extensionmanager_domain_model_extension table.
47 *
48 * @var array
49 */
50 protected static $fieldNames = [
51 'extension_key',
52 'version',
53 'integer_version',
54 'current_version',
55 'alldownloadcounter',
56 'downloadcounter',
57 'title',
58 'ownerusername',
59 'author_name',
60 'author_email',
61 'authorcompany',
62 'last_updated',
63 'md5hash',
64 'repository',
65 'state',
66 'review_state',
67 'category',
68 'description',
69 'serialized_dependencies',
70 'update_comment'
71 ];
72
73 /**
74 * Keeps indexes of fields that should not be quoted.
75 *
76 * @var array
77 */
78 protected static $fieldIndicesNoQuote = [2, 3, 5, 11, 13, 14, 15, 16];
79
80 /**
81 * Keeps repository UID.
82 *
83 * The UID is necessary for inserting records.
84 *
85 * @var int
86 */
87 protected $repositoryUid = 1;
88
89 /**
90 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\RepositoryRepository
91 */
92 protected $repositoryRepository;
93
94 /**
95 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository
96 */
97 protected $extensionRepository;
98
99 /**
100 * @var \TYPO3\CMS\Extensionmanager\Domain\Model\Extension
101 */
102 protected $extensionModel;
103
104 /**
105 * Class constructor.
106 *
107 * Method retrieves and initializes extension XML parser instance.
108 *
109 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
110 */
111 public function __construct()
112 {
113 /** @var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager */
114 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
115 $this->repositoryRepository = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Domain\Repository\RepositoryRepository::class);
116 $this->extensionRepository = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository::class);
117 $this->extensionModel = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class);
118 // @todo catch parser exception
119 $this->parser = \TYPO3\CMS\Extensionmanager\Utility\Parser\XmlParserFactory::getParserInstance('extension');
120 if (is_object($this->parser)) {
121 $this->parser->attach($this);
122 } else {
123 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
124 get_class($this) . ': No XML parser available.',
125 1476108717
126 );
127 }
128 }
129
130 /**
131 * Method initializes parsing of extension.xml.gz file.
132 *
133 * @param string $localExtensionListFile absolute path to extension list xml.gz
134 * @param int $repositoryUid UID of repository when inserting records into DB
135 * @return int total number of imported extension versions
136 */
137 public function import($localExtensionListFile, $repositoryUid = null)
138 {
139 if (!is_null($repositoryUid) && is_int($repositoryUid)) {
140 $this->repositoryUid = $repositoryUid;
141 }
142 $zlibStream = 'compress.zlib://';
143 $this->sumRecords = 0;
144 $this->parser->parseXml($zlibStream . $localExtensionListFile);
145 // flush last rows to database if existing
146 if (!empty($this->arrRows)) {
147 GeneralUtility::makeInstance(ConnectionPool::class)
148 ->getConnectionForTable('tx_extensionmanager_domain_model_extension')
149 ->bulkInsert(
150 'tx_extensionmanager_domain_model_extension',
151 $this->arrRows,
152 self::$fieldNames
153 );
154 }
155 $extensions = $this->extensionRepository->insertLastVersion($this->repositoryUid);
156 $this->repositoryRepository->updateRepositoryCount($extensions, $this->repositoryUid);
157 return $this->sumRecords;
158 }
159
160 /**
161 * Method collects and stores extension version details into the database.
162 *
163 * @param \SplSubject|\TYPO3\CMS\Extensionmanager\Utility\Parser\AbstractExtensionXmlParser &$subject a subject notifying this observer
164 * @return void
165 */
166 protected function loadIntoDatabase(\SplSubject &$subject)
167 {
168 // flush every 50 rows to database
169 if ($this->sumRecords !== 0 && $this->sumRecords % 50 === 0) {
170 GeneralUtility::makeInstance(ConnectionPool::class)
171 ->getConnectionForTable('tx_extensionmanager_domain_model_extension')
172 ->bulkInsert(
173 'tx_extensionmanager_domain_model_extension',
174 $this->arrRows,
175 self::$fieldNames
176 );
177 $this->arrRows = [];
178 }
179 $versionRepresentations = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionStringToArray($subject->getVersion());
180 // order must match that of self::$fieldNames!
181 $this->arrRows[] = [
182 $subject->getExtkey(),
183 $subject->getVersion(),
184 $versionRepresentations['version_int'],
185 // initialize current_version, correct value computed later:
186 0,
187 (int)$subject->getAlldownloadcounter(),
188 (int)$subject->getDownloadcounter(),
189 !is_null($subject->getTitle()) ? $subject->getTitle() : '',
190 $subject->getOwnerusername(),
191 !is_null($subject->getAuthorname()) ? $subject->getAuthorname() : '',
192 !is_null($subject->getAuthoremail()) ? $subject->getAuthoremail() : '',
193 !is_null($subject->getAuthorcompany()) ? $subject->getAuthorcompany() : '',
194 (int)$subject->getLastuploaddate(),
195 $subject->getT3xfilemd5(),
196 $this->repositoryUid,
197 $this->extensionModel->getDefaultState($subject->getState() ?: ''),
198 (int)$subject->getReviewstate(),
199 $this->extensionModel->getCategoryIndexFromStringOrNumber($subject->getCategory() ?: ''),
200 $subject->getDescription() ?: '',
201 $subject->getDependencies() ?: '',
202 $subject->getUploadcomment() ?: ''
203 ];
204 ++$this->sumRecords;
205 }
206
207 /**
208 * Method receives an update from a subject.
209 *
210 * @param \SplSubject $subject a subject notifying this observer
211 * @return void
212 */
213 public function update(\SplSubject $subject)
214 {
215 if (is_subclass_of($subject, \TYPO3\CMS\Extensionmanager\Utility\Parser\AbstractExtensionXmlParser::class)) {
216 $this->loadIntoDatabase($subject);
217 }
218 }
219 }