TYPO3 ConnectionPool find a file after the uid of

2019-08-18 16:54发布

问题:

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'. 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. 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'.

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.

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. I only have it this way in order to get the results on the backend.

Thanks in advance,

回答1:

You might want to make use of the FileRepository class here.

$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.

You will get back an array of file objects to deal with.



回答2:

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. In order to get the $uid from the processDatamap_afterDatabaseOperations you need to add this code before you get the instance of the fileRepository.

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

Now as far as the text concerns, i extracted from a 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. 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.

$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.

EXTRA CONTENT

If you want to include the PDFParser as well and you are on composer mode, then add this on your composer.json:

"smalot/pdfparser" : "*"

and on the autoload:

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

Then under: yourExtension/Classes/Hooks/DataHandler.php add the namespace:

use Smalot\PdfParser\Parser;

Now you are able to use the getPages() and getText() functions.

The Documentation

If i missed something let me know and i will add it.