Replacement for deprecated TYPO3 ErrorpageMessage - error-handling

After the upgrade of the extension tt_board to TYPO3 10 I stumble over deprecation #77164 - ErrorpageMessage and AbstractStandaloneMessage.
The official page only states that the new Fluid-based ErrorPageController class should be used instead.
However this controller class is just able to generate a HTML result string for me. But the second half of the job is missing. The HTML output must be shown somehow by TYPO3 in an error dialog raised by an exception.
Is there any simple solution for this?
Before:
use TYPO3\CMS\Core\Messaging\ErrorpageMessage;
...
$message = $languageObj->getLabel('error_no_permission');
$title = $languageObj->getLabel('error_access_denied');
$messagePage =
GeneralUtility::makeInstance(
ErrorpageMessage::class,
$message,
$title
);
$messagePage->output();
Now:
use TYPO3\CMS\Core\Controller\ErrorPageController;
...
$message = $languageObj->getLabel('error_no_permission');
$title = $languageObj->getLabel('error_access_denied');
$errorController =
GeneralUtility::makeInstance(
ErrorPageController::class
);
$content = GeneralUtility::makeInstance(ErrorPageController::class)->errorAction(
$title,
$message
);
Can I send this $content to a TYPO3 object which will do the error output for the extension?

In general you can show it an any possible way, but you can use flashMessages to show it in standardized kind.
Be aware that for the frontend you have to implement according CSS for the styling.
In fluid it's looking like this and is part of extensions created with extension_builder:
<f:flashMessages />
It might be possible that you have to implement it a bit different to loop about several messages. I never use it usually but I remember that implementation changed once and doubt that it's reflected by this kind of implementation.
Below you find the required details listed:
The implementation for flashMessages is described here:
https://docs.typo3.org/m/typo3/reference-coreapi/11.5/en-us/ApiOverview/FlashMessages/Index.html
The description of the flashMessage-ViewHelper you find here:
https://docs.typo3.org/other/typo3/view-helper-reference/11.5/en-us/typo3/fluid/latest/FlashMessages.html
The CSS you could probably take from bootstrap but reliable from the extension examples. In the CSS for the backend you could search it too.
Concerning your code:
I think you can leave away this, as it's not used:
$errorController =
GeneralUtility::makeInstance(
ErrorPageController::class
);
or you can use this code:
$errorController =
GeneralUtility::makeInstance(
ErrorPageController::class
);
$content = $errorController->errorAction(
$title,
$message
);

Related

How to set syntax highlighting to a code section to a specific language programmatically/with comments?

I have a Laravel blade template (.blade.php) which contains plain JavaScript as a section that will be later inserted into a generic wrapper. So the example would be:
<div>Some HTML content</div>
#section('js')
var a = "b";
someCall();
#endsection
Now PhpStorm would recognize the JavaScript if it was in <script> tag, which it can't be. So I've tried this which I would expect to work like a section highlighter hint:
#section('js')
// #lang JavaScript
var a = "b";
someCall();
// #endlang
#endsection
and this
#section('js')
// language=JavaScript
var a = "b";
someCall();
#endsection
But nothing worked (clickable language injection breaks other highlighting).
What am I doing wrong? How can I programmatically/commentarily set a section to be highlighted as a language I specify?
It's not yet implemented for Blade (although exists for Smarty and Twig templates).
https://youtrack.jetbrains.com/issue/WI-29254 -- watch this ticket (star/vote/comment) to get notified on any progress.

How do I allow my ASP.NET Core tag helpers to be self-closing

