简体   繁体   English

TYPO3 ConnectionPool在文件引用的uid之后查找文件并更新数据

[英]TYPO3 ConnectionPool find a file after the uid of the file reference and update data

The concept is that, after a successfull save of my object, it should update a text in the database (With a Hook). 这个概念是,在成功保存对象之后,它应该更新数据库中的文本(带有挂钩)。 Lets call the field ' succText '. 让我们将字段称为“ succText ”。 The table i would like to access is the sys_file but i only get the sys_file_reference id when i save the object. 我要访问的表是sys_file,但是当我保存对象时,我仅获得sys_file_reference ID。 So i thought i could use the ConnectionPool to select the sys_file row of this file reference and then insert the data on the field ' succText '. 因此,我认为我可以使用ConnectionPool选择该文件引用的sys_file ,然后将数据插入“ succText ”字段中。

I tried this: 我尝试了这个:

public function processDatamap_preProcessFieldArray(array &$fieldArray, $table, $id, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj) {
    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
    $findItemsId = $queryBuilder
       ->select('*')
       ->from('sys_file_reference')
       ->join(
          'sys_file_reference',
          'sys_file',
          'reference',
          $queryBuilder->expr()->eq('reference.uid', $queryBuilder->quoteIdentifier('uid_local'))
       )
       ->where(
            $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter($fieldArray['downloads'], \PDO::PARAM_INT))
       )
      ->execute();
}

But this give me back the sys_file_reference id and not the id and the field values of the sys_file table. 但这给了我sys_file_reference id,而不是sys_file表的id和字段值。

As for the update, i havent tried it yet, cause i haven't figured out yet, how to get the row that needs to be updated. 至于更新,我还没有尝试过,因为我还没有弄清楚如何获取需要更新的行。 I gues with a subquery after the row is found, i don't really know. 找到行后,我猜测一个子查询,我真的不知道。

The processDatamap_preProcessFieldArray is going to be renamed to post. processDatamap_preProcessFieldArray将重命名为post。 I only have it this way in order to get the results on the backend. 我只有通过这种方式才能在后端获得结果。

Thanks in advance, 提前致谢,

You might want to make use of the FileRepository class here. 您可能要在这里使用FileRepository类。

$fileRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\FileRepository::class);
$fileObjects = $fileRepository->findByRelation('tablename', 'fieldname', $uid);

Where $uid is the ID of the record that the files are connected to via file reference. 其中$ uid是文件通过文件引用连接到的记录的ID。

You will get back an array of file objects to deal with. 您将取回要处理的文件对象数组。

I resolved my problem by removing the first code and adding a filerepository instance. 我通过删除第一个代码并添加了文件存储库实例来解决了我的问题。

 $fileRepository = GeneralUtility::makeInstance(FileRepository::class);
 $fileObjects = $fileRepository->findByRelation('targetTable', 'targetField', $uid);

VERY IMPORTANT! 很重要!

If you are creating a new element then TYPO3 assigns a temp UID variable with a name that looks like this NEW45643476 . 如果要创建新元素,则TYPO3会分配一个临时UID变量,其名称类似于此NEW45643476 In order to get the $uid from the processDatamap_afterDatabaseOperations you need to add this code before you get the instance of the fileRepository. 为了从processDatamap_afterDatabaseOperations获取$ uid,您需要在获取fileRepository实例之前添加此代码。

if (GeneralUtility::isFirstPartOfStr($uid, 'NEW')) {
    $uid = $pObj->substNEWwithIDs[$uid];
 }

Now as far as the text concerns, i extracted from a pdf. 现在,就文本而言,我是从pdf中提取的。 First i had to get the basename of the file in order to find its storage location and its name. 首先,我必须获取文件的基本名称才能找到其存储位置和名称。 Since i have only one file i don't really need a foreach loop and i can use the [0] as well. 因为我只有一个文件,所以我真的不需要foreach循环,我也可以使用[0]。 So the code looked like this: 因此,代码如下所示:

$fileID = $fileObjects[0]->getOriginalFile()->getProperties()['uid'];
$fullPath[] = [PathUtility::basename($fileObjects[0]->getOriginalFile()->getStorage()->getConfiguration()['basePath']), PathUtility::basename($fileObjects[0]->getOriginalFile()->getIdentifier())];

This, gives me back an array looking like this: 这给了我一个看起来像这样的数组:

array(1 item)
   0 => array(2 items)
      0 => 'fileadmin' (9 chars)
      1 => 'MyPdf.pdf' (9 chars)

Now i need to save the text from every page in a variable. 现在,我需要将每个页面中的文本保存在变量中。 So the code looks like this: 因此,代码如下所示:

$getPdfText = '';
foreach ($fullPath as $file) {
    $parser = new Parser();
    $pdf    = $parser->parseFile(PATH_site . $file[0] . '/' . $file[1]);
    $pages  = $pdf->getPages();
    foreach ($pages as $page) {
         $getPdfText .= $page->getText();
     }
  }

Now that i have my text i want to add it on the database so i will be able to use it on my search action. 现在我有了我的文本,我想将其添加到数据库中,这样我就可以在搜索操作中使用它了。 I now use the connection pool to get the file from the sys_file. 现在,我使用连接池从sys_file获取文件。

$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file');
$queryBuilder
      ->update('sys_file')
      ->where(
          $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($fileID))
        )
        ->set('pdf_text', $getPdfText)
        ->execute();

Now everytime i choose a PDF from my extension, i save its text on the database. 现在,每次我从扩展名中选择PDF时,我都会将其文本保存在数据库中。

EXTRA CONTENT 额外内容

If you want to include the PDFParser as well and you are on composer mode, then add this on your composer.json: 如果您也想包括PDFParser并且处于作曲者模式,则将其添加到composer.json中:

"smalot/pdfparser" : "*"

and on the autoload: 并在自动加载上:

"Smalot\\PdfParser\\" : "Packages/smalot/pdfparser/src/"

Then under: yourExtension/Classes/Hooks/DataHandler.php add the namespace: 然后在: yourExtension / Classes / Hooks / DataHandler.php下添加名称空间:

use Smalot\PdfParser\Parser;

Now you are able to use the getPages() and getText() functions. 现在,您可以使用getPages()getText()函数了。

The Documentation 文档资料

If i missed something let me know and i will add it. 如果我错过了任何事情,请告诉我,我将其添加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM