Add marker to tt_news which saves the link to another page - typo3

I want that the user can specify a link to a page. Therefore an group is used. The example is based on the field "related". Since the rest is structured for more than entry, also the user should be able to set more than one link. A reverse query is not needed.
This is how I do it:
Here I load the input field "link":
$TCA['tt_news'] = Array (
'ctrl' => $TCA['tt_news']['ctrl'],
'interface' => Array (
'showRecordFieldList' => 'title,hidden,datetime,starttime,archivedate,category,author,author_email,short,image,imagecaption,links,related,news_files,link'
),
Here I define the field "link"
'link' => Array (
'label' => 'Link to another page',
'config' => Array (
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tt_news,pages',
'MM' => 'tt_news_link_mm',
'size' => '3',
'autoSizeMax' => 10,
'maxitems' => '200',
'minitems' => '0',
'show_thumbs' => '1',
'wizards' => array(
'suggest' => array(
'type' => 'suggest'
)
)
)
),
I used the field "related" as sample.
Here I define the position in the backend:
'types' => Array (
'0' => Array('showitem' =>
'hidden, type;;;;1-1-1,title;;;;2-2-2,short,bodytext;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.special, datetime;;;;2-2-2,archivedate,author;;3;; ;;;;2-2-2,
keywords;;;;2-2-2,sys_language_uid;;1;;3-3-3,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.media, image;;;;1-1-1,imagecaption;;5;;,links;;;;2-2-2,news_files;;;;4-4-4,link;;;;3-3-3,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.catAndRels, category;;;;3-3-3,related;;;;3-3-3,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.access, starttime,endtime,fe_group,editlock,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.extended,
'),
Now the field is shown as expected. I can choose a page and it appears in the selection list. In the field in the table tt_news the value only changes from 0 to 1. Also in the table tt_news_related_mm there is now an entry. I have reached this by using a separate table.
CREATE TABLE `tt_news_link_mm` (
`uid_local` int(11) NOT NULL default '0',
`uid_foreign` int(11) NOT NULL default '0',
`sorting` int(11) NOT NULL default '0',
`tablenames` varchar(255) NOT NULL default '',
KEY `uid_local` (`uid_local`),
KEY `uid_foreign` (`uid_foreign`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Only one thing is missing: How can I translate an page ID into a speaking URL?
Now I managed it with the help from cascaval:
$typolink_conf = array(
"title" => $title,
"ATagParams" =>'',
"no_cache" => 0,
"parameter" => $data['uid'],
"useCacheHash" => 1
);
$link = $this->cObj->typolink('linkname', $typolink_conf);

Related

Typo3 10.4.1 extend pages with an file ref

hope a knowing being reads this.
The task is simple but something went wrong.
Ive wrote an extension to extend the pages table for every page with some new props.
These values are:
1 boolean value (is extension active)
1 Text value (e.g css class name)
1 Filelink to sys_file for uploaded images
The fields itself are working as expected in backend.
fields in backend
But if i try to access them via fluid in frontend, there is only a lony 1 (Int) saved?
In Fluid:
{data.tx_mnadditionalpagefields_extended_background_image}
leads to this -> 1 (Integer)
What iam doing wrong?
my ext_tables.sql
CREATE TABLE pages (
tx_mnadditionalpagefields_custom_css_class varchar(255) DEFAULT '' NOT NULL,
tx_mnadditionalpagefields_activate_extended_rules TINYINT(1) UNSIGNED DEFAULT '0' NOT NULL,
tx_mnadditionalpagefields_extended_background_image int(11) unsigned NOT NULL default '0'
);
my ext.../Configuration/TCA/Overrides/pages.php
<?php
defined('TYPO3_MODE') or die();
// Configure new fields:
$fields = [
'tx_mnadditionalpagefields_custom_css_class' => [
'label' => 'LLL:EXT:nm_addtional_page_fields/Resources/Private/Language/locallang_db.xlf:pages.tx_mnadditionalpagefields_custom_css_class',
'exclude' => 1,
'config' => [
'type' => 'input',
'max' => 255
],
],
'tx_mnadditionalpagefields_activate_extended_rules' => [
'exclude' => 1,
'label' => 'LLL:EXT:nm_addtional_page_fields/Resources/Private/Language/locallang_db.xlf:pages.tx_mnadditionalpagefields_activate_extended_rules',
'config' => [
'type' => 'check',
'default' => 0
]
],
'tx_mnadditionalpagefields_extended_background_image' => [
'exclude' => 1,
'label' => 'LLL:EXT:nm_addtional_page_fields/Resources/Private/Language/locallang_db.xlf:pages.tx_mnadditionalpagefields_extended_background_image',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
'tx_mnadditionalpagefields_extended_background_image',
[
'maxitems' => 1,
'minitems' => 0,
'appearance' => [
'createNewRelationLinkTitle' => 'LLL:EXT:cms/locallang_ttc.xlf:images.addFileReference'
],
//'foreign_match_fields' => array(
// 'fieldname' => 'tx_mnadditionalpagefields_extended_background_image',
// 'tablenames' => 'pages',
// 'table_local' => 'sys_file',
//),
],
$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
),
]
];
// Add new fields to pages:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages', $fields);
// Make fields visible in the TCEforms:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'pages', // Table name
'--palette--;LLL:EXT:nm_addtional_page_fields/Resources/Private/Language/locallang_db.xlf:pages.palette_title;nm_addtional_page_fields', // Field list to add
'1', // List of specific types to add the field list to. (If empty, all type entries are affected)
'after:nav_title' // Insert fields before (default) or after one, or replace a field
);
// Add the new palette:
$GLOBALS['TCA']['pages']['palettes']['nm_addtional_page_fields'] = [
'showitem' => 'tx_mnadditionalpagefields_activate_extended_rules,tx_mnadditionalpagefields_custom_css_class,tx_mnadditionalpagefields_extended_background_image'
];
Extension download (WIP): download
For images/files, the local table stores only the count of references to files. (int)1 means, there's one reference.
Have a look at DataProcessing for how to use these filereferences with Fluid:
https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/7.4/Feature-67662-DataProcessorForFiles.html

In SuiteCRM how to add custom field in sub panel from relationship table?

I have a module and a sub panel with another module in relationship with it.
As shown in below image-
In the above image its a sub-panel of a module in the relationship,
I have added a column in the relationship table in database.
My requirement is to add that field in this sub-panel list view like shown in image in red rectangle, which is ideally not possible from the studio as per my knowledge.
If anyone has idea to do stuff like this please share.
There may come a time in the development of a custom SuiteCRM module when it would be handy to store additional data in the relationship table between two modules. This is not possible in studio or module builder and is not that straight forward even for an experienced coder unless you have a deep understanding of SuiteCRM underlying architecture.
Step 1 The first thing you need to do is define your new fields in the metadata for the relationship. I will be adding the field in the relationship between a custom module FP_events and Contacts. The relationship fp_events_contacts is a many to many and the subpanel will be displaying the field in the contacts subpanel on the FP_events module.
This file can be found at custom/metadata/fp_events_contactsMetaData.php
In the code below notice that I added a field called date_cancelled with type date to the fields array.
$dictionary["fp_events_contacts"] = array (
'true_relationship_type' => 'many-to-many',
'relationships' =>
array (
'fp_events_contacts' =>
array (
'lhs_module' => 'FP_events',
'lhs_table' => 'fp_events',
'lhs_key' => 'id',
'rhs_module' => 'Contacts',
'rhs_table' => 'contacts',
'rhs_key' => 'id',
'relationship_type' => 'many-to-many',
'join_table' => 'fp_events_contacts_c',
'join_key_lhs' => 'fp_events_contactsfp_events_ida',
'join_key_rhs' => 'fp_events_contactscontacts_idb',
),
),
'table' => 'fp_events_contacts_c',
'fields' =>
array (
0 =>
array (
'name' => 'id',
'type' => 'varchar',
'len' => 36,
),
1 =>
array (
'name' => 'date_modified',
'type' => 'datetime',
),
2 =>
array (
'name' => 'deleted',
'type' => 'bool',
'len' => '1',
'default' => '0',
'required' => true,
),
3 =>
array (
'name' => 'fp_events_contactsfp_events_ida',
'type' => 'varchar',
'len' => 36,
),
4 =>
array (
'name' => 'fp_events_contactscontacts_idb',
'type' => 'varchar',
'len' => 36,
),
5 =>
array (
'name' => 'invite_status',
'type' => 'varchar',
'len'=>'25',
'default'=>'Not Invited',
),
6 =>
array (
'name' => 'accept_status',
'type' => 'varchar',
'len'=>'25',
'default'=>'No Response',
),
7 =>
array (
'name' => 'email_responded',
'type' => 'int',
'len' => '2',
'default' => '0',
),
8 =>
array (
'name' => 'date_cancelled',
'type' => 'date',
),
),
'indices' =>
array (
0 =>
array (
'name' => 'fp_events_contactsspk',
'type' => 'primary',
'fields' =>
array (
0 => 'id',
),
),
1 =>
array (
'name' => 'fp_events_contacts_alt',
'type' => 'alternate_key',
'fields' =>
array (
0 => 'fp_events_contactsfp_events_ida',
1 => 'fp_events_contactscontacts_idb',
),
),
),
);
Once you have added your desired fields to the fields arrays do a quick repair and rebuild from the admin panel of SuiteCRM and then execute the suggested SQL queries this will add the fields to the database table for the relationship. (I double-checked that the fields were added by going into phpmyadmin and looking at the fp_events_contacts_c table.)
Step 2 Your fields are now defined and in the actual database table but your only halfway their if you want your fields to actually be displayed in the subpanel. The next thing you want to do is define your new fields in the vardefs for the relationship. This is done by adding a file in the custom/Extensions folder like so: custom/Extension/modules/Contacts/Ext/Vardefs/CAN_BE_ANY_NAME.php
In this file add the following three definitions for each field your adding. Pay careful attention that all the field names and ids match up between definitions as minor typos here will prevent the fields from showing in the subpanel and can be major pain to spot:
$dictionary['Contact']['fields']['e_date_cancelled'] =
array (
'name' => 'e_date_cancelled',
'rname' => 'id',
'relationship_fields'=>array('id' => 'cancelled_id', 'date_cancelled' => 'event_cancelled'),
'vname' => 'LBL_CONT_ACCEPT_CANCELLED',
'type' => 'relate',
'link' => 'fp_events_contacts',
'link_type' => 'relationship_info',
'join_link_name' => 'fp_events_contacts',
'source' => 'non-db',
'importable' => 'false',
'duplicate_merge'=> 'disabled',
'studio' => false,
);
$dictionary['Contact']['fields']['event_cancelled'] =
array(
'massupdate' => false,
'name' => 'event_cancelled',
'type' => 'date',
'studio' => 'false',
'source' => 'non-db',
'vname' => 'LBL_LIST_ACCEPT_CANCELLED',
'importable' => 'false',
);
$dictionary['Contact']['fields']['cancelled_id'] =
array(
'name' => 'cancelled_id',
'type' => 'varchar',
'source' => 'non-db',
'vname' => 'LBL_LIST_ACCEPT_CANCELLED',
'studio' => array('listview' => false),
);
Step 3 The final thing you need to do is define the fields in the actual layout defs of the subpanel. In this case, that file is located: custom/modules/Contacts/metadata/subpanels/FP_events_subpanel_fp_events_contacts.php
In the code below notice that I add my field event_cancelled (as defined in the step 2 vardefs) to list_fields array and further down in the array I also add e_date_cancelled and cancelled_id and mark their usage as query_only.
$subpanel_layout['list_fields'] = array (
'name' =>
array (
'name' => 'name',
'vname' => 'LBL_LIST_NAME',
'sort_by' => 'last_name',
'sort_order' => 'asc',
'widget_class' => 'SubPanelDetailViewLink',
'module' => 'Contacts',
'width' => '23%',
'default' => true,
),
'account_name' =>
array (
'name' => 'account_name',
'module' => 'Accounts',
'target_record_key' => 'account_id',
'target_module' => 'Accounts',
'widget_class' => 'SubPanelDetailViewLink',
'vname' => 'LBL_LIST_ACCOUNT_NAME',
'width' => '22%',
'sortable' => false,
'default' => true,
),
'phone_work' =>
array (
'name' => 'phone_work',
'vname' => 'LBL_LIST_PHONE',
'width' => '15%',
'default' => true,
),
'email1' =>
array (
'name' => 'email1',
'vname' => 'LBL_LIST_EMAIL',
'widget_class' => 'SubPanelEmailLink',
'width' => '20%',
'sortable' => false,
'default' => true,
),
'event_status_name' =>
array (
'vname' => 'LBL_STATUS',
'width' => '10%',
'sortable' => false,
'default' => true,
),
'event_accept_status' =>
array (
'width' => '10%',
'sortable' => false,
'default' => true,
'vname' => 'LBL_ACCEPT_STATUS',
),
'event_cancelled' =>
array (
'width' => '10%',
'sortable' => false,
'default' => true,
'vname' => 'LBL_ACCEPT_CANCELLED',
),
'edit_button' =>
array (
'vname' => 'LBL_EDIT_BUTTON',
'widget_class' => 'SubPanelEditButton',
'module' => 'Contacts',
'width' => '5%',
'default' => true,
),
'remove_button' =>
array (
'vname' => 'LBL_REMOVE',
'widget_class' => 'SubPanelRemoveButton',
'module' => 'Contacts',
'width' => '5%',
'default' => true,
),
'e_accept_status_fields' =>
array (
'usage' => 'query_only',
),
'event_status_id' =>
array (
'usage' => 'query_only',
),
'e_invite_status_fields' =>
array (
'usage' => 'query_only',
),
'event_invite_id' =>
array (
'usage' => 'query_only',
),
'e_date_cancelled' =>
array (
'usage' => 'query_only',
),
'cancelled_id' =>
array (
'usage' => 'query_only',
),
'first_name' =>
array (
'name' => 'first_name',
'usage' => 'query_only',
),
'last_name' =>
array (
'name' => 'last_name',
'usage' => 'query_only',
),
'salutation' =>
array (
'name' => 'salutation',
'usage' => 'query_only',
),
'account_id' =>
array (
'usage' => 'query_only',
),
);
Also, remember to add the label in this case LBL_ACCEPT_CANCELLED to the custom language strings.
I added it to: custom/Extension/application/Ext/Language/en_us.Advanced OpenEvents.php
$app_strings['LBL_ACCEPT_CANCELLED'] = 'Date Cancelled';
But it may work if added to the mod strings.
Now do another quick repair and rebuild from the admin panel and your custom relationship fields should now be showing up on the subpanel. You will now be able to add data into these fields in your module controller either via queries or through SuiteCRM bean framework.
Note you might have to manually go into the database and add some dummy data into those fields to confirm they are showing (Assuming you have not yet added any data to your new fields).
Cheers!

how can I add a dependant custom field through the manifest.php

I am currently adding a web hook and want to add some fields programmatically through the manifest.php.
I have found the relevent information to add fields as below:
'custom_fields' => array (
array (
'name' => 'text_c',
'label' => 'LBL_TEXT_C',
'type' => 'varchar',
'max_size' => 255,
'require_option' => 'optional',
'default_value' => '',
'ext1' => '',
'ext2' => '',
'ext3' => '',
'audited' => 1,
'module' => 'Accounts'
)
);
the issue is that I cant seem to find how to make the fields dependant i.e. they will only be visible if another field contains a specific value.
any help would be greatly appreciated
In the definition array you would need to add the dependency attribute like so :
'custom_fields' => array (
array (
'name' => 'text_c',
'label' => 'LBL_TEXT_C',
'type' => 'varchar',
'max_size' => 255,
'require_option' => 'optional',
'default_value' => '',
'ext1' => '',
'ext2' => '',
'ext3' => '',
'audited' => 1,
'module' => 'Accounts'
'dependency' => 'equal($other_field,"other field value")'
)
);
This would replicate setting the dependency option in Studio.
The dependency formula
'equal($other_field,"other field value")'
Means show this field when the another field other_field equals the string "other field value"

TYPO3 extbase & IRRE: add existing records with 'foreign_selector'

I "kickstarted" an extension with the extbase extension builder that contains some 1:1 and 1:n relations. It automatically set the field types to 'inline' and displayed a nice IRRE UI in the backend.
But by default, there is no way to select an existing record, just create new ones.
I found various explanations on how to achieve this with 'foreign_selector', but all of them very sketchy. The feature itself should be working, see https://forge.typo3.org/issues/43239
Can someone walk me through this or point to a working example in the TER? I could create a step-by-step tutorial from the example, once I get it to work.
PS The field's TCA config as generated by extension_builder:
'myfield' => array(
'exclude' => 1,
'label' => 'LLL:EXT:myextension/Resources/Private/Language/locallang_db.xlf:tx_myextension_domain_model_myitem.myfield',
'config' => array(
'type' => 'inline',
'foreign_table' => 'tx_myextension_domain_model_myfield',
'foreign_field' => 'myitem',
'maxitems' => 9999,
'appearance' => array(
'collapseAll' => 0,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showAllLocalizationLink' => 1
),
),
),
The main problem is that IRRE relations of type 1:n work like this: A child record holds the uid of its parent. So your table tx_myext_domain_model_city holds the UID of your (imaginary) tx_myext_domain_model_address.
Therefore with the default configuration you will not be able to select a city multiple times as it can only have exactly one parent.
So you will need to use a relation table for this field. This table needs to contain a uid field for both the address (uid_address) and the city (uid_city):
CREATE TABLE tx_irreforeignselectordemo_address_city_mm (
uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
uid_address int(11) unsigned DEFAULT '0' NOT NULL,
uid_city int(11) unsigned DEFAULT '0' NOT NULL,
sorting int(11) unsigned DEFAULT '0' NOT NULL,
PRIMARY KEY (uid),
KEY parent (pid)
);
And it needs to have a TCA configuration for these fields (while the table itself can be hidden):
return array(
'ctrl' => array(
'title' => 'Relation table',
'hideTable' => TRUE,
'sortby' => 'sorting',
),
'columns' => array(
'uid_address' => Array(
'label' => 'Address',
'config' => Array(
'type' => 'select',
'foreign_table' => 'tx_irreforeignselectordemo_domain_model_address',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
),
),
'uid_city' => Array(
'label' => 'City',
'config' => Array(
'type' => 'select',
'foreign_table' => 'tx_irreforeignselectordemo_domain_model_city',
'foreign_table_where' => ' AND sys_language_uid IN (0,-1)',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
),
),
),
'types' => array(
'0' => array('showitem' => 'uid_address,uid_city')
),
'palettes' => array()
);
You can then configure the TCA of your address to make it an IRRE field:
'type' => 'inline',
'foreign_table' => 'tx_yourext_address_city_mm',
'foreign_field' => 'uid_address',
'foreign_label' => 'uid_city',
'foreign_selector' => 'uid_city',
'foreign_unique' => 'uid_city',
'foreign_sortby' => 'sorting',
Note that foreign_unique tells TYPO3 that a city can only selected once.
And you need to define the relation from the other side (from your city TCA):
'addresses' => array(
'exclude' => 1,
'label' => 'Addresses',
'config' => array(
'type' => 'inline',
'foreign_table' => 'tx_irreforeignselectordemo_address_city_mm',
'foreign_field' => 'uid_city',
'foreign_label' => 'uid_address',
),
),
Once your configuration is complete, you will be able to use this in the Backend.
Since this is a non-standard MM relation, Extbase will not be able to deal with it by default. But we can compare this to the sys_file_reference table that was introduced in TYPO3 6. So we build an Extbase model for the CityRelation with the properties "address" and "city" and map this model to our mm table:
config.tx_extbase.persistence.classes {
Visol\Irreforeignselectordemo\Domain\Model\CityRelation {
mapping {
tableName = tx_irreforeignselectordemo_address_city_mm
columns {
uid_address.mapOnProperty = address
uid_city.mapOnProperty = city
}
}
}
}
Now in our address model, we define the city (or cities - of you allow more than one choice) as ObjectStorage of type CityRelation:
/**
* Cities
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Visol\Irreforeignselectordemo\Domain\Model\CityRelation>
*/
protected $cities = NULL;
We now have a property "cities" that contains the references to all selected cities. You can iterate through them and use them:
<f:for each="{address.cities}" as="cityRelation">
<li>{cityRelation.city.name}</li>
</f:for>
Since I couldn't find an all-in-one demo for this and was interested in the topic, I created a demo extension that does what I just described - based on the Core and two extensions that deal with the topic: https://github.com/lorenzulrich/irreforeignselectordemo
The solution is an m:n approach anyway (because 1:n wouldn't work for the reasons stated above) so I decided to use "cities" instead of "city". While this might not make sense for selecting a city (as suggested by your post), it might make sense for other opportunities. Feel free to replace "cities" by "city" and set maxItems in the inline configuration to one - then you have kind of an 1:n.

Permanently show block in Moodle?

Is there a way to permanently show a block within Moodle? I am working on configuring a theme, and I wanted to know if there's a way to ensure that a block is visible no matter which page you're on.
One solution should be to add a new block region.
In your theme directory, in config.php file, modify the layout option and add your new region to all your used layouts:
$THEME->layouts = array(
'base' => array(
'file' => 'admin.php',
'regions' => array('your-region'),
'defaultregion' => 'your-region',
),
'standard' => array(
'file' => 'admin.php',
'regions' => array('your-region', 'side-post'),
'defaultregion' => 'your-region',
),
// The site home page.
'frontpage' => array(
'file' => 'general.php',
'regions' => array('tools-menu', 'side-post'),
'defaultregion' => 'tools-menu',
'defaultregion' => 'tools-menu',
),
'course' => array(
'file' => 'general.php',
'regions' => array('your-region'),
'defaultregion' => 'your-region',
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true),
),
etc...
Then you edit all your layout files theme/your_theme/layout/*.php and add this line where you want your block to appear:
echo $OUTPUT->blocks_for_region('your-region');
Now, you will have to add your block to this region for all page type, simply execute this sql in you database:
INSERT INTO `mdl_block_instances` (
`id` ,
`blockname` ,
`parentcontextid` ,
`showinsubcontexts` ,
`pagetypepattern` ,
`subpagepattern` ,
`defaultregion` ,
`defaultweight` ,
`configdata`
)
VALUES ( NULL , 'your_block_name', '1', '1', '*', NULL, 'your-region', '0', NULL );