Disabling file compression in TYPO3 'be:container' - typo3

I've been working around with the development of a TYPO3 extension. While designing the backend module I'd observed that my css and js external files which are included with,
<f:be.container loadJQuery="true" includeCssFiles="{0:'https://ajax.googleapis.com/****'}" includeJsFiles="{0:'https://ajax.googleapis.com/****'}" >
are getting compressed and as a result the design turning into a mess.
Compressing is a good act. I admit it. But how can avoid it in backend container or at least for external files.. ?? Wandering for the answer for 2 days.

From the code this is not easily possible with the be.container view helper (as it calls $pageRenderer->addCssFile directly, without options).
What you could do would be to add an own viewhelper exposing all the addCssFile options. As an example, your viewhelper could look like this:
class AddCssFileViewHelper extends AbstractViewHelper
{
/**
* #var PageRenderer
*/
protected $pageRenderer;
/**
* #param PageRenderer $pageRenderer
*/
public function injectPageRenderer(PageRenderer $pageRenderer)
{
$this->pageRenderer = $pageRenderer;
}
/**
* Initialize arguments.
*
* #throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('cssFile', 'string', 'path to your file', false, '');
$this->registerArgument('compress', 'bool', 'specifies whether to compress or not, default: true', false, true);
}
public function render()
{
$this->pageRenderer->addCssFile($this->arguments['cssFile'], 'stylesheet', 'all', '', $this->arguments['compress']);
}
}

Related

How does one make jsdoc actually output docs?

I'm trying to get jsdoc (version 3.6.7, using node 16) to turn my documented js code into actual documentation, but no matter what I do it just generates an out directory with an index.html that is primarily empty lines, rather than documentation. I've asked about this over on the issue tracker (after I searched the docs and the web for information on what one might be doing wrong to get jsdoc to generate empty files, but I can't for the life of me find anything useful that addresses that) but since it's been a few days, it feels useful to ask here as well, so that an answer in either place can be cross posted.
Running the jsdoc command does not flag any errors with the input, and completes with a normal zero exit code but generates nothing useful, so hopefully someone here's run into his before and can explain what is necessary in addition to the follow code to actually get jsdoc to generate docs.
An example of code that has no errors according to jsdoc, but also yields no docs whatsoever:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #class
* #namespace model
*/
export class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*
* #ignore
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}
Running this with jsdoc test.js yields an out dir with an index.html and test.js.html file, the first containing some thirty newlines of "no docs here" with boilerplate wrapper HTML code, and the second containing the original source code with nothing else useful either.
What else does one need to do to get jsdoc to actually generate documentation here?
I have fixed it by not using export infront of classes, instead exporting them at the end of the file. like this:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #class
* #namespace model
*/
class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*
* #ignore
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}
export {Model}
Turns out this was posted too early: taking the time to start at the official documentation for classes over on https://jsdoc.app/tags-class.html and running that example through jsdoc works perfectly fine, and subsequently building out that example to match the actual file's code yields working documentation just fine, too.
And in this specific case, there were several problems:
adding #namespace paired with #class was the main problem. Neither were necessary, but the #namespace entry changes how jsdoc parses the rest of a file's documentation, where if methods are to show up, they must use a #name property that includes that namespace. As that was not the case here, nothing ended up showing in the documentation.
having an #ignore on the constructor function, rather than using the #hideconstructor property on the class meant that even with #namespace removed, no documentation got written. JSdoc treats the class docs heading and the constructor as the same thing, so #ignoreing the constructor is treated the same as ignoring the entire class.
Fixing both mistakes, and removing the unnecessary #class at the top, gives perfectly fine documentation:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #hideconstructor
*/
export class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}

How to get fal object instead of array when using flux:field.inline.fal

