Get Disabled/Hidden Relation Table Records using TYPO3 Repository Query - typo3

I've a requirement in my custom extension where there are records, lets say which are projects saved in table name: tx_myextension_domain_model_projects and which are categorized using custom category table tx_myextension_domain_model_categories the relation which is mapped in model is m:n and saved in mm table tx_myextension_category_record_mm.
This is the TCA mapping for the category field:
products_category' => [
'exclude' => true,
'label' => 'Category Label',
'config' => [
'type' => 'select',
'renderType' => 'selectTree',
'foreign_table' => 'tx_myextension_domain_model_categories',
'foreign_table_where' => 'ORDER BY tx_myextension_domain_model_categories.sorting',
'MM' => 'tx_myextension_category_record_mm',
'MM_match_fields' => [
'tablenames' => 'tx_myextension_domain_model_projects',
],
'MM_opposite_field' => 'items',
'size' => 20,
'treeConfig' => [
'parentField' => 'parent',
'appearance' => [
'showHeader' => true,
'expandAll' => true,
'maxLevels' => 99,
],
],
],
],
So in one of my use cases I need to get the projects which are categorized with disabled and active categories.
For example this is the categories :
categories = [
A => [
A1 => [
A1.2
]
A2 => [
A2.2
]
],
B => [
B1 => [
B1.2
]
],
];
Lets say A1 is disabled/hidden record and I want to get the projects which are assigned to A1 and its child A1.2. Is there any possibilities to get the project records using TYPO3 Repository query.
Note: I couldn't disable the enable fields using $querySettings->setIgnoreEnableFields(true); because I don't want to disable it for the entire repository of category and also I need to disable it from the Project repository while query the project records. I hope my question is clear. Please let me know the solution for this.
Solution Currently I choosed: I used TYPO3 Connection Pool Query instead of repository query.

Why isnt $query->getQuerySettings()->setIgnoreEnableFields(true); an option for you? You can build the query exactly the way you need it like you would do with the Connection Pool.

Related

Extbase proper relation discovery

I've come accross a weird issue with extbasewhile working on some semi-complicated logic for filtering of courses for a LMS tools that we work on.
The logic is as follows:
There are course templates and seminars
A course template always has a start and end date, it contains courses that depend on one another
A seminar contains multiple courses that do not depend on one another
As long as a course template starts after the selected date, it has to be displayed
As long as a seminar contains a course that starts after the selected date, it has to be displayed
There are other filters that do not matter here and that do not play into this issue
In order to solve this request, I resorted to the power of extbase being able to simply create a subquery by using something like $query->greaterThanOrEqual('template_children.start_date', $date) (see below for concrete example). This now generates the below result:
Resulting SQL:
SELECT `tx_xxx_domain_model_courseprogrammetemplate`.*
FROM `tx_xxx_domain_model_courseprogrammetemplate`
`tx_xxx_domain_model_courseprogrammetemplate`
LEFT JOIN `tx_xxx_domain_model_courseprogrammetemplate`
`tx_xxx_domain_model_courseprogrammetemplate0`
ON Find_in_set(
`tx_xxx_domain_model_courseprogrammetemplate0`.`uid`,
`tx_xxx_domain_model_courseprogrammetemplate`.`template_children`)
The relations are built by an important and there are no values written to the field template_children on this side of the relation, thus no result is found.
AFAIK, this should work without having to populate this field with anything else than maybe an amount of children (and I'm not sure if this is even necessary anymore).
Here's my TCA configuration and the PHP code handling the logic.
TCA:
'template_children' => [
'exclude' => true,
'label' => 'LLL:EXT:xxx/Resources/Private/Language/locallang_db.xlf:tx_xxx_domain_model_courseprogrammetemplate.template_children',
'config' => [
'items' => [
['', 0]
],
'type' => 'select',
'renderType' => 'selectSingleBox',
'foreign_table' => 'tx_xxx_domain_model_courseprogrammetemplate',
'foreign_table_where' => 'AND tx_xxx_domain_model_courseprogrammetemplate.template = ###REC_FIELD_uid### AND tx_xxx_domain_model_courseprogrammetemplate.sys_language_uid = 0',
'readOnly' => 1,
'size' => 5,
'maxitems' => 100,
'autoSizeMax' => 20,
],
],
Extbase:
$constraints[] =
$query->logicalAnd(
[
$query->logicalOr(
[
// If the learning form is a course, the start and end date should be in between the period
$query->logicalAnd(
[
$query->greaterThanOrEqual('start_date', $demand->getStartDate()->format('Y-m-d H:i:s')),
$query->logicalNot($query->equals('learning_form', 'Seminar'))
]
),
// If the learning form is seminar, we only want to display it, if there is at least one course that starts in this period
$query->logicalAnd(
[
$query->logicalOr(
[
$query->greaterThanOrEqual('templateChildren.start_date', $demand->getStartDate()->format('Y-m-d H:i:s')),
]
),
$query->equals('learning_form', 'Seminar')
]
)
]
)
]
);
I tried switching the TCA field type to inline but this didn't change the behaviour.
Another way to do this would be to get all objects that relate to each seminar that match the filter, but that would mean creating some thousands of separate queries while filter :-/
Thanks for your support.
PS: I found this article, but it does not describe, how to configure the TCA accordingly, so that it works:
TYPO3 Extbase: Filtering a 1:N relation
Also sadly the documentation doesn't say much about what to configure how in TCA for this to work:
https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/6-Persistence/3-implement-individual-database-queries.html
I ended up finding the solution to my problem: you have to use inline as a type so that extbase has a chance to know how to resolve the relation:
'template_children' => [
'exclude' => true,
'label' => 'LLL:EXT:xxx/Resources/Private/Language/locallang_db.xlf:tx_xxx_domain_model_courseprogrammetemplate.template_children',
'config' => [
'items' => [
['', 0]
],
'type' => 'inline',
'foreign_table' => 'tx_xxx_domain_model_courseprogrammetemplate',
'foreign_field' => 'template',
'appearance' => [
'collapseAll' => 1,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showAllLocalizationLink' => 1
],
'overrideChildTca' => [
'ctrl' => [
'types' => [
'1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title'],
],
],
],
],
],

