TYPO3 Extbase: How to get disabled related Object, without raw sql-query?
Asked Answered
L

2

5

Scenario:

I have following model: Domain-Model

ContactPerson has a relation to FrontendUser and is the owning side of the relation. Now I have following problem:
I am activating/deactivating the FrontendUsers in a task, based on the ContactPersons which are active. When the FrontendUser is disabled or deleted the result of contactPerson->getFrontendUser() is null, even if both repositories ignoreEnableFields:

    /** @var Typo3QuerySettings $querySettings */
    $querySettings = $this->objectManager->get(Typo3QuerySettings::class);
    $querySettings->setIgnoreEnableFields(true);
    $querySettings->setRespectStoragePage(false);
    $this->frontendUserRepository->setDefaultQuerySettings($querySettings);

    $debugContactPerson = $this->contactPersonRepository->findOneByContactPersonIdAndIncludeDeletedAndHidden('634');
    $debugFrontendUser = $this->frontendUserRepository->findOneByUid(7);
    \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
        array(
            '$debugContactPerson' => $debugContactPerson,
            '$debugFrontendUser' => $debugFrontendUser,
        )
    );

Result: DebugResult

P.s.: $this->frontendUserRepository->findByUid(7); also doesn't work because it isn't using the query, but persistenceManager->getObjectByIdentifier(... which is of course ignoring the query-settings.

The problem is, in my real code I can't use findOneByUid(), because I can't get the integer-Value(uid) in the frontend_user field of the contact_person.

Any way to solve this without using a raw query to get the contact_person-row?


My (yes raw query) Solution:

Because I didn't want to write an own QueryFactory and I didn't want to add a redundant field to my contactPerson I solved it now with a raw statement. Maybe it can help someone with the same problem:

class FrontendUserRepository extends \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
{
    /**
     * @param \Vendor\ExtKey\Domain\Model\ContactPerson $contactPerson
     * @return Object
     */
    public function findByContactPersonByRawQuery(ContactPerson $contactPerson){
        $query = $this->createQuery();

        $query->statement(
            "SELECT fe_users.* FROM fe_users" .
            " LEFT JOIN tx_extkey_domain_model_contactperson contact_person ON contact_person.frontend_user = fe_users.uid" .
            " WHERE contact_person.uid = " . $contactPerson->getUid()
        );
        return $query->execute()->getFirst();
    }

}
Lymphoma answered 12/10, 2016 at 8:13 Comment(1)
I posted a bug report for TYPO3: forge.typo3.org/issues/84955Kharkov
B
8

Invoking repository directly

There are two aspects for the enable fields of table fe_users:

  • $querySettings->setIgnoreEnableFields(true);
  • $querySettings->setEnableFieldsToBeIgnored(['disable']);

Have a look to some overview in the wiki page - it says 6.2, but it's still valid in most parts for 7.6 and 8 as well. However, this only works if the repository is invoked directly, but not if an entity is retrieved as part of another entity - in this case the repository is not used for nested entities.

Modify query settings for nested entities

Nested entities are retrieved implicitly - this happens in DataMapper::getPreparedQuery(DomainObjectInterface $parentObject, $propertyName). To adjust query settings for child entities, the QueryFactoryInterface implementation has to be overloaded.

Register an alternative implementation in ext_localconf.php (replace \Vendor\ExtensionName\Persistence\Generic\QueryFactory with the real class name of your extension):

$extbaseObjectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
    \TYPO3\CMS\Extbase\Object\Container\Container::class
);
$extbaseObjectContainer->registerImplementation(
    \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface::class,
    \Vendor\ExtensionName\Persistence\Generic\QueryFactory::class
);

With new Typo3 versions (v8+), the registerImplementation method no longer works for QueryFactory. Instead, a XCLASS must be used to overwrite/extend the class:

$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory::class] = [
    'className' => \Vendor\ExtensionName\Persistence\Generic\QueryFactory::class,
];

Then inside the implementation:

<?php
namespace \Vendor\ExtensionName\Persistence\Generic;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser;

class QueryFactory extends \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory {
    public function create($className) {
        $query = parent::create($className);
        if (is_a($className, FrontendUser::class, true)) {
            // @todo Find a way to configure that more generic
            $querySettings = $query->getQuerySettings();
            $querySettings->setIgnoreEnableFields(true);
            // ... whatever you need to adjust in addition ...
        }
        return $query;
    }
}

Bucaramanga answered 12/10, 2016 at 9:18 Comment(4)
$querySettings->setIgnoreEnableFields(true);Lymphoma
// if nothing else is given, all enableFields are ignored $querySettings->setIgnoreEnableFields(true); // define single fields to be ignored $querySettings->setEnableFieldsToBeIgnored(['disable']); The first one should disable all enable fields. But it only has effect on queries of the repository, not on the relation of some other model.Lymphoma
Exactly, this only works if the repository is invoked directly, but not if an entity is retrieved as part of another entity - in this case the repository is not used for nested entities. I'll update the answer above to given an example on how to do that individually.Bucaramanga
@OliverHader Any experience with 8.7.x? I cannot get fe_users that are disabled. Worked with 7.6.xMinna
R
0

My solution of this problem was to disable the "enablecolumns" in TCA definitions and deal this in the repository myself. Here an example of findAll method:

public function findAll($ignoreEnableFields = false) {
    $query = $this->createQuery();
    if (!$ignoreEnableFields) {
        $currTime = time();
        $query->matching(
            $query->logicalAnd(
                $query->equals("hidden", 0),
                $query->logicalOr(
                    $query->equals("starttime", 0),
                    $query->lessThanOrEqual("starttime", $currTime)
                ),
                $query->logicalOr(
                    $query->equals("endtime", 0),
                    $query->greaterThanOrEqual("endtime", $currTime)
                )
            )
        );
    }
    return $query->execute();
}
Regimentals answered 8/8, 2017 at 11:10 Comment(1)
Disabling the section $TCA['fe_users']['ctrl']['enablecolumns'] has a global effect on all handlers of frontend users, not only related to Extbase applications. Thus, this would probably modify the login behavior as well - disabled or expired user accounts still could be used to log into the according application.Bucaramanga

© 2022 - 2024 — McMap. All rights reserved.