In my flux content template configuration section I define an image field like this:
<flux:field.inline.fal label="Image" name="images" maxItems="1" minItems="0" showThumbs="1"/>
In my flux content template main section I debug the output:
<f:for each="{v:resource.record.fal(table: 'tt_content',field: 'images', uid: '{record.uid}')}" as="image" iteration="iterator">
<f:debug>{image}</f:debug>
</f:for>
The debuging output shows an array but what I need is the FAL object of that image I added in the backend.
I googled a lot and found some older posts from 2015. All say it is not possible to get the fal object(!) in flux. Is it still true? Do you know any way?
One solution is to create a custom ViewHelper:
<?php
namespace Cmichael\Typo3projectprovider\ViewHelpers\Content;
/* FalViewHelper
* To get fal object by image uid (respectivly in flux templates)
* Usage example: <cm:content.fal referenceUid="{image.uid}">
* */
class FalViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* #var bool
*/
protected $escapeOutput = false;
/**
* Initialize arguments.
*
*/
public function initializeArguments() {
$this->registerArgument('referenceUid', 'integer', 'File reference uid', true, 0);
}
/**
* Return file reference
*
* #return \TYPO3\CMS\Core\Resource\FileReference|null
*/
public function render() {
$referenceUid = $this->arguments['referenceUid'];
$fileReferenceData = $GLOBALS['TSFE']->sys_page->checkRecord('sys_file_reference', $referenceUid);
return $fileReferenceData ? \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileReferenceObject($referenceUid) : $referenceUid;
}
}

Could not analyse class: maybe not loaded or no autoloader in typo3 for export using phpexcel

I am writing an export feature using phpexcel library. I have included the library into typo3conf/ext/extension_name/Classes/Library/PHPExcel. And also included the file typo3conf/ext/extension_name/Classes/Library/PHPExcel.php. And injected this file into my typo3 extbase controller as
/**
* PHPExcel
*
* #var \VendorName\ExtensionName\Classes\PHPExcel
* #inject
*/
protected $PHPExcel;
And called this into my export function as
public function exportxlsAction() {
$objPHPExcel = new \PHPExcel();
}
On clicking the backend module it throws the error as
Could not analyse class: "VendorName\ExtensionName\Classes\PHPExcel" maybe not loaded or no autoloader? Class VendorName\ExtensionName\Classes\PHPExcel does not exist..
Why is it so?
Problems in your namespace. Just change it like below.
\VendorName\ExtensionName\Classes\PHPExcel to \VendorName\ExtensionName\Library
Also if you have added all PHPExcel library on this path \VendorName\ExtensionName\Classes\Library\PHPExcel then your name space like below.
\VendorName\ExtensionName\Library\PHPExcel
Another Way.
In your ext_emconf.php File. add below code.
'autoload' => [
'classmap' => [
'Classes',
'Classes/Library/PHPExcel/PHPExcel.php',
]
]
Your controller file code like below.
/**
* PHPExcel
*
* #var \PHPExcel
* #inject
*/
protected $PHPExcel = null;
And you function as it is. like below.
public function exportxlsAction() {
$objPHPExcel = $this->PHPExcel;
}
After replace this changes you need to once install/Uninstall Extension.

Extend tx_news with 1 field without extension_builder

I try to extend the tx_news extension with the field imageright.
For that I found this tutorial: https://docs.typo3.org/typo3cms/extensions/news/2.2.1/Main/Tutorial/ExtendingNews/Index.html
The first step is to use extension_builder to add the field. As I already have a extension in where I want to implement the extension I do not want to use the extension_builder (also I tried it with a new extension and extend the news-model did not work - I have no clue how to do it right). However this are the steps I did:
In my extension my_template I added the folders and file: Classes/Domain/Model/News.php:
class MyTemplate_Domain_Model_News extends Tx_News_Domain_Model_News {
/**
* #var bool
*/
protected $imageright;
/**
* Returns the imageright
*
* #return bool $imageright
*/
public function getImageright() {
return $this->imageright;
}
/**
* Sets the sort
*
* #param bool $imageright
* #return void
*/
public function setImageright($imageright)
{
$this->imageright = $imageright;
}
}
?>
/Ressources/Private/extend-news.txt:
Domain/Model/News
Created the field imageright as tinyint in the table tx_news_domain_model_news (and added it to the SQL file)
I knew I have to create a TCA file in /Configuration/TCA/, but I have no clue how this should look like or what name it needs to have. I think this is the last step I need to make this working.
Also note the extension my_template was just a template, so before my changes there where no Classes and no TCA files.
Solution is to use this tutorial: http://www.lukasjakob.com/extend-a-typo3-extbase-model-with-custom-field/

