db1ff3276abb66aeb6f7dbeddd3a8929a162e311
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Resource / MetaDataAspectTest.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\Tests\Unit\Resource;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Prophecy\Argument;
20 use TYPO3\CMS\Core\Database\Connection;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Resource\Exception\InvalidUidException;
23 use TYPO3\CMS\Core\Resource\File;
24 use TYPO3\CMS\Core\Resource\Index\MetaDataRepository;
25 use TYPO3\CMS\Core\Resource\MetaDataAspect;
26 use TYPO3\CMS\Core\Resource\ResourceStorage;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
29
30 /**
31 * Test case
32 */
33 class MetaDataAspectTest extends UnitTestCase
34 {
35 /**
36 * @var ResourceStorage|\PHPUnit\Framework\MockObject\MockObject
37 */
38 protected $storageMock;
39
40 /**
41 * Set up
42 */
43 protected function setUp(): void
44 {
45 $this->storageMock = $this->createMock(ResourceStorage::class);
46 $this->storageMock->expects($this->any())->method('getUid')->will($this->returnValue(12));
47 }
48
49 /**
50 * Tear down
51 */
52 protected function tearDown(): void
53 {
54 $this->resetSingletonInstances = true;
55
56 GeneralUtility::purgeInstances();
57 parent::tearDown();
58 }
59
60 /**
61 * @test
62 */
63 public function knownMetaDataIsAdded(): void
64 {
65 $metaData = [
66 'width' => 4711,
67 'title' => 'Lorem ipsum meta sit amet',
68 ];
69 $file = new File([], $this->storageMock, $metaData);
70
71 $this->assertSame($metaData, $file->getMetaData()->get());
72 }
73
74 /**
75 * @test
76 */
77 public function manuallyAddedMetaDataIsMerged(): void
78 {
79 $metaData = [
80 'width' => 4711,
81 'title' => 'Lorem ipsum meta sit amet',
82 ];
83 $file = new File([], $this->storageMock, $metaData);
84 $file->getMetaData()->add([
85 'height' => 900,
86 'description' => 'This file is presented by TYPO3',
87 ]);
88
89 $expected = [
90 'width' => 4711,
91 'title' => 'Lorem ipsum meta sit amet',
92 'height' => 900,
93 'description' => 'This file is presented by TYPO3',
94 ];
95
96 $this->assertSame($expected, $file->getMetaData()->get());
97 }
98
99 /**
100 * @test
101 */
102 public function metaDataGetsRemoved(): void
103 {
104 $metaData = ['foo' => 'bar'];
105
106 $file = new File(['uid' => 12], $this->storageMock);
107
108 /** @var MetaDataAspect|\PHPUnit\Framework\MockObject\MockObject $metaDataAspectMock */
109 $metaDataAspectMock = $this->getMockBuilder(MetaDataAspect::class)
110 ->setConstructorArgs([$file])
111 ->setMethods(['getMetaDataRepository'])
112 ->getMock();
113
114 $metaDataAspectMock->add($metaData);
115 $metaDataAspectMock->remove();
116
117 $this->assertEmpty($metaDataAspectMock->get());
118 }
119
120 /**
121 * @test
122 */
123 public function positiveUidOfFileIsExpectedToLoadMetaData(): void
124 {
125 $this->expectException(InvalidUidException::class);
126 $this->expectExceptionCode(1381590731);
127
128 $file = new File(['uid' => -3], $this->storageMock);
129 $file->getMetaData()->get();
130 }
131
132 /**
133 * @test
134 */
135 public function newMetaDataIsCreated(): void
136 {
137 $GLOBALS['EXEC_TIME'] = 1534530781;
138 $metaData = [
139 'title' => 'Hooray',
140 // This value is ignored on purpose, we simulate the non-existence of the field "description"
141 'description' => 'Yipp yipp yipp',
142 ];
143
144 $file = new File(['uid' => 12], $this->storageMock);
145
146 $connectionProphecy = $this->prophesize(Connection::class);
147 $connectionProphecy->insert(Argument::cetera())->willReturn(1);
148 $connectionProphecy->lastInsertId(Argument::cetera())->willReturn(5);
149 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
150 $connectionPoolProphecy->getConnectionForTable(Argument::cetera())->willReturn($connectionProphecy->reveal());
151 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
152
153 $metaDataRepositoryMock = $this->getMockBuilder(MetaDataRepository::class)
154 ->setMethods(['findByFileUid', 'getTableFields', 'update'])
155 ->getMock();
156 $metaDataRepositoryMock->expects($this->any())->method('findByFileUid')->willReturn([]);
157 $metaDataRepositoryMock->expects($this->any())->method('getTableFields')->willReturn(['title' => 'sometype']);
158 $metaDataRepositoryMock->expects($this->never())->method('update');
159 GeneralUtility::setSingletonInstance(MetaDataRepository::class, $metaDataRepositoryMock);
160
161 $file->getMetaData()->add($metaData)->save();
162
163 $expected = [
164 'file' => $file->getUid(),
165 'pid' => 0,
166 'crdate' => 1534530781,
167 'tstamp' => 1534530781,
168 'cruser_id' => 0,
169 'l10n_diffsource' => '',
170 'title' => 'Hooray',
171 'uid' => '5',
172 'newlyCreated' => true,
173 ];
174
175 $this->assertSame($expected, $file->getMetaData()->get());
176 }
177
178 /**
179 * @test
180 */
181 public function existingMetaDataGetsUpdated(): void
182 {
183 $metaData = ['foo' => 'bar'];
184
185 $file = new File(['uid' => 12], $this->storageMock);
186
187 $metaDataRepositoryMock = $this->getMockBuilder(MetaDataRepository::class)
188 ->setMethods(['loadFromRepository', 'createMetaDataRecord', 'update'])
189 ->getMock();
190
191 $metaDataRepositoryMock->expects($this->any())->method('createMetaDataRecord')->willReturn($metaData);
192 GeneralUtility::setSingletonInstance(MetaDataRepository::class, $metaDataRepositoryMock);
193
194 $metaDataAspectMock = $this->getMockBuilder(MetaDataAspect::class)
195 ->setConstructorArgs([$file])
196 ->setMethods(['loadFromRepository'])
197 ->getMock();
198
199 $metaDataAspectMock->expects($this->any())->method('loadFromRepository')->will($this->onConsecutiveCalls([], $metaData));
200 $metaDataAspectMock->add($metaData)->save();
201 $metaDataAspectMock->add(['testproperty' => 'testvalue'])->save();
202
203 $this->assertSame(['foo' => 'bar', 'testproperty' => 'testvalue'], $metaDataAspectMock->get());
204 }
205
206 /**
207 * @return array
208 */
209 public function propertyDataProvider(): array
210 {
211 return [
212 [
213 [
214 'width' => 4711,
215 'title' => 'Lorem ipsum meta sit amet',
216 ],
217 [
218 'property' => 'width',
219 'expected' => true,
220 ],
221 [
222 'property' => 'width',
223 'expected' => 4711,
224 ],
225 ],
226 [
227 [
228 'foo' => 'bar',
229 ],
230 [
231 'property' => 'husel',
232 'expected' => false,
233 ],
234 [
235 'property' => 'husel',
236 'expected' => null,
237 ],
238 ],
239 ];
240 }
241
242 /**
243 * @param $metaData
244 * @param $has
245 * @param $get
246 * @test
247 * @dataProvider propertyDataProvider
248 */
249 public function propertyIsFetchedProperly($metaData, $has, $get): void
250 {
251 $file = new File([], $this->storageMock, $metaData);
252
253 $this->assertSame($has['expected'], isset($file->getMetaData()[$has['property']]));
254 $this->assertSame($get['expected'], $file->getMetaData()[$get['property']] ?? null);
255 }
256 }