TYPO3 - Fluid Translate in PHP ViewHelper within extension - typo3

Using PHP 8.7.17
I have the following viewhelper to give an example of what I require
<?php namespace SRS\SrsPccLog\ViewHelpers;
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
class ShowDateAsStringViewHelper extends AbstractViewHelper
{
public function initializeArguments()
{
$this->registerArgument('month', 'integer', 'month value', true);
}
public function render()
{
$month = $this->arguments['month'];
return $this->monthAsString($month, $year);
}
public function monthAsString ($month) {
switch ($month) {
case 1:
return "January";
case 2:
return "February";
case 3:
return "March";
case 4:
return "April";
case 5:
return "May";
default:
return "";
}
}
I have the function but what I simply want to do is display the month in the native language, ie replace return "January'
with <f:translate key="tx_srspcclog_domain_model_myext.january" />
so that I can be less language specific and get the language from the language files like i do for a fluid view. Any ideas of how to do this when you not in a fluid view but a PHP view helper

\TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($key, $extensionName)

Look inside the TranslateViewHelper and see how they did it (most likely the translate(...) method), and use the code to render your own labels from your XLFF files

What you are actually looking for is "%B".
As the documentation clearly states, the FormatDate ViewHelper understands format strings in strftime() as well as date() format. strftime already has localization built in. You don't need to translate anything yourself.
https://docs.typo3.org/typo3cms/ExtbaseGuide/Fluid/ViewHelper/Format/Date.html#localized-time-using-strftime-syntax
http://php.net/manual/de/function.strftime.php

Related

How can I display the version of my sitepackage in the frontend?

I want to display the version of my sitepackage (from my declaration file ext_emconf.php ) in the frontend.
How do I query this information? I was thinking of using a DataProcessor in my FLUIDTEMPLATE, but I’m not sure whether I need to write my own or if there’s already one I can use for that.
Thank you!
Depending on your exact needs you could make use of ExtensionManagementUtility::getExtensionVersion() to inject a global TypoScript constant via ExtensionManagementUtility::addTypoScriptConstants():
// ext_localconf.php
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptConstants(sprintf(
'site.version = %s',
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sitepackage')
));
Afterwards you can use this constant anywhere in TypoScript setup including variables of Fluid templates:
// TypoScript setup
10 = FLUIDTEMPLATE
10 {
// ...
variables {
siteVersion = {$site.version}
}
}
Now use this variable anywhere you like in your template:
<!-- Fluid template -->
<p>Site {siteVersion}</p>
There is no DataProcessor for that.
I'd suggest to create a small PHP class to read out the version and integrate it via TypoScript as a USER object.
namespace Vendor\Sitepackage\Service;
class SitepackageVersionService
{
public function getVersion(): string
{
$version = '';
$packageManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class);
$extensionKey = 'my_extension_key';
if ($packageManager->isPackageActive($extensionKey)) {
$package = $packageManager->getPackage($extensionKey);
$version = $package->getPackageMetaData()->getVersion();
}
return $version;
}
}
page.10.variables.sitePackageVersion = USER
page.10.variables.sitePackageVersion.userFunc = Vendor\Sitepackage\Service\SitepackageVersionService->getVersion
<strong>Version: {sitePackageVersion}</strong>

"Undeclared arguments passed to ViewHelper" Exception

