How to dynamically change serialized groups in symfony jms fosrestbundle? - rest

Hello I'd like to dynamically change the groups of my serialization context.
The code :
/**
* #Rest\Get("", name="bap_api_space_query")
* #Rest\View(serializerGroups={"Default", "space_dashboard", "dashboard_resource"})
*
* #ApiDoc(resource=true,description="List all spaces this user has access to")
*/
public function queryAction(Request $request)
{
$user = $this->getUser()->reload();
$organization = $user->getOrganization();
// depending the request, remove or add serialized group
// for example $view->setSerializationGroups('dashboard');
return $organization->getSpaces();
}
As commented in the code, i'd like to remove or add group in the controller .
Is there a way to do it ?

The solution is pretty easy after 5hours of research :
public function queryAction(Request $request)
{
$user = $this->getUser()->reload();
$organization = $user->getOrganization();
// filter spaces where org has an active contract
$context = new Context();
$context->setGroups(array('Default'));
$spaces = $organization->getSpaces();
$view = $this->view($spaces, 200);
$view->setContext($context);
return $this->handleView($view);
}

Related

Is there a way to search in Extbase and the TYPO3 query builder for words which have a "&shy" inside?

I have the problem that the backend users can set a word with a "­" character, for example something like "Test&shy ;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 [];
}

How do I get uid of a File Reference Object in TYPO3?

I am trying to get a file through this code $f = $resourceFactory->getFileObject($uid); but the problem is the uid is a protected field in the file reference object, as seen below so I am not able to get the uid, and getUid() obviously wont work either.
So how can I get the uid of the file reference (FAL)
/**
* A file reference object (File Abstraction Layer)
*
* #api experimental! This class is experimental and subject to change!
*/
class FileReference extends
\TYPO3\CMS\Extbase\Domain\Model\AbstractFileFolder
{
/**
* Uid of the referenced sys_file. Needed for extbase to serialize the
* reference correctly.
*
* #var int
*/
protected $uidLocal;
/**
* #param \TYPO3\CMS\Core\Resource\ResourceInterface $originalResource
*/
public function setOriginalResource(\TYPO3\CMS\Core\Resource\ResourceInterface $originalResource)
{
$this->originalResource = $originalResource;
$this->uidLocal = (int)$originalResource->getOriginalFile()->getUid();
}
/**
* #return \TYPO3\CMS\Core\Resource\FileReference
*/
public function getOriginalResource()
{
if ($this->originalResource === null) {
$this->originalResource = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileReferenceObject($this->getUid());
}
return $this->originalResource;
}
}
Given you have an instance of TYPO3\CMS\Extbase\Domain\Model\FileReference then you can use getOriginalResource() to get the wrapped TYPO3\CMS\Core\Resource\FileReference. If you need the referenced file, you can then use getOriginalFile(). Thus as a chained call:
$file = $fileReference->getOriginalResource()->getOriginalFile();
Notice that you don't have to use the ResourceFactory yourself in all of this, this is taken care of internally.
Work form me.
You can find or get file refernce uid using custom query.
In Controller :
$uid = $yourObject->getUid();
$fileReference = $this->yourRepository->getFileReferenceObject($uid);
In Repository
public function getFileRefernceHeaderLogo($uid){
$query = $this->createQuery();
$queryString = "SELECT *
FROM sys_file_reference
WHERE deleted = 0
AND hidden = 0
AND tablenames='your_table_name'
AND fieldname='your_field_name'
AND uid_foreign =".$uid;
$query->statement($queryString);
return $res = $query->execute(true);
}
In Controller
$fileRefUid = $fileReference[0]['uid'];
Here you can get uid of file reference table.It is long process.
You can also get sys_file table uid for getFileObject.like,
$sys_file_uid = $fileReference[0]['uid_local'];

LinkHandler hook on TYPO3 8

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

Fluidtypo3: Use custom field as title of FCE

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.

How to set either Zend_Form_Element_Text required?

I'm new to Zend Framework, I have a question is that if I have two Zend_Form_Element_Text in a form, and I want make either of them to be filled by the user.
For example, phone number and mobile number. People only need enter one of them to continue.
How am I going to do this? Thanks
Hi i think you can do the following.
If you're initalizing your form in an Controller Action try this:
/**
* IndexAction
*
* #return void
*/
public function indexAction() {
// initalize your form
$form = new MyForm();
// get post data
$post = $this->_request->getPost();
// check if phone number is empty
if (! empty($post['phone_number'])) {
// remove validator from mobile phone element
$mobile = $form->getElement('mobile');
$mobile->removeValidator('notEmpty');
$mobile->setRequired(false);
}
if ($form->isValid($this->getRequest()->getPost())) {
$input = $form->getValues();
// do something with the input
print_r($input, true);
}
}