An error occurred while trying to call Controller->createAction()

I am trying to create something with extbase, but the error-message I get is not very helpful. I took the blog_example extension as a guide. A (maybe) important difference is: I don't have a database table because I want to write a custom domain repository that connects to an external servive through REST.
The actual error message (displayed above the plugin, not as an exception message):
An error occurred while trying to call Tx_MyExt_Controller_SubscriptionController->createAction()
Classes/Controller/SubscriptionController:
Stripped down to the important parts.
class Tx_MyExt_Controller_SubscriptionController extends Tx_Extbase_MVC_Controller_ActionController
{
/**
* #var Tx_MyExt_Domain_Repository_SubscriberRepository
*/
protected $subscriberRepository;
/**
* #return void
*/
public function initializeAction()
{
$this->subscriberRepository = t3lib_div::makeInstance('Tx_MyExt_Domain_Repository_SubscriberRepository');
}
/**
* #param Tx_MyExt_Domain_Model_Subscriber $subscriber
* #dontvalidate $subscriber
* #return string The rendered view
*/
public function newAction(Tx_MyExt_Domain_Model_Subscriber $subscriber = null)
{
$this->view->assign('subscriber', $subscriber);
}
/**
* #param Tx_MyExt_Domain_Model_Subscriber $subscriber
* #return string The rendered view
*/
public function createAction(Tx_MyExt_Domain_Model_Subscriber $subscriber)
{ }
}
Classes/Domain/Model/Subscriber
class Tx_MyExt_Domain_Model_Subscriber extends Tx_Extbase_DomainObject_AbstractEntity
{
/**
* #var string
* #dontvalidate
*/
protected $email = '';
/**
* #param string $email
* #return void
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return string
*/
public function getEmail()
{
return $this->email;
}
}
Resources/Private/Templates/Subscription/new
<f:form action="create" controller="Subscription" objectName="Subscriber" object="{subscriber}" method="post">
<f:form.textfield property="email"></f:form.textfield>
<f:form.submit value="submit"></f:form.submit>
</f:form>
Facts
Adding $subscriber = null removes the message. But $subscriber is null then
A var_dump($this->request->getArguments()); displays the form's fields
There is an index action, and it is also the first action defined in ext_localconf.php
The hints and solutions I found aren't working for me, so I hope someone can guide me into the right direction.
I've got the same bug.
If you pass an Model as argument to an method, it will also validate the model fields.
I've had this annotation on my model property:
/**
*
* #var \string
* #validate NotEmpty
*/
It validates the "#validate" annotation.
The field in the database was empty so i got the error message
An error occurred while trying to call ...
It would be good if there was a better error message.
You need to customize the validation annotation or verify that the property is not empty in the database
Hope it helps somebody
In addtion: check any Validations in your Model and your TCA. If a field is marked as #validate NotEmpty in your Model and is not marked appropriately in the TCA, a record can be saved ignoring the #validate settings in the Model. This can happen if you change the Model and/or TCA after creating records.
An example:
Field 'textfield' is set to not validate, both in the TCA and the Model. You create a new record and save it without filling in the field 'textfield' (you can, it is not set to validate). You then change the Model setting 'textfield' to #validate NotEmpty and then try to show the record on the FE, you will get the error.
The solution for that example:
Simply remove the validation in your Model OR check validations in the TCA and Model so that they work together.
--
A German blog post covers this solution: http://www.constantinmedia.com/2014/04/typo3-extbase-an-error-occurred-while-trying-to-call-anyaction/
just override the template method getErrorFlashMessage in yout controller to provide a custom error message...
/**
* A template method for displaying custom error flash messages, or to
* display no flash message at all on errors. Override this to customize
* the flash message in your action controller.
*
* #return string|boolean The flash message or FALSE if no flash message should be set
* #api
*/
protected function getErrorFlashMessage() {
return 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '()';
}
classic case of "start over from scratch and it works, and if you compare it you have the same code, though".
I updated the code in the question, maybe it helps someone.