I have written a tag helper that I can use as follows...
<mytaghelper attr1="jim"></mytaghelper>
I would like to be able to shorten this to just...
<mytaghelper attr1="jim">
...or at least...
<mytaghelper attr1="jim"/>
However, I can't get this to work. Here is some sample code for the Process method...
public override void Process(TagHelperContext context, TagHelperOutput output) {
output.TagName = "div";
output.PreContent.SetHtmlContent("<div>");
output.Content.SetHtmlContent("OUTPUT HTML GOES HERE");
output.PostContent.SetHtmlContent("</div>");
output.Attributes.Clear();
}
I have tried adding a TagStructure setting to the HtmlTargetElement attribute on the class...
[HtmlTargetElement("mytaghelper", TagStructure = TagStructure.WithoutEndTag)]
...but it doesn't seem to make any difference. <mytaghelper attr1="jim"/> generates <div /> and <mytaghelper attr1="jim"></mytaghelper> generates <div></mytaghelper>.
If I set the TagStructure to NormalOrSelfClosing then included a closing tag works, but <mytaghelper attr1="jim"/> gives an empty <div />
Anyone able to explain what I need to do?
TagStructure.WithoutEndTag is able to write the tag with only a start tag or self-closing, but the output would be <div > or <div/> . Self-closing anchor tags are not valid HTML, so you wouldn't want to create one, but you might want to create a tag helper that's self-closing. Tag helpers set the type of the TagMode property after reading a tag. Add the below code line Inside the process method:
output.TagMode = TagMode.StartTagAndEndTag;
Take a moment to read Author Tag Helpers in ASP.NET Core which covers this perfectly .
The correct syntax is:
[HtmlTargetElement("mytaghelper", TagStructure = TagStructure.WithoutEndTag)]
Which should be applied to the taghelper class, not the Process method. You may already be doing that, but it wasn't clear in your question. I believe you still must use the self-closing tag syntax (/>) for it work, though.

TYPO3 fluid: how to create link to PDF-File (no download, no display)

