[TASK] Introduce unique signal registration
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / Index / MetaDataRepository.php
1 <?php
2
3 namespace TYPO3\CMS\Core\Resource\Index;
4
5 /***************************************************************
6 * Copyright notice
7 *
8 * (c) 2013 Steffen Ritter <steffen.ritter@typo3.org>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the text file GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 use TYPO3\CMS\Core\Resource\File;
32 use TYPO3\CMS\Core\SingletonInterface;
33
34 /**
35 * Repository Class as an abstraction layer to sys_file_metadata
36 *
37 * Every access to table sys_file_metadata which is not handled by TCEmain
38 * has to use this Repository class
39 */
40 class MetaDataRepository implements SingletonInterface {
41
42 /**
43 * @var string
44 */
45 protected $tableName = 'sys_file_metadata';
46
47 /**
48 * Internal storage for database table fields
49 *
50 * @var array
51 */
52 protected $tableFields = array();
53
54 /**
55 * Wrapper method for getting DatabaseConnection
56 *
57 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
58 */
59 protected function getDatabaseConnection() {
60 return $GLOBALS['TYPO3_DB'];
61 }
62
63 /**
64 * Returns array of meta-data properties
65 *
66 * @param File $file
67 * @return array
68 */
69 public function findByFile(File $file) {
70 return $this->findByFileUid($file->getUid());
71 }
72
73 /**
74 * Retrieves metadata for file
75 *
76 * @param int $uid
77 * @return array
78 * @throws \RuntimeException
79 */
80 public function findByFileUid($uid) {
81 $uid = (int)$uid;
82 if ($uid <= 0) {
83 throw new \RuntimeException('Metadata can only be retrieved for indexed files.', 1381590731);
84 }
85 $record = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('*', $this->tableName, 'file = ' . $uid . $this->getGeneralWhereClause());
86
87 if ($record === FALSE) {
88 $record = $this->createMetaDataRecord($uid);
89 }
90
91 $passedData = new \ArrayObject($record);
92 $this->emitRecordPostRetrievalSignal($passedData);
93 return $passedData->getArrayCopy();
94 }
95
96 /**
97 * General Where-Clause which is needed to fetch only language 0 and live record.
98 *
99 * @return string
100 */
101 protected function getGeneralWhereClause() {
102 return ' AND sys_language_uid IN (0,-1) AND pid=0';
103 }
104
105 /**
106 * Create empty
107 *
108 * @param int $fileUid
109 * @param array $additionalFields
110 * @return array
111 */
112 public function createMetaDataRecord($fileUid, array $additionalFields = array()) {
113 $emptyRecord = array(
114 'file' => (int)$fileUid,
115 'pid' => 0,
116 'crdate' => $GLOBALS['EXEC_TIME'],
117 'tstamp' => $GLOBALS['EXEC_TIME'],
118 'cruser_id' => isset($GLOBALS['BE_USER']->user['uid']) ? (int)$GLOBALS['BE_USER']->user['uid'] : 0
119 );
120 $emptyRecord = array_merge($emptyRecord, $additionalFields);
121 $this->getDatabaseConnection()->exec_INSERTquery($this->tableName, $emptyRecord);
122 $record = $emptyRecord;
123 $record['uid'] = $this->getDatabaseConnection()->sql_insert_id();
124
125 $this->emitRecordCreatedSignal($record);
126
127 return $record;
128 }
129
130 /**
131 * Updates the metadata record in the database
132 *
133 * @param int $fileUid the file uid to update
134 * @param array $data Data to update
135 * @return void
136 * @internal
137 */
138 public function update($fileUid, array $data) {
139 if (count($this->tableFields) === 0) {
140 $this->tableFields = $this->getDatabaseConnection()->admin_get_fields($this->tableName);
141 }
142 $updateRow = array_intersect_key($data, $this->tableFields);
143 if (array_key_exists('uid', $updateRow)) {
144 unset($updateRow['uid']);
145 }
146 $row = $this->findByFileUid($fileUid);
147 if (count($updateRow) > 0) {
148 $updateRow['tstamp'] = time();
149 $this->getDatabaseConnection()->exec_UPDATEquery($this->tableName, 'uid = ' . (int)$row['uid'], $updateRow);
150
151 $this->emitRecordUpdatedSignal(array_merge($row, $updateRow));
152 }
153 }
154
155 /**
156 * Remove all metadata records for a certain file from the database
157 *
158 * @param integer $fileUid
159 * @return void
160 */
161 public function removeByFileUid($fileUid) {
162 $this->getDatabaseConnection()->exec_DELETEquery($this->tableName, 'file=' . (int)$fileUid);
163 $this->emitRecordDeletedSignal($fileUid);
164 }
165
166 /**
167 * Get the SignalSlot dispatcher
168 *
169 * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
170 */
171 protected function getSignalSlotDispatcher() {
172 return $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
173 }
174
175 /**
176 * Get the ObjectManager
177 *
178 * @return \TYPO3\CMS\Extbase\Object\ObjectManager
179 */
180 protected function getObjectManager() {
181 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
182 }
183
184 /**
185 * Signal that is called after a record has been loaded from database
186 * Allows other places to do extension of metadata at runtime or
187 * for example translation and workspace overlay
188 *
189 * @param \ArrayObject $data
190 * @signal
191 */
192 protected function emitRecordPostRetrievalSignal(\ArrayObject $data) {
193 $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository', 'recordPostRetrieval', array($data));
194 }
195
196 /**
197 * Signal that is called after an IndexRecord is updated
198 *
199 * @param array $data
200 * @signal
201 */
202 protected function emitRecordUpdatedSignal(array $data) {
203 $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository', 'recordUpdated', array($data));
204 }
205
206 /**
207 * Signal that is called after an IndexRecord is created
208 *
209 * @param array $data
210 * @signal
211 */
212 protected function emitRecordCreatedSignal(array $data) {
213 $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository', 'recordCreated', array($data));
214 }
215
216 /**
217 * Signal that is called after an IndexRecord is deleted
218 *
219 * @param integer $fileUid
220 * @signal
221 */
222 protected function emitRecordDeletedSignal($fileUid) {
223 $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository', 'recordDeleted', array($fileUid));
224 }
225
226 /**
227 * @return \TYPO3\CMS\Core\Resource\Index\MetaDataRepository
228 */
229 public static function getInstance() {
230 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Index\\MetaDataRepository');
231 }
232 }