After updating TYPO3, I get a TYPO3Fluid\Fluid\Core\ViewHelper\Exception "Undeclared arguments passed to ViewHelper ... Valid arguments are."
Tip: Use rector to make these (and other) conversions! Functions for TYPO3 are available, see
https://usetypo3.com/using-rector-with-typo3.html
This may be due to an extension using functionality that has been dropped. Using only the TYPO3 core, you should not see this error.
In your extension: If you still use the render() method in your ViewHelper class with arguments, you may want to replace this:
before:
public function render(Mail $mail, $type = 'web', $function = 'createAction')
after:
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('mail', Mail::class, 'Mail', true);
$this->registerArgument('type', 'string', 'type: web | mail', false, 'web');
$this->registerArgument('function', 'string', 'function: createAction | senderMail | receiverMail', false, 'createAction');
}
public function render()
{
$mail = $this->arguments['mail'];
$type = $this->arguments['type'] ?? 'web';
// ...
}
Additionally,
if there is no need to use render() (e.g. unless you need to access $this variables), you may want to switch to renderStatic() for performance reasons (see also this other Stack Overflow answer "What is the difference between render() and renderStatic() ..." for clarification)
inherit from classes in TYPO3Fluid\Fluid\Core\ViewHelper instead of TYPO3\CMS\Fluid\Core\ViewHelper:
// use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
Documentation:
Developing a Custom ViewHelper
Changelogs:
Breaking: #82414 - CMS ViewHelper base classes removed (>= TYPO3 9.0)
Deprecation: #81213 - Render method arguments on ViewHelpers deprecated (>= TYPO3 9.0)
Breaking: #87193 - Deprecated functionality removed (>= TYPO3 10.0)
You are using other extension that makes this error, for example: https://github.com/lochmueller/calendarize/issues/280
If you have a parameters in a ViewHelper, you send them as arguments from Fluid Template. In TYPO3 this error throws when in render() function not have comments about parameters. You have to include them.
Example:
<?php
namespace VENDOR\ExtensionName\ViewHelpers;
class ExampleViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
{
/**
*
* #param int $foo
* #return boolean
*/
public function render($foo) {
//function render lines
return $bar_boolean;
}
}

How to access a method and pass an argument within the template?

In my template I want check whether an entity has a relation to another one. Meaning one object is in an attached Object Storage of another one.
In the controller I can simply call:
if ($product->getCategory()->offsetExists($category) {
print 'In category ' . $category->getName();
}
But I can't figure out the correct syntax in the template. I tried those without luck (both evaluate to true everytime):
<f:if condition="{product.category.offsetExists(category)}">true</f:if>
<f:if condition="{product.category.offsetExists({category})}">true</f:if>
Is this even possible within the template?
You can only access properties via Getter from Fluid with no parameters, but you can implement an own ViewHelper to check that. As parameters you can use your Product and the Category. Then you can call your ViewHelper from Fluid this way:
<vh:checkOffset product="{product}" category="{category}" />
or inline
{vh:checkOffset(product: product, category: category)}
Within your ViewHelper you can check this in the way you've done it in your Controller:
public function render($product, $category){
return ($product->getCategory()->offsetExists($category));
}
Additionally to sretuer's answer, I'll only mention that you can create VH which will display block conditionally like:
File typo3conf/ext/your_ext/ViewHelpers/CheckOffsetViewHelper.php
<?php
namespace VENDORNAME\YourExt\ViewHelpers;
class CheckOffsetViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
public function render() {
return ($product->getCategory()->offsetExists($category))
? $this->renderChildren()
: '';
}
}
?>
So you can use it in the view:
{namespace vh=VENDORNAME\YourExt\ViewHelpers}
<vh:checkOffset product="{product}" category="{category}" >
Display this only if product is in category
</vh:checkOffset>
Of course you need to fix VENDORNAME and YourExt according to your extension, can be found at the beginning of every controller, model, repository etc.
You may consider https://fluidtypo3.org/viewhelpers/vhs/master/Condition/Iterator/ContainsViewHelper.html which is designed for creating conditions in Fluid that check if an array or Iterator contains another object and works exactly like f:if regarding then and else arguments and f:then and f:else child nodes.

Symfony and Zend Lucene highlighting

