Last active
December 19, 2015 08:29
-
-
Save nicodh/5926450 to your computer and use it in GitHub Desktop.
Update wizard for file links in RTE fields. Migrates links like
<link fileadmin/download.pdf download >Download</link> to <link file:123 download >Download</link>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace TYPO3\CMS\Install\Updates; | |
/*************************************************************** | |
* Copyright notice | |
* | |
* (c) 2013 Nico de Haen | |
* All rights reserved | |
* | |
* This script is part of the TYPO3 project. The TYPO3 project is | |
* free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* The GNU General Public License can be found at | |
* http://www.gnu.org/copyleft/gpl.html. | |
* | |
* This script is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* This copyright notice MUST APPEAR in all copies of the script! | |
***************************************************************/ | |
use TYPO3\CMS\Core\Utility\GeneralUtility; | |
/** | |
* Upgrade wizard which goes through tt_content records | |
* and replaces links with a path reference with the according sys_file reference | |
* | |
* @author Nico de Haen | |
* @license http://www.gnu.org/copyleft/gpl.html | |
*/ | |
class RteFileLinksUpdateWizard extends \TYPO3\CMS\Install\Updates\AbstractUpdate { | |
/** | |
* @var string | |
*/ | |
protected $title = 'Migrate file relations of tt_content "bodytext"'; | |
/* | |
* @var \TYPO3\CMS\Core\Html\RteHtmlParser | |
*/ | |
protected $rteHtmlParser; | |
/** | |
* should we include deleted content elements here? | |
* | |
* @var string | |
*/ | |
protected $addWhere = 'bodytext RLIKE "<link[[:space:]]*([[:alnum:]]|_|-)*/" AND deleted = 0'; | |
/** | |
* @var int | |
*/ | |
protected $convertedLinkCounter = 0; | |
/** | |
* | |
* @var array | |
*/ | |
protected $fileNotFoundErrors = array(); | |
/** | |
* Reference to the current record | |
* to enable meaningful error messages in recursion method | |
* @var null|array | |
*/ | |
protected $currentRecord = NULL; | |
/** | |
* The default storage | |
* @var \TYPO3\CMS\Core\Resource\ResourceStorage | |
*/ | |
protected $storage = NULL; | |
protected $fileAdminDir; | |
/** | |
* Initialize all required repository and factory objects. | |
* | |
* @throws \RuntimeException | |
*/ | |
protected function init() { | |
$this->rteHtmlParser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\RteHtmlParser'); | |
$storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository'); | |
$storages = $storageRepository->findAll(); | |
$this->storage = $storages[0]; | |
$this->fileAdminDir = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir']; | |
} | |
/** | |
* Checks if an update is needed | |
* | |
* @param string &$description: The description for the update | |
* @return boolean TRUE if an update is needed, FALSE otherwise | |
*/ | |
public function checkForUpdate(&$description) { | |
$updateNeeded = FALSE; | |
$notMigratedRowsCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( | |
'uid', | |
'tt_content', | |
$this->addWhere | |
); | |
// Fetch records where the field contains file links | |
if ($notMigratedRowsCount > 0) { | |
$description = 'There are file links in RTE fields referencing files without using the file abstraction layer FAL.'; | |
$updateNeeded = TRUE; | |
} | |
return $updateNeeded; | |
} | |
/** | |
* Performs the update. | |
* | |
* @param array &$dbQueries: queries done in this update | |
* @param mixed &$customMessages: custom messages | |
* @return boolean TRUE on success, FALSE on error | |
*/ | |
public function performUpdate(array &$dbQueries, &$customMessages) { | |
$this->init(); | |
if(!$this->storage) { | |
$customMessages = 'No file resource storage found'; | |
return FALSE; | |
} | |
$records = $this->getRecordsFromTable('tt_content'); | |
foreach($records as $singleRecord) { | |
$this->migrateRecord($singleRecord); | |
} | |
if(count($this->fileNotFoundErrors) > 0) { | |
$customMessages .= '<strong>' . count($this->fileNotFoundErrors). ' missing files:</strong><br />'; | |
$customMessages .= implode('<br />', $this->fileNotFoundErrors); | |
if($this->convertedLinkCounter == 0) { | |
// no links converted only missing files: UPDATE was not successful | |
return FALSE; | |
} | |
} | |
if($this->convertedLinkCounter > 0) { | |
$customMessages = $this->convertedLinkCounter . ' links converted.<br />' . $customMessages; | |
} else { | |
$customMessages .= 'No file links found'; | |
} | |
return TRUE; | |
} | |
/** | |
* Processes each record and updates the database | |
* | |
* @param array $record | |
* @return void | |
*/ | |
protected function migrateRecord(array $record) { | |
$this->currentRecord = $record; | |
$convertedBodyText = $this->convertFileLink($record['bodytext']); | |
$GLOBALS['TYPO3_DB']->exec_UPDATEquery( | |
'tt_content', | |
'uid = ' . $record['uid'], | |
array('bodytext' => $convertedBodyText) | |
); | |
} | |
/** | |
* The actual transformation of the links | |
* pretty similar to TS_links_rte in RteHtmlParser | |
* | |
* @param $value | |
* @return string | |
*/ | |
protected function convertFileLink($value) { | |
$blockSplit = $this->rteHtmlParser->splitIntoBlock('link', $value, 1); | |
foreach ($blockSplit as $k => $v) { | |
// Block | |
if ($k % 2) { | |
$tagCode = \TYPO3\CMS\Core\Utility\GeneralUtility::unQuoteFilenames(trim(substr($this->rteHtmlParser->getFirstTag($v), 0, -1)), TRUE); | |
$link_param = $tagCode[1]; | |
if(intval(strpos($link_param, '/')) && strpos($link_param, 'http') === FALSE){ | |
$fileObject = NULL; | |
if(@file_exists(PATH_site . '/' . $link_param)) { | |
try { | |
if(strpos($link_param, $this->fileAdminDir) !== FALSE) { | |
$fileObject = $this->storage->getFile('/' . str_replace($this->fileAdminDir,'',$link_param)); | |
} | |
} catch (\TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException $notFoundException) { | |
$this->fileNotFoundErrors[] = $link_param . ' not indexed (referenced in content element ' . $this->currentRecord['uid'] . ' on page ' . $this->currentRecord['pid'] . ')'; | |
} | |
if ($fileObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) { | |
// It's a file | |
$fileLink = 'file:' . $fileObject->getUid(); | |
$tagCode[1] = $fileLink; | |
$bTag = implode(' ', $tagCode) . '>'; | |
$eTag = '</link>'; | |
$blockSplit[$k] = $bTag . $this->convertFileLink($this->rteHtmlParser->removeFirstAndLastTag($blockSplit[$k])) . $eTag; | |
$this->convertedLinkCounter++; | |
} | |
} else { | |
// Nothing to be done if file not found | |
$this->fileNotFoundErrors[] = $link_param . ' not found (referenced in content element ' . $this->currentRecord['uid'] . ' on page ' . $this->currentRecord['pid'] . ')'; | |
} | |
} | |
} | |
} | |
$convertedText = implode('', $blockSplit); | |
return $convertedText; | |
} | |
/** | |
* Retrieve every record which needs to be processe | |
* | |
* @return array | |
*/ | |
protected function getRecordsFromTable() { | |
$records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,pid,bodytext', 'tt_content', $this->addWhere); | |
return $records; | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment