Extbase add calculated field in query/repository - typo3

I have a normal extbase extension.
In the controller I get all my records:
$stuff = $this->jobRepository->findAll();
$this->view->assign('stuff', $stuff);
and in the template I display them:
<f:for each="{stuffs}" as="stuff">
{stuff.title} <br />
{stuff.category}
</f:for>
Now I need a new field stuff.isnew with the value 1 if the record is the newest by category.
An SQL-Statement for that would look like:
SELECT j2.isnew, j.* FROM `tx_stuff_domain_model_stuff` as j
left join
(SELECT max(crdate) as crdate, category, 1 as isnew FROM `tx_stuff_domain_model_stuff` group by category) as j2
on j.crdate=j2.crdate and j.category=j2.category
(If I have to write my own Query I will have to check deleted, hidden, starttime, endtime to check if the record is active right now)
My question now is, what is the cleanest/best way to add that to my extension?

My solution would be to implement the method findAll in the job repository. It would first use the method findAll from the parent class to get all jobs. The usual constraints will already be applied. Then it would walk the resulting jobs and mark the newest one.
It should also be possible to create a custom query to reach you goal, but that would probably be a bite more work.

Actually you don't need to use additional query at all... while it's always first record which is new, you can just use an iterator of for ViewHelper:
<f:for each="{stuffs}" as="stuff" iteration="iterator">
<f:if condition="{iterator.isFirst}">THIS ONE IS BRAND NEW STUFF! </f:if>
{stuff.title} <br />
{stuff.category}
</f:for>

Related

TYPO3 Fluid items -> f:count() select field and f:widget.paginate

I currently have the following problem:
An item has different variables that I select simple via a select in the TCA. Now with my pagination widget I want to select only the elements that have this variable 1.
Of course, if I set a condition within the pagination, it does not work, because it calculates these into these pages (which suggests more pages than actually exists).
<f:if condition="{items -> f:count()} > 1">
<f:then>
<f:widget.paginate objects="{items}" as="paginatedItems" configuration="{itemsPerPage: 10, insertAbove: 0, insertBelow: 0, maximumNumberOfLinks: 10}">
<f:for each="{paginatedItems}" as="item">
<f:if condition="{item.variable} == 1">
<div>.....</div>
</if>
</f:for>
</f:widget.paginate>
</f:then>
<f:else>
You need to compute the pagination on the subselection in that way that you need to eliminate all unwanted records before you give the array of items to the pagination viewhelper.
Either you get this subselection directly from the repository (create a new query)
or you subselect the array of items into another fluid variable like it is done by ext:news (evaluation of already shown records)
I would prefer the first solution if possible as the performance should be better and it's scalable too.

Source a value from custom record field to a field in employee record

I need to source a value from a custom record field (type: decimal) to a field in employee record(type: decimal). when the custom record is created. Is there any way I can implement this in workflow or should I go for the script?
If I choose the script which script I need to write?
Actually, I am new to script.so can anyone show me some sample?
Sounds very much like business logic, and thus shouldn't be done in a template... but, maybe you have no choice, so you can write a function like this:
<#--
Returns if two sequences (Java List-s or Java arrays usually) are equal.
Items at the same index must have common comparable type, and no item
can be null, or else you may get an error!
-->
<#function sequencesEqual s1, s2>
<#if s1?size != s2?size>
<#return false>
</#if>
<#list s1 as i1>
<#if i1 != s2[i1?index]>
<#return false>
</#if>
</#list>
<#return true>
</#function>
Then you can do things like <#if sequencesEqual(foo, bar)>...</#if>.

Compare current item with previous in f:for loop [duplicate]

