TYPO3 CMS  TYPO3_6-2
RteFileLinksUpdateWizard.php
Go to the documentation of this file.
1 <?php
3 
18 
25 
30  protected $title = 'Migrate all file links of RTE-enabled fields to FAL';
31 
35  protected $fileAdminDir;
36 
41  protected $storage;
42 
46  protected $rteHtmlParser;
47 
52  protected $convertedLinkCounter = 0;
53 
58  protected $isDbalInstalled = FALSE;
59 
64  protected $errors = array();
65 
70  protected $queries = array();
71 
77  public function init() {
78  $this->rteHtmlParser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\RteHtmlParser');
80  $storageRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
81  $storages = $storageRepository->findAll();
82  $this->storage = $storages[0];
83  $this->fileAdminDir = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'];
84  // Check if DBAL is installed or not
85  $this->isDbalInstalled = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('dbal');
86  }
87 
94  public function checkForUpdate(&$description) {
95  $description = 'This update wizard goes through all file links in all rich-text fields and changes them to FAL references.';
96  $description .= 'If the process times out, please run it again.';
97  // Issue warning about sys_refindex needing to be up to date
100  'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
101  'This script bases itself on the references contained in the general reference index (sys_refindex). It is strongly advised to update it before running this wizard.',
102  'Updating the reference index',
103  \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
104  );
105  $description .= $message->render();
106 
107  // Confirm activation only if some old-style links are found
108  $oldRecords = $this->findOldLinks();
109  if (count($oldRecords) > 0) {
110  $description .= '<br />There are currently <strong>' . count($oldRecords) . '</strong> links to update.<br />';
111  return TRUE;
112  }
113 
114  // No update needed, disable the wizard
115  return FALSE;
116  }
117 
125  public function performUpdate(array &$dbQueries, &$customMessages) {
126  $this->init();
127 
128  // Make sure we have a storage
129  if (!$this->storage) {
130  $customMessages = 'No file resource storage found';
131  return FALSE;
132  }
133 
134  // Get the references and migrate them
135  $records = $this->findOldLinks();
136  foreach ($records as $singleRecord) {
137  $this->migrateRecord($singleRecord);
138  }
139  $dbQueries = $this->queries;
140 
141  if (count($this->errors) > 0) {
142  $customMessages .= implode(PHP_EOL, $this->errors);
143  if ($this->convertedLinkCounter == 0) {
144  // no links converted only missing files: UPDATE was not successful
145  return FALSE;
146  }
147  }
148 
149  if ($this->convertedLinkCounter > 0) {
150  $customMessages = $this->convertedLinkCounter . ' links converted.' . PHP_EOL . $customMessages;
151  } else {
152  $customMessages .= 'No file links found';
153  }
154  return TRUE;
155  }
156 
163  protected function migrateRecord(array $reference) {
164  // Get the current record based on the sys_refindex information
165  $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
166  'uid, ' . $reference['field'],
167  $reference['tablename'],
168  'uid = ' . $reference['recuid']
169  );
170  if (is_array($record)) {
171  $this->convertFileLinks($reference, $record);
172  } else {
173  // Original record could not be found (happens if sys_refindex is not up to date), issue error
174  $this->errors[] = 'Original record not found for reference to element ' . $reference['recuid'] . ' of table ' . $reference['tablename'] . ' in field ' . $reference['field'] . '. Not migrated.';
175  }
176  }
177 
186  protected function convertFileLinks(array $reference, array $record) {
187  // First of all, try to get the referenced file. Continue only if found.
188  try {
189  $fileObject = $this->fetchReferencedFile($reference['ref_string'], $reference);
190  } catch (\InvalidArgumentException $exception) {
191  $fileObject = NULL;
192  $this->errors[] = $reference['ref_string'] . ' could not be replaced. File does not exist.';
193  }
194  if ($fileObject instanceof \TYPO3\CMS\Core\Resource\AbstractFile) {
195  // Next, match the reference path in the content to be sure it's present inside a <link> tag
196  $content = $record[$reference['field']];
197  $regularExpression = '$<((link|LINK) ' . str_replace('%2F', '/', rawurlencode($reference['ref_string'])) . ').*>$';
198  $matches = array();
199  $result = preg_match($regularExpression, $content, $matches);
200  if ($result) {
201  // Replace the file path with the file reference
202  $modifiedContent = str_replace(
203  $matches[1],
204  'link file:' . $fileObject->getUid(),
205  $record[$reference['field']]
206  );
207  // Save the changes and stop looping
208  $this->saveChanges($modifiedContent, $reference, $fileObject);
209  $this->convertedLinkCounter++;
210  } else {
211  $this->errors[] = $reference['ref_string'] . ' not found in referenced element (uid: ' . $reference['recuid'] . ' of table ' . $reference['tablename'] . ' in field ' . $reference['field'] . '). Reference index was probably out of date.';
212  }
213  }
214  }
215 
223  protected function fetchReferencedFile($path, array $reference) {
224  $fileObject = NULL;
225  if (@file_exists(PATH_site . '/' . $path)) {
226  try {
227  $fileObject = $this->storage->getFile(
228  '/' . str_replace(
229  $this->fileAdminDir,
230  '',
231  $path
232  )
233  );
234  } catch (\TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException $notFoundException) {
235  // This should really not happen, since we are testing existence of the file just before
236  $this->errors[] = $path . ' not found (referenced in element ' . $reference['recuid'] . ' of table ' . $reference['tablename'] . ' in field ' . $reference['field'] . ')';
237  }
238  } else {
239  // Nothing to be done if file not found, but output errors with (page) pid in csv format for easier manual treatment
240  $recpid = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
241  'pid',
242  $reference['tablename'],
243  'uid = ' . (int)$reference['recuid']
244  );
245  $this->errors[] = 'File not found (page / uid / path / table / field):,'
246  . $recpid[0]['pid'] . ','
247  . $reference['recuid'] . ','
248  . $path . ','
249  . $reference['tablename'] . ','
250  . $reference['field'];
251  }
252  return $fileObject;
253  }
254 
263  protected function saveChanges($modifiedText, array $reference, $file) {
264 
265  // If DBAL is not installed, we can start a transaction before saving
266  // This ensures that a possible time out doesn't break the database integrity
267  // by occurring between the two needed DB writes.
268  if (!$this->isDbalInstalled) {
269  $GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION');
270  }
271 
272  // Save the changed field
273  $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
274  $reference['tablename'],
275  'uid = ' . $reference['recuid'],
276  array(
277  $reference['field'] => $modifiedText
278  )
279  );
280  $this->queries[] = htmlspecialchars(str_replace(LF, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery));
281 
282  // Finally, update the sys_refindex table as well
283  $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
284  'sys_refindex',
285  'hash = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($reference['hash'], 'sys_refindex'),
286  array(
287  'ref_table' => 'sys_file',
288  'ref_uid' => $file->getUid(),
289  'ref_string' => ''
290  )
291  );
292  $this->queries[] = str_replace(LF, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
293 
294  // Confirm the transaction
295  if (!$this->isDbalInstalled) {
296  $GLOBALS['TYPO3_DB']->sql_query('COMMIT');
297  }
298  }
299 
307  protected function findOldLinks() {
308  $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
309  'hash, tablename, recuid, field, ref_table, ref_uid, ref_string',
310  'sys_refindex',
311  'softref_key = \'typolink_tag\' AND ref_table = \'_FILE\' '
312  );
313  return $records;
314  }
315 
316 }
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]