Different value_options in Form Collection

I hava a Collection, in which a field User (a multiselect) depends on a previous Select, the Department. Therefore each User select contain a different "value_options".
How can I set different "value_options" when retrieving the form for each row of the Collection?
You have different options:
You create an API endpoint to retrieve form options
You make this into two different pages, the first one you choose the department and the second one you choose the user (ew)
You populate the form in server-side and you filter the selects on client side
I personally discourage the second option. Is there just to say that it is a possible solution, but NO.
The first option, the API, is interesting, but requires actually more work, especially if it is the only endpoint in your application.
The third option is the one I always use, since it requires the less code and it quite simple to implement.
In your form, you have your two elements:
$this->add([
'name' => 'department_id',
'type' => 'Select',
'attributes' => [
'id' => 'department_id'
],
'options' => [
'value_options' => [
1 => 'Marketing',
2 => 'IT',
3 => 'Logistic'
]
]
]);
$this->add([
'name' => 'user_id',
'type' => 'Select',
'attributes' => [
'id' => 'user_id',
'multiple' => true
],
'options' => [
'value_options' => [
[
'value' => 1,
'label' => 'John Doe - Marketing',
'attributes' => ['data-department-id' => 1]
],
[
'value' => 2,
'label' => 'Jane Doe - Marketing',
'attributes' => ['data-department-id' => 1]
],
[
'value' => 3,
'label' => 'Jack Doe - IT',
'attributes' => ['data-department-id' => 2]
],
[
'value' => 4,
'label' => 'Dana Doe - IT',
'attributes' => ['data-department-id' => 2]
],
[
'value' => 5,
'label' => 'Frank Doe - Logistic',
'attributes' => ['data-department-id' => 3]
],
[
'value' => 6,
'label' => 'Lara Doe - Logistic',
'attributes' => ['data-department-id' => 3]
]
]
]
]);
As you can see, all the users are put in the value_options. Keep in mind that this is just an example, you should use custom elements to populate this kind of selects ;)
Then, in your view, you render the elements:
<?= $this->formElement($this->form->get('department_id')); ?>
<?= $this->formElement($this->form->get('user_id')); ?>
And you finally add the JS code to handle the filter. Here I use jQuery, but it's not necessary to use it:
$(function () {
// Filter users when you load the page
filterUsers(false);
// Filter users when you change value on multiselect
$('#department_id').on('change', function () {
filterUsers(true);
});
});
function filterUsers(resetValue) {
var departmentId = $('#department_id').val();
// Remove previous value only when filter is changed
if (resetValue) {
$('#user_id').val(null);
}
// Disable all options
$('#user_id option').attr('disabled', 'disabled').attr('hidden', true);
// Enable only those that respect the criteria
$('#user_id option[data-department-id=' + departmentId + ']').attr('disabled', false).attr('hidden', false);
}
Final tip: don't forget to create and add to the form a Validator to check the couple department_id - user_id is correct, just to avoid (on my example) to accept Lara Doe (logistic) with IT department ;)

How to add custom wizards in TYPO3 9 TCA?

