Fileupload TYPO3 getting null on findAll() - typo3

Hi have a backend module extension to upload files. Im using helhum fileupload for reference. File upload is successful. But the file filed of table updates the uid of sys_file_reference instead of no of files. Why it happens?
<f:form.upload property="file" />
my reference is this Where can I set the table name and no_files in my table and sys_file reference

The property "file" I assume is an 1:1 relation which is why the UID of the file reference is what gets written in to the field.
Had the property been a M:N or 1:N table you would see the number of files, as you expect - and Extbase would need to know you want an ObjectStorage containing FileReference objects on your property.
Regarding the subject, if your Repository returns NULL when you do findAll, this is almost always because of storage page restrictions. To overcome it, override either createQuery and manipulate QuerySettings on the query before it gets returned, setting respectStoragePageUids(false).

I got the solution for my problem. my model was
/**
* Sets the file
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $file
* #return void
*/
public function setFile(\TYPO3\CMS\Extbase\Domain\Model\FileReference $file = NULL)
{
$this->file = $file;
}
I removed the type from argument list .Now its working fine.My updated code is below
/**
* Sets the file
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $file
* #return void
*/
public function setFile($file = NULL)
{
$this->file = $file;
}

Related

Is there a way to create domain-object-translations over extbase in TYPO3 9?

I'm importing some products with JSON into my TYPO3 extension.
I'm having problems with translation creating over my ImportService, as I upgraded from TYPO3 8 to TYPO3 9. It seems, that the l10n_parent in the database cannot be set, although _localizedUid and _versionedUid are being set.
/**
* #param DomainObjectInterface $object
* #param $targetLanguageUid
* #return DomainObjectInterface|null
*/
public function translate($object, $targetLanguageUid)
{
/** #var AbstractDomainObject $objectCopy */
$objectCopy = new $this->objectType;
$properties = ObjectAccess::getGettableProperties($object);
foreach ($properties as $propertyName => $propertyValue) {
ObjectAccess::setProperty($objectCopy, $propertyName, $propertyValue);
}
$objectCopy->_setProperty('_localizedUid', $object->getUid());
$objectCopy->_setProperty('_languageUid', $targetLanguageUid);
$objectCopy->_setProperty('_versionedUid', $object->getUid());
return $objectCopy;
}
Expected Result: l10n_parent in database is e.g. 403 (uid of original object)
Actual Result: l10n_parent in database is 0
When dealing with TYPO3 internal data structures, the recommendation is to use the DataHandler for this. In your case, you just need to provide the config array and set the localize field correctly. You can use this in your own scripts with a backend scope, examples are provided in the documentation. In your import script, you would have to create the records in the default language first, then create each translation for it.

Typo3 accessing an existing table to consume data of it

I tried to integrate an existing table to my extension. The problem is that the content of the table isn't taken over. I created a new model with the name of the existing table and named the properties according to the existing column names. I also implemented the corresponding getters and setters of the properties.
The name of the existing table is tx_institutsseminarverwaltung_domain_model_event.
What is my failure in this case? Just want to access the data of an existing table from another extension.
Thanks in advance.
UPDATE:
I tried this:
/**
* Protected Variable objectManager wird mit NULL initialisiert.
*
* #var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
* #inject
*/
protected $objectManager = NULL;
and listAction():
/**
* action list
*
* #return void
*/
public function listAction() {
echo "test";
$theRepository = $this->objectManager->get('\TYPO3\institutsseminarverwaltung\Domain\Repository\EventRepository');
$yourRecords = $theRepository->findAll();
$this->view->assign('events', $yourRecords);
}
But no results returned.
You should use the repository linked to this table. Something like this :
$theRepository = $this->objectManager->get(\Your\VendorName\Domain\Repository\TheRepository::class);
$yourRecords = $theRepository->findAll();
How are you trying to "consume" or access the data from the other table in your extension?
Do you have a repository for the existing table (maybe there is already an existing repository, that you can reuse)?
See german typo3 board mapping existing tables and SO thread TYPO3 / How to make repository from existing table fe_users?
solution is:
$querySettings = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$theRepository = $this->objectManager->get('TYPO3\\institutsseminarverwaltung\\Domain\\Repository\\EventRepository');
$theRepository->setDefaultQuerySettings($querySettings);
$yourRecords = $theRepository->findAll();
$this->view->assign('events', $yourRecords);

TYPO3 8 with extbase: remove FileReference

