Question: What is the best way to track a fields data source?
I have been going through numerous files and all the references that I can find are correct.
The issue is that the "Last Name" field is showing the contacts full name.
Any ideas would be greatly appreciated.
I am working with SugarCRM CE 6.5.13
Thanks.
Fields are defined in modules/SomeModules/vardefs.php or if it is a
custom_field in the db table fields_meta_data
in the modules bean modules/SomeModules/SomeModule.php you can overwrite default behavior to generate for example a full_name like this:
For detail view:
function fill_in_additional_detail_fields() {
parent::fill_in_additional_detail_fields();
$this->full_name = 'Something else';
}
For list view:
function fill_in_additional_list_fields() {
parent::fill_in_additional_list_fields();
$this->full_name = 'Something else';
}
Or by overriding the standard function _create_proper_name_field:
/**
* This function helps generate the name and full_name member field
* variables from the salutation, title, first_name and last_name fields.
* It takes into account the locale format settings as well as ACL settings
* if supported.
*/
public function _create_proper_name_field() {
parent::_create_proper_name_field();
$full_name = trim(trim($this->first_name) . ' ' . trim($this->last_name));
if (!empty($full_name) && !empty($this->name)) {
$full_name .= ' - ';
}
if (!empty($this->name)) {
$full_name .= $this->name;
}
$this->full_name = $full_name;
}
Related
I have the problem that the backend users can set a word with a "" character, for example something like "Test­ ;labor".
If someone uses the frontend search with the word "Testlabor" no match will be found.
In the extbase repository I used this:
$query->like('name', '%' . $searchWord . '%')
I can change that to something like this:
$query->statement("SELECT * FROM table WHERE hidden = 0 AND REPLACE(name,'', '') LIKE '%$searchWord%'")
Then the word will be found but I have to check all the things the framework normally does, like check if it's hidden and deleted and more complicated, if the result is in the right site tree. Now I just get everything that matches the searchword.
Is there a better way to search for words which have "" inside? Can I use something like that within the TYPO3 query builder?
Many thanks in advance.
You can try with QueryBuilder interface
public function findShy($searchWord)
{
/** #var ConnectionPool $pool */
$pool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $pool->getConnectionForTable('table');
$queryBuilder = $connection->createQueryBuilder();
$query = $queryBuilder
->select('*')
->from('table')
->where("REPLACE(name,'', '') like :name")
->setParameter('name', "%{$searchWord}%");
// for debug only
echo($query->getSQL());
print_r($query->getParameters());
return $query->execute()->fetchAll();
}
and call it somewhere i.e. in your controller:
DebuggerUtility::var_dump(
$this->yourRepository->findShy('Testlabor'),
'findShy() sample'
);
it will create a query with named parameter like (according to your TCA of course):
SELECT *
FROM `table`
WHERE (REPLACE(name, '', '') like :name)
AND ((`table`.`deleted` = 0) AND (`table`.`hidden` = 0) AND
(`table`.`starttime` <= 1596363840) AND
((`table`.`endtime` = 0) OR (`table`.`endtime` > 1596363840)))
Note that returns associative array with the record not a mapped object of your model.
Optional
If you need mapped model objects anyway, you can mix these two solutions, i.e. first select only the pids of your records with QueryBuilder and then fetch them with Query which implements QueryInterface like this:
public function findShy2($searchWord)
{
/** #var ConnectionPool $pool */
$pool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $pool->getConnectionForTable('table');
$queryBuilder = $connection->createQueryBuilder();
$preQuery = $queryBuilder
->select('uid')
->from('table')
->where("REPLACE(name,'', '') like :name")
->setParameter('name', "%{$searchWord}%");
// for debug only
echo($query->getSQL());
print_r($query->getParameters());
$uids = [];
foreach ($preQuery->execute()->fetchAll() as $item) {
$uids[] = $item['uid'];
}
if(count($uids) > 0){
$interfaceQuery = $this->createQuery();
$interfaceQuery->matching(
$interfaceQuery->in('uid', $uids)
);
return $interfaceQuery->execute();
}
return [];
}
Is there any hook to handle links with the new LinkHandler for TYPO3 8.7?
On the old LinkHandler extension is possible to define a hook to process the links as we want.
I need to overwrite the parameter of typolink based on some rules. Is there a way to do this on my extension?
There are multiple points to hook into.
TypoLink post-processing
You can hook into the TypoLink post-processing to modify the typolink itself before it gets rendered.
For this, you first register your custom class in ext_tables/ext_localconf:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'][] = 'Vendor\\Name\\Service\\TypoLinkProcessingService->postProcessTypoLink';
Then, inside your TypoLinkProcessingService class (with your name of choice, of course), you'd handle it inside your own method. For visualisation purposes, in this example, I'm altering an URL if it is a link to a youtube video in order to turn off "related videos" at the end, and to modify the color used by the controls inside youtube's player.
public function postProcessTypoLink(&$parameters, ContentObjectRenderer &$parentObject)
{
if (isset($parameters['finalTagParts']['url'])) {
$urlParts = parse_url($parameters['finalTagParts']['url']);
if (stristr($urlParts['host'], 'youtube.com') !== false && stristr($urlParts['path'], 'watch') !== false) {
$parameters['finalTag'] = str_replace(
'"' . htmlspecialchars($parameters['finalTagParts']['url']) . '"',
'"' . htmlspecialchars($parameters['finalTagParts']['url'] . '&rel=0&color=ffffff') . '"',
$parameters['finalTag']
);
}
}
}
TypoLink UserFunc
Another option is to utilise userFunc and adapt links.
For this, you configure your linkhandler configuration (PageTS) to provide userFunc inside typolink. Add TypoScript as needed to later fetch the configured data.
config.recordLinks {
tx_myest {
typolink {
userFunc = Vendor\Name\UserFunc\TypolinkUserFunc->parseLinkHandlerTypolink
userFunc {
newsUid = TEXT
newsUid.data = field:uid
newsClass = TEXT
newsClass.data = parameters:class
defaultDetailPid = 53
}
}
}
}
Inside your parseLinkHandlerTypolink method, you can access configured properties and adapt as required:
class TypolinkUserFunc
{
/**
* #var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
* #inject
*/
public $cObj;
/**
* Add a method description here
*
* #param array $content
* #param array $configuration
* #return string
*/
public function parseNewsLinkHandlerTypolink(array $content, array $configuration)
{
if (!$configuration['newsUid']) {
return;
}
$params = $this->cObj->cObjGetSingle($configuration['newsClass'], $configuration['newsClass.']);
$newsUid = (int)$this->cObj->cObjGetSingle($configuration['newsUid'], $configuration['newsUid.']);
// ... your code goes here ...
$url = $this->cObj->typolink('', $typolink);
return '<a href="' . $url . '" ' . $attributes . '>';
}
}
Alternatively, this hook that has been introduced in 8.6 may also help you: https://docs.typo3.org/typo3cms/extensions/core/Changelog/8.6/Feature-79121-ImplementHookInTypolinkForModificationOfPageParams.html
I don't want to use the default header in my FCE's, but only custom flux fields. In the backend list views my FCE's are shown as "[no title]" because the default header is not filled. This leads to much confusion for editors.
How can I define one of my custom flux fields to be used as title for the FCE in TYPO3 Backend list views etc.?
You can't just use a field from the flexform, because all fields from the FCE are stored in the same field in the database (pi_flexform).
What you can do is to render the content element title with a user function. It is registered with a line like this in the TCA config:
$GLOBALS['TCA']['tt_content']['ctrl']['label_userFunc'] = 'Vendor\\Extkey\\Utility\\ContentElementLabelRenderer->getContentElementTitle';
The user function itself could look like this:
<?php
namespace Vendor\Extkey\Utility;
/**
* This class renders a human readable title for FCEs,
* so one is able to find a content element by its headline.
*/
class ContentElementLabelRenderer implements \TYPO3\CMS\Core\SingletonInterface {
/**
* #var \TYPO3\CMS\Extbase\Service\FlexFormService
* #inject
*/
protected $flexFormService = null;
/**
* Returns the content element title for a given content element
*/
public function getContentElementTitle(&$params) {
if (null === $this->flexFormService) {
$this->flexFormService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Service\\FlexFormService');
}
if (ctype_digit($params['row']['uid']) && 'fluidcontent_content' === $params['row']['CType']) {
// If this is a FCE, parse the flexform and template name and generate the
// title in a template specific way.
$row = $params['row'];
$additionalRowData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('pi_flexform, tx_fed_fcefile', 'tt_content', 'uid = ' . $row['uid']);
$flexFormContent = $this->flexFormService->convertFlexFormContentToArray($additionalRowData['pi_flexform']);
$lastColonPosition = strrpos($additionalRowData['tx_fed_fcefile'], ':');
$contentElementType = (FALSE === $lastColonPosition) ? 'invalidtype' : substr($additionalRowData['tx_fed_fcefile'], $lastColonPosition + 1);
switch ($contentElementType) {
case 'Image.html':
$params['title'] = 'Image: "' . ($flexFormContent['title'] ?: $flexFormContent['subtitle']) . '"';
break;
default:
$params['title'] = 'Unknown content element type';
break;
}
}
else {
// If this is not a FCEm, print out "normal"
// title. Not the real thing, but comes pretty close, hopefully.
$params['title'] = $params['row']['header'] ?: ($params['row']['subheader'] ?: $params['row']['bodytext']);
}
}
}
This produces a maintainance problem though: Every time you add or change a content element, you have to update this file.
I'm looking for a hook that let's me modify the database output, when editing my extension in the backend, before it's printed to the TCE fields.
I tried getSingleField_preProcess in class.t3lib_tceforms.php but that did not contain any relevant data to my extension.
getSingleField_preProcess should be the correct hook for what you want. I think the problem is that your function is called for records of every table, not just yours. You have to differentiate when to do any processing based on the table that is being rendered. The name of the table is passed to your getSingleField_preProcess() method.
Your ext_localconf.php should register your hook:
$GLOBALS ['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms.php']['getSingleFieldClass'][] = 'tx_yourextension_be';
...where tx_yourextension_be is the name of your class designated for the backend processing. This class then must contain getSingleField_preProcess() method:
public function getSingleField_preProcess($table, $field, &$row, $altName, $palette, $extra, $pal, &$pObj) {
// ...processing...
}
As you see, several variables are passed to your method. $table contains the name of the table to which the processed record belongs to. $field is the name of the field that is being rendered. $row contains the whole record that you can manipulate.
Probably you want to use TCEmain hook
function processDatamap_preProcessFieldArray(array &$incomingFieldArray, $table, $id, t3lib_TCEmain &$reference) {
if ($table == 'tx_yourext_table') {
$a = $incomingFieldArray['field_a'];
$b = $incomingFieldArray['field_b'];
$incomingFieldArray['field_c'] = $a . ' ' . $b;
}
}
OR/AND
function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, &$reference) {
if ($table == 'tx_yourext_table') {
if ($status == 'update') {
$this->doSomethingWithRecordAfterUpdate($id);
}
}
}
Of course you need to register the hook in ext_localconf.php of your extension, for an example:
$GLOBALS ['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['yourext']
= 'EXT:yourext/class.tx_yourext_tcemain.php:tx_yourext_tcemain';
I get a really anoying error when I try to edit an entry from a table, in tutorial they always use getTable()->find(), but I need to verify that the person logged in is the owner of that entry here what I did:
In the action:
public function executeEdit(sfWebRequest $request)
{
$id = $request->getParameter('id');
$userid = $this->getUser()->getGuardUser()->getId();
$ad = Doctrine_Core::getTable('BambinbazarArticles')->getMyAd($id, $userid);
$this->forward404Unless($ad, sprintf('Object bambinbazar_articles does not exist (%s).', $request->getParameter('id')));
$this->form = new BambinbazarArticlesForm($ad);
}
In the model:
public function getMyAd($id, $userid)
{
$q = $this->createQuery('c')
->where('c.id = ? ', $id)
->addWhere('c.userid = ? ', $userid);
return $q->execute();
}
I tried it with and without the ->execute(), did doctrine clean, cleared cache, rebuilded model,
Always get the same error 'The "%s" form only accepts a "%s" object.
If I use the Doctrine_Core::getTable('BambinbazarArticles')->find() it work, but of course, i need more than that..
I am becoming crazy over this.
execute() can return multiple rows; effectively you're getting a recordset back, rather than the individual object that your form is expecting. Try fetching a single object, using, e.g.:
return $q->execute()->getFirst();
or
return $q->fetchOne();
Its probably because your query is returning a Doctrine_Collection, not the actual Doctrine_Record youre expecting. Instead of execute use fetchOne.
public function getMyAd($id, $userid)
{
$q = $this->createQuery('c')
->where('c.id = ? ', $id)
->addWhere('c.userid = ? ', $userid)
->limit(1);
return $q->fetchOne();
}