Related to How to add custom wizards in typo3 7 TCA? how can costum wizards in TYPO3 9 be implemented? I've added my entry to the Routes.php
return [
'tx_csseo_preview' => [
'path' => '/wizard/tx_csseo/preview',
'target' => \Clickstorm\CsSeo\UserFunc\PreviewWizard::class . '::render'
],
'tx_csseo_permalink' => [
'path' => '/wizard/tx_csseo/permalink',
'target' => \Clickstorm\CsSeo\UserFunc\PermalinkWizard::class . '::render'
]
];
How can I add them now to my TCA field?
'tx_csseo_title' => [
'label' => 'LLL:EXT:cs_seo/Resources/Private/Language/locallang_db.xlf:pages.tx_csseo_title',
'exclude' => 1,
'config' => [
'type' => 'input',
'max' => $extConf['maxTitle'],
'eval' => 'trim',
'fieldWizard' => [
'tx_csseo_preview' => [
'disabled' => false,
]
]
]
],
This does not work. What do I miss? Thanks in advance.
Related to your kind of wizard the registration-process is different and extensive explained here. You can leave the entries in Routes.php away (perhaps even the whole file if nothing else is inside).
Registration is done in ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1485351217] = [
'nodeName' => 'importDataControl',
'priority' => 30,
'class' => \T3G\Something\FormEngine\FieldControl\ImportDataControl::class
];
Then reference the new wizard in TCA:
'somefield' => [
'label' => $langFile . ':pages.somefield',
'config' => [
'type' => 'input',
'eval' => 'int, unique',
'fieldControl' => [
'importControl' => [
'renderType' => 'importDataControl'
]
]
]
],
Then finally the class with the "magic"
declare(strict_types=1);
namespace T3G\Something\FormEngine\FieldControl;
use TYPO3\CMS\Backend\Form\AbstractNode;
class ImportDataControl extends AbstractNode
{
public function render()
{
$result = [
'iconIdentifier' => 'import-data',
'title' => $GLOBALS['LANG']->sL('LLL:EXT:something/Resources/Private/Language/locallang_db.xlf:pages.importData'),
'linkAttributes' => [
'class' => 'importData ',
'data-id' => $this->data['databaseRow']['somefield']
],
'requireJsModules' => ['TYPO3/CMS/Something/ImportData'],
];
return $result;
}
}
In the linked example there is still an Ajax Route with corresponding files, including a special defined route, but that's not required to get the basic wizard shown.
Concerning the registration in ext_localconf.php there is above the number 1485351217 as array-key shown. For an own registered node just calculate once the current time as unix-timestamp and enter that instead. So it's unique and can't be mistaken with other definitions of any registered nodes.
In contrast to the linked example I used slightly different descriptions, so I call the process in ext_localconf.php registering, and the inclusion in TCA referencing. Perhaps this small difference makes it a bit more clear.
Icons
Concerning Icons there is still a difference to earlier TYPO3 versions, they have to be registered now too and in TCA they are only referenced too by the registered name. Here in the TCA-file is no icon referenced but the class below makes usage of it. Here is an example how an icon has to be registered in ext_tables.php:
$systemIconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
$systemIconRegistry->registerIcon(
'imagemapwizard_link_edit',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
[
'source' => 'EXT:imagemap_wizard/Resources/Public/Icons/link_edit.png'
]
);
The new icon registry is implemented starting with TYPO3 version 7.5
Don't forget the configuration in YourExtension/Configuration/Backend/AjaxRoutes.php. See the documentation

Add Taxvat field to magento 2 checkout page

I'm from Brazil, and here we use the "taxvat" customer field to store a number called "CPF". I managed to make the field appear on checkout by adding it to an layoutProcessor, like this:
$shippingFields['taxvat'] = [
'component' => 'Magento_Ui/js/form/element/abstract',
'label' => __('CPF'),
'config' => [
'customScope' => 'shippingAddress',
'template' => 'ui/form/field',
'elementTmpl' => 'ui/form/element/input',
],
'placeholder' => 'CPF *',
'validation' => [
'required-entry' => 1
],
'provider' => 'checkoutProvider',
'source' => 'customer.taxvat',
'dataScope' => 'customer.taxvat',
'sortOrder' => 1,
];
But, i don't know why, this field it's not saving on database. It only works if i save this field on customer form, not on checkout form.
Anyone know what i'm missing?
thanks!

TYPO3 foreign_table_where not works properly

I have TYPO3 version 7.6.18.
'images' => [
'label' => 'LLL:EXT:fefiles/Resources/Private/Language/locallang_db.xlf:images',
'config' => [
'type' => 'inline',
'foreign_table' => 'tx_fefiles_domain_model_photo',
'foreign_field' => 'album',
'foreign_table_where' => 'AND tx_fefiles_domain_model_photo.allow = 1',
'maxitems' => '5000'
],
],
This is configuration in TCA for someone field.
in table tx_fefiles_domain_model_photo I have 4 rows which id = album,
but allow = 1 only two. But I get all four rows. My condition tx_fefiles_domain_model_photo.allow = 1 does't works. I tried different variants, cleared cache. Really I need your help, I must make it works, help me please (
Try:
'foreign_match_fields' => [
'allow' => 1
]
instead of foreign_table_where.
For examples look into documentation: https://docs.typo3.org/typo3cms/TCAReference/