This seems simple enough but I seem to be too stupid to do it. I have added a field to fe_users called "cv" for uploading a pdf file. In my FrontendUser Model it looks like this:
/**
* #var \TYPO3\CMS\Extbase\Domain\Model\FileReference
* #cascade remove
*/
protected $cv;
Uploading a file works like a charm, I used the script from https://github.com/helhum/upload_example in parts.
The only problem is deleting such a file, or rather, removing the connection between sys_file and the user. After submitting a form and checking a checkbox, I tried to do this:
$user->setCv(null);
$user->setEdited(new \DateTime());
$this->frontendUserRepository->update($user);
$persistenceManager->persistAll();
After a page reload if I take a look at the backend, the cv File is still attached to the user (but "edited" was correctly set to the current datetime). I do not understand this, how can I set the FileReference Value to null?
Make sure to check your Model. FileReferences are stored in an M:N relation. So you must use the folling declaration in your Model:
/**
* cv
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
* #cascade remove
*/
protected $cv = null;
with an initialization in the __constructor:
public function __construct()
{
$this->cv = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
Now you have your FileReference in an ObjectStorage. To clear all FileReferences you can set cv to new \TYPO3\CMS\Extbase\Persistence\ObjectStorage():
$user->removeCv(new \TYPO3\CMS\Extbase\Persistence\ObjectStorage());
$user->setEdited(new \DateTime());
$this->frontendUserRepository->update($user);
$persistenceManager->persistAll();

Delete file when deleting sys_file_reference

I am writing an extension which allows to upload files in the frontend and backend of a TYPO3 instance. The upload works in both views but if the admin wants to delete an upload in the backend in list view, the "physical" file, which is located on the harddisk of the webserver, will not be deleted, only the sys_file_reference record.
Is there a possibility to tell the tca that in case of a deletion of the upload record the associated file should also be deleted? I've also tried to implement a slot with the following code but nothing happens:
ext_localconf.php:
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher')->connect(
'TYPO3\CMS\Extbase\Persistence\Generic\Backend',
'afterRemoveObject',
'Kmi\feupload\Slots\MyAfterRemoveObjectSlot',
'myAfterRemoveObjectMethod'
);
Classes/Slots/MyAfterRemoveObjectSlot.php:
namespace Kmi\feupload\Slots;
class MyAfterRemoveObjectSlot {
public function myAfterRemoveObjectMethod($object) {
// do something
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($object);
}
}
Has anyone an idea how to solve this? There will be many uploads and if the admin deletes one, the associated file should also be deleted...
Thank you in advance for your help :)
Unfortunately I don't have time to create a complete, tested answer ATM but I'm putting together the steps needed and hope that you can work a solution and complete my answer then.
Every manipulation done through a TCEFORM is saved with the DataHandler (formerly called TCEmain). The DataHandler has numerous hooks. I assume that your model "Upload" has a property file which is of type (or extends) \TYPO3\CMS\Extbase\Domain\Model\FileReference.
File references in TCEFORM are added as IRRE elements. So when you remove the file reference and save the Upload object, the following data is (amogst others) sent to DataHandler:
cmd[sys_file_reference][15011][delete]=1
This means that the file reference with uid 15011 must be deleted. I suggest to implement the processCmdmap_deleteAction hook for this.
So you must also check the datamap to find out if the command was executed through a manipulation of an "Upload" record.
ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass']['your_extension'] = 'My\\Extension\\Hook\\DataHandler';
EXT:your_extension/Classes/Hook/DataHandler.php
This code is untested!
<?php
namespace My\Extension\Hook
class DataHandler {
/**
* #param string $table
* #param int $id
* #param array $recordToDelete
* #param $parentObject \TYPO3\CMS\Core\DataHandling\DataHandler
*/
public function processCmdmap_deleteAction($table, $id, $recordToDelete, $parentObject) {
if (array_key_exists('tx_myext_domain_model_upload', $parentObject->datamap)) {
// Parent record of record to delete is of type "tx_myext_domain_model_upload"
if ($table === 'sys_file_reference' && is_integer($id)) {
// A file reference was requested to delete
// Get an instance of the ResourceFactory
/** #var $resourceFactory \TYPO3\CMS\Core\Resource\ResourceFactory */
$resourceFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
// We get the FileReference object for the given id
$fileReferenceObject = $resourceFactory->getFileReferenceObject($id);
// Delete the original file of the file reference
$fileWasDeleted = $fileReferenceObject->getOriginalFile()->delete();
// #TODO throw a warning if $fileWasDeleted is false
}
}
}
}
I commented the code so you know which checks are necessary for what.
Don't forget to clear the system cache after defining the hook in ext_localconf.php.
// delete video or image from sys_file table and sys_file_reference
// table (here videourl - sys_file_reference fieldname)
$fileRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\FileRepository::class);
$fileObjects = $fileRepository->findByRelation('tablename', 'videourl', $id);
foreach ($fileObjects as $fileKey => $fileValue) {
$delete= $fileValue->getOriginalFile()->delete();
}

SphinxQL & Phalcon\Mvc\Model

I have a Sphinx search engine running on MySQL protocol and I use Phalcon\Db\Adapter\Pdo\Mysql to connect to it. Sphinx tables are implemented as models.
When I try to select (using SpinxQL) I, obviously, get an error when database adapter attempts to extract table metadata running queries against tables which are not supported and not present respectively in SpinxQL. There is a workaround in the documentation showing how to manually assign metadata... But being to lazy by nature I want to try to automate metadata generation.
I assume that metadata is produced by the database adapter, probably as a result of calling getColumnsList() on the instance following getColumnDefinition() or something else (???). Is this my assumption correct? I want is to extend Phalcon\Db\Adapter\Pdo\Mysql and override those methods to be compatible with Sphinx.
Thanks in advance for your suggestions!
Ok, you need to override at least two methods to make this work, the following class would work:
<?php
class SphinxQlAdapter extends Phalcon\Db\Adapter\Pdo\Mysql implements Phalcon\Db\AdapterInterface
{
/**
* This method checks if a table exists
*
* #param string $table
* #param string $schema
* #return boolean
*/
public function tableExists($table, $schema=null)
{
}
/**
* This method describe the table's columns returning an array of
* Phalcon\Db\Column
*
* #param string $table
* #param string $schema
* #return Phalcon\Db\ColumnInterface[]
*/
public function describeColumns($table, $schema=null)
{
}
}
Then in your connection, you use the new adapter:
$di->set('db', function(){
return new SphinxQlAdapter(
//...
);
});