Being new to TYPO3 fluid I was wondering if there's an easy way to create a link to a PDF-file which is located in the filelist as you would in simple html as follows:
Click here to open pdf (in a new window)
I couldn't find a solution so far that wouldn't require an extension or that wouldn't render the pdf direclty on the page (<flux:field.inline.fal name="settings.image" required="1" maxItems="1" minItems="1"/>)
Should/Can this be done with <f:link.external href="filePathOnServer/file.pdf"> ? (I've got another problem at the moment preventing me from checking if this works...)
EDIT
I've tried using <f:link.external> which didn't work. For the time being I'm using the (non-fluid) <a>-tag...
I had to do the same thing and I resolved it by writing a custom ViewHelper just to get the site url.
ViewHelper:
class InternalViewHelper extends AbstractViewHelper
{
/**
* Renders a link to a specific path from the root path of TYPO3.
*
* #param string $path The path to an internal resource relative to the TYPO3 site URL.
* #return string The absolute URL to the given resource.
*/
public function render($path)
{
$siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
return htmlspecialchars($siteUrl . $path);
}
}
Fluid Template:
{namespace ext = Vendor\MyExt\ViewHelpers}
<f:link.external target="_blank"
uri="{ext:internal(path: 'uploads/tx_myext/myfile.pdf')}">
Link
</f:link.external>

Yii CGridView change the header's tr class

So i am working in an app that uses de CGridView extensively but I am porting a webapp from a proprietary framework to Yii. So the CSS files are already written and have been working up until now.
The thing is that in my CGridView widget the headers of columns are enclosed in a TR tag and I have got no clue on where I can add a class attribute to this tag. I've read the documentation and now how to change each header cell individually but not the whole TR.
Thanks for your help!
Ran into a similar problem however as our CSS is for a legacy system I didn't want to roll in yet more CSS rules. In addition I needed support for extra things such as targeting the header with a specific CSS class on the table row and putting in first/last css classes on the items.
To achieve a first/last css on the items you do not need to extend the GridView and can use the handy rowCssClassExpression parameter.
To achieve my second objective of injecting a CSS class into the 'table thead tr' element I did have to override the renderTableHeader() method.
I strongly advise you only consider this route as a last resort because if you update the version of Yii it is conceivable that they make changes that are not backwards compatible with the renderTableHeader() method. Alternatively you could write a test case that runs your widget through a DOM checker to confirm that you only have 1 table element, 1 thead element, 1 tbody element etc...
Yii::import('zii.widgets.grid.CGridView');
class FXSGridView extends CGridView {
public $headerCssClass = 'columnHeadings';
public $itemsCssClass = 'grey';
public $rowCssClassExpression = '$this->rowCssClassFunction($row, $data);';
public $rowCssClass = array('odd','even');
public function rowCssClassFunction($row, $data) {
$classes = array();
if ($row == 0) $classes []= 'first';
if ($row == $this->dataProvider->getItemCount() - 1) $classes []= 'last';
// Do flip/flop on defined rowCssClass
if(is_array($this->rowCssClass) && !empty($this->rowCssClass)) $classes []= $this->rowCssClass[$row % count($this->rowCssClass)];
return empty($classes) ? false : implode(' ', $classes);
}
public function renderTableHeader()
{
if(!$this->hideHeader)
{
echo "<thead>\n";
if($this->filterPosition===self::FILTER_POS_HEADER)
$this->renderFilter();
echo '<tr class="' . $this->headerCssClass . ' ">' . "\n";
foreach($this->columns as $column)
$column->renderHeaderCell();
echo "</tr>\n";
if($this->filterPosition===self::FILTER_POS_BODY)
$this->renderFilter();
echo "</thead>\n";
}
else if($this->filter!==null && ($this->filterPosition===self::FILTER_POS_HEADER || $this->filterPosition===self::FILTER_POS_BODY))
{
echo "<thead>\n";
$this->renderFilter();
echo "</thead>\n";
}
}
}
'columns'=>array(
array(
'name'=>'id',
'header'=>'#',
'htmlOptions'=>array('style'=>'width: 50px; text-align: center;', 'class'=>'zzz'),
'headerHtmlOptions'=>array('class'=>'mytheadclass'),
),
The "headerHtmlOptions" is the one that gives a class to the thead cell of this column.
Unfortunately you cannot do this directly, as there is no provision for adding attributes to the header row tags (see source code).
A straightforward solution would be to subclass CGridView as e.g. MyGridView and override the renderTableHeader method to do what you need it to (add some class variables to MyGridView to let it be configurable). I have used this approach many times in similar situations.
If it's just simple changes you need to make, you might be able to use the generated CSS with something like:
table.admins th {border-right:none;text-align:center;}
table.admins th:first-child {text-align:left;}
etc...
or you could use the Yii-generated ids (view the generated HTML):
<th id="admins-grid_c1">
which may or may not be appropriate depending on how many grids you want to apply the css to and your own naming conventions. You could also use JavaScript/jQuery to manipulate the styles but certainly #Jon's suggestion of creating a custom renderTableHeader is going to give you the most control. (I've also used that approach with lists and renderSorter.)

Access Elements of a DOJO DIV

I have two Hyper Links on to a DOJO DIv
var create = dojo.create("div",{
id:"create_links",
className:"iconRow1",
innerHTML:"<a class='popupLink' href='javascript:openCreateDialog()'>Create </a> <span>|</span><a href='javascript:openUploadDialog()'>Batch </a>"
},dojo.query(".ui-jqgrid-titlebar")[0]);
On click of the Batch Hyperlink , i have a function
function openUploadDialog()
{
// Here i want to disable the Create Hyper Link tried this way
dojo.byId('create_links')[1].disabled=true; // Not working
}
See whether i can answer your question.
HTML Part:
<div id="create_links">
g
h
</div>
JS Part:
dojo.addOnLoad(function() {
var a = dojo.query("#create_links a")[1];
dojo.connect(a,'click',function(e){
console.log(e.preventDefault())
})
})
#Kiran, you are treating the return of dojo.byId('create_links') like an array when that statement will return to you a node on the dom.
Also, hyperlinks don't support a disabled attribute to prevent them from being actionable. You could probably create a click handler that returns false to accomplish this type of functionality, or like #rajkamal mentioned, calling e.preventDefault(). #rajkamal also provides a good solution to selection the link properly.