This question already has answers here:
Display list of elements grouped by year and by month in TYPO3 Fluid
(3 answers)
Closed 6 years ago.
I want to group my appointments by startDate (and later by lawyer.fullName).
So I want to display the appointment's startDate only if the previous appointment's startDate is different.
This is what I tried. But I really have no idea how I can get the object from the previous operation.
Line 3 is where the fail happens right now...
<f:widget.paginate objects="{appointments}" as="paginatedAppointments">
<f:for each="{paginatedAppointments}" as="appointment" iteration="i">
<f:if condition="{appointment.startDate->f:format.date(format:'d.m.Y')} != {0:paginatedAppointments.{i.index-1}.startDate->f:format.date(format:'d.m.Y')}">
<f:then>
<br/>
{appointment.startDate->f:format.date(format:'d.m.Y')}<br/>
{appointment.startTime->f:format.date(format:'H:i')}<br/>
{appointment.lawyer.fullName}<br/><br/>
</f:then>
<f:else>
{appointment.startTime->f:format.date(format:'H:i')}<br/>
{appointment.lawyer.fullName}<br/>
<br/><br/>
</f:else>
</f:if>
</f:for>
</f:widget.paginate>
Keep in mind if you have an answer: I would really like to keep using this useful paginate widget if possible.
--Edit--
I noticed that an answer from another question solved my question perfectly in terms of the grouping for DateTime objects so I marked my question as a duplicate. Thanks to Jigal's answer I found it, because I forgot about f:groupedFor.
You could create a ViewHelper with some value to compare as an argument that saves the startDate in a static variable and returns true/false if it is different from the last one. It is also useful if it has some kind of reset function, so something like that:
{vendor:utility.compareLast(reset:1)}
<f:for each="{paginatedAppointments}" as="appointment" iteration="i">
<f:if condition="{vendor:utility.compareLast(value:'{appointment.startDate->f:format.date(format:\'d.m.Y\')}')}">
...
Use the f:groupedFor viewhelper and you can group the items by startDate. In the inner loop you can check the iterator if it's the first and display the startDate in that case. See Fluid Guide

How to make circle with break in fluid?

I want to stop my circle after output first element.
<f:for each="{errors}" as="error">
<f:switch expression="{error.code}">
<f:comment>The given subject was not a valid email address</f:comment>
<f:case value="1221559976">
<f:translate extensionName="helper" key="validator.emailaddress.notvalid" />
</f:case>
...
</f:switch>
BREAK????
</f:for>
Is it possible with fluid? Regards, Anton
You don't even need to iterate the collection, what for? Instead you can just fetch first element like: {errors.0}
Additionally if you want to fetch i.e. first 3 elements, you can prepare $limitedErrors (or smth) in your PHP controller and then assign it into the view.
It will be still more comfortable than manipulating within the template engine.
You can make you for each loop with additional argument iteration=""
add below code
<f:for each="{errors}" as="error" iteration="errorIterator">
and add condition
<f:if condition="{errorIterator.index} = 0">
or
<f:if condition="{errorIterator.isFirst}">
May you can use vhs viewhelper
<v:switch value="{variable}">
<v:case case="someValue" break="TRUE">
<!-- do whatever, if {variable} == 'someValue' -->
</v:case>
<v:case case="default">
<!-- the case "default" is a reserved keyword which acts as the default case. -->
</v:case>
</v:switch>
break > boolean

ASP.NET MVC 2: What Model property datatype will autobind an html select (DDL) with multiple selections?

The customer has a Model property that requires a comma separated list of selected options. We present their select list (DDL) as a multi-choice drop down.
What would the property datatype look like that would autobind multi-selections in the client side HTML select (DDL)?
The select posts data like this:
myOptions=Volvo&myOptions=Mercedes&myOptions=Audi
And we want to automagically bind it back to some property:
IList<string> CarChoices {get;set;}
So the POST action method parameter would be (Carform myForm)
which would have myForm.CarChoices which includes a List of the three selected cars?
I might be misunderstanding what you're trying to accomplish but I think this post from Phil Haack describes how to do what you're attempting to do in a clean way: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Sometimes it is just easier to get your hands dirty and work with the HTML. I suggest doing something like this:
<select multiple>
<% foreach(var item in Model){ %>
<option value="<%= item.ID %>"><%= item.Description %></option>
<% } %>
</select>
obviously your model is your collection. You can also use the ViewData["Whatever"] object to pass data as well, your choice.