I use symfony 1.4 and I use Zend Lucene search like in Jobbet And I need to make Search Results Highlighting, I read this , but I do not understend how it make in my case with symfony(
$ highlightedHTML = $ query-> highlightMatches ($sourceHTML);
What is $sourceHTML? And is it all makes by only one row?
upd:
$ highlightedHTML = $ query-> highlightMatches ($sourceHTML);
It works in my model, but how it implement in my view?
I do not now , if it is right , but it is work :)
Just in view:
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
$highlightedHTML = $query->highlightMatches($sourceHTML);
In my case for example:
echo $query->highlightMatches($ad->getCompany())
You need to store this highlighted HTML in your model. Or make a function that is accessible from the view. For example:
<?php
class Model {
private $content;
public function getContent(){
return $this->content;
}
public function getContentHighlighted(){
// Search term, usually in $_GET or $_POST
$term = $_GET['searchterm'];
// Parse query
$query = Zend_Search_Lucene_Search_QueryParser::parse($term);
// Return highlighted
return $query->highlightMatches($this->getContent());
}
}
?>
In your view (like in this case: Twig) you use:
<h1>The content</h1>
{{model.getContentHighlighted}}

Wordpress: Accessing A Plugin's Function From A Theme

I'm trying to add some functionality from a plugin I have made into a Wordpress theme but I am having little joy. The documentation doesn't really help me solve the problem so perhaps someone here can help.
I have a plugin in Wordpress that is activated and working fine. The class for this plugin has a function called generateHtml which I would like to access from a Wordpress Theme. But whatever I try, I cannot seem to access my plugin's code.
Can either give me a summary of what I need to do to get a theme accessing code from a plugin and/or point out there I am going wrong in my code:
Plugin:
<?php
/** Usual comments here **/
if (!class_exists("ImageRotator")) {
class ImageRotator {
private $uploadPath = '';
private $pluginPath = '';
private $options;
function __construct() {
$this->uploadPath = dirname(__file__).'\\uploads\\';
// add_shortcode('imagerotator', array(&$this, 'generateHtml'));
}
// Various functions for plugin
function generateHtml() {
echo '<p>Hello World</p>';
}
}
}
/**
* Create instance of image rotator
*/
$imageRotator = new ImageRotator();
/**
* Create actions & filters for Wordpress
*/
if (isset($imageRotator)) {
// Actions
add_action('admin_menu', array(&$imageRotator, 'createMenu'));
add_action('admin_init', array(&$imageRotator, 'registerSettings'));
add_action('imagerotator_show', array(&$imageRotator, 'generateHtml'));
}
Portion from theme header page:
<?php if (isset($imageRotator)) {
$imageRotator->generateHtml();
} else if (isset($ImageRotator)) {
print_r($ImageRotator);
} else {
echo '<p>Nope!</p>';
}
if (function_exists("imagerotator_show")) {
echo 'Function found';
} else {
echo 'Function NOT found';
}
?>
Currently all I ever see is "Nope" and "Function NOT found". Thanks for any input.
Lee,
For starters, "imagerotator_show" is not a function; it's the name of a type of action. When you use the add_action() function, Wordpress just adds your method to the list of functions/methods to call when a particular action is triggered. Thus your second test will always respond with 'Function NOT found'.
The most likely cause of the first problem is failing to declare the method you want to call as a public method. You're also making the code harder than it needs to be.
The best practice I've seen for declaring methods and registering hooks from a class looks something like this:
if ( ! class_exists( 'Foo' ) ):
class Foo {
function __construct() {
add_action( 'hook_name', array( &$this, 'my_hook_implementation' ) );
}
function my_hook_implementation() {
// does something
}
public function my_special_method() {
// does something else
}
}
if ( class_exists( 'Foo' ) ):
$MyFoo = new Foo();
This allows your class to keep all of its implementation details private. When you need to call my_special_method(), you do it as follows:
$MyFoo->my_special_method();
#andrew since I can't comment I thought I would answer your ancillary question. See:
http://net.tutsplus.com/tutorials/wordpress/create-wordpress-plugins-with-oop-techniques/
Where it is explained that when defining a callback function from an object you have to use the array function. It's basically saying get the function 'my_hook_implementation' from the object $this and use it as the callback parameter to the add action hook. It is because you defined the function within the scope of the object and you have to define the scope in order for PHP to know what function you are talking about. The scope being the object referred to by the variable $this.
You just need to use do_action() function, inside your theme.
If you want the function generateHtml to appears inside your header.php you just need to open the header.php file and paste <?php do_action('imagerotator_show'); ?> where you want and then your function will be called there.