Drupal 9 - Changing Dynamic entity reference field cardinality with existing content - drupal

I need to change the cardinality of the dynamic entity reference field from 3 to -1 on Drupal 9 site with existing content. Is there a way to change that field configuration without breaking a site? When I do it from UI the site crashes with an error:
Drupal\Core\Database\DatabaseExceptionWrapper: Exception in Enhanced Landing Page Content[enhanced_landing_page_content]: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'node__field_feature_medium_reference.field_feature_medium_reference_target_id_int'
in 'on clause': SELECT "node_field_data"."nid" AS "nid", "node_field_data_node__field_feature_medium_reference"."nid" AS "node_field_data_node__field_feature_medium_reference_nid" FROM "node_field_data" "node_field_data" LEFT JOIN "node__field_feature_medium_reference"
"node__field_feature_medium_reference" ON node_field_data.nid = node__field_feature_medium_reference.entity_id AND node__field_feature_medium_reference.deleted = :views_join_condition_0 LEFT JOIN "node_field_data" "node_field_data_node__field_feature_medium_reference"
ON node__field_feature_medium_reference.field_feature_medium_reference_target_id_int = node_field_data_node__field_feature_medium_reference.nid AND node__field_feature_medium_reference.field_feature_medium_reference_target_type = :views_join_condition_1
WHERE ((node_field_data.nid = :node_field_data_nid1)) AND (("node_field_data_node__field_feature_medium_reference"."status" = :db_condition_placeholder_2) AND ("node_field_data"."langcode" IN (:db_condition_placeholder_3)) AND ("node_field_data_node__field_feature_medium_reference"."langcode"
= :db_condition_placeholder_4)) LIMIT 5 OFFSET 0; Array ( [:node_field_data_nid1] => 225032 [:db_condition_placeholder_2] => 1 [:db_condition_placeholder_3] => en [:db_condition_placeholder_4] => en [:views_join_condition_0] => 0 [:views_join_condition_1]
=> node ) in main() (line 19 of index.php).

Related

Does the symfony translation system support an arbitrary-length list of elements to be concatenated?

I need to translate variable-length sentences in Symfony 3.4.
Sample sentence: "Included: 4 breakfasts, 1 brunch and 3 dinners."
For the exemple let's say the following constraints:
I have to express the number of breakfasts, brunches, lunches and dinners that a travel may have in a full itinerary
The list of "things" to enumerate is known and finite. There is singular and plural translation for each of the key-words.
Not all of them have to appear. If there are 0 units, the full block will be omitted.
The list is comma-separated.
Except the last block which is added with an "and" connector.
If there's only 1 block there's no comma and no "and" connector.
Each can be singular/plural.
There are multiple languages, for this example I'll use English and Spanish, but in the reality there is also catalan.
The keywords are the following in english-singular / english-plural / spanish-singular / spanish-plural:
breakfast / breakfasts / desayuno / desayunos
brunch / brunches / alumerzo-desayuno / almuerzo-desayunos
lunch / lunches / almuerzo / almuerzos
dinner / dinners / cena / cenas
So... I can imagine the following tests cases:
[
'language' => 'en-US',
'parameters' => [
'breakfast' => 4,
'dinner' => 1,
],
'expectedOutput' => 'Included: 4 breakfasts and 1 dinner.'
],
[
'language' => 'es-ES',
'parameters' => [
'breakfast' => 2,
'brunch' => 1,
'lunch' => 5,
'dinner' => 2,
],
'expectedOutput' => 'Incluido: 2 desayunos, 1 desayuno-almuerzo, 5 almuerzos y 2 cenas.'
],
[
'language' => 'en-US',
'parameters' => [
'breakfast' => 1,
],
'expectedOutput' => 'Included: 1 breakfast.'
],
[
'language' => 'es-ES',
'parameters' => [
'dinner' => 4,
'lunch' => 3,
],
'expectedOutput' => 'Incluido: 3 almuerzos y 4 cenas.'
],
Questions
Is this supported by the native translation engine in Symfony 3.4?
If not, is this supported by the native translation engines of Symfony 4 or 5?
Otherwise, is there any known pattern or strategy that fits this case?
What the translation engine can do to some extent is use a number to switch between different cases (for singular/plural). Have a look at transChoice for symfony 3.4 (til 4.1.x apparently). Since symfony 4.2, the ICU message format (follow links too) may be used to handle pluralization.
However, (conditional) string building is not really a task for the translation engine at all (even though for simple cases transChoice or the ICU message format might work out fine). So you'll probably end up building the strings from bits and pieces.
Building the string in php
// fetch translations for the itemss
$items = [];
foreach($parameters as $key => $count) {
if($count <= 0) {
continue;
}
$items[] = $translator->transChoice($key, $count);
}
// handle 2+ items differently from 1 item
if(count($items) > 1) {
// get last item
$last = array_pop($items);
// comma-separate all other items, add last item with "and"
$itemstring = implode(', ', $items)
. $translator->trans('included_and')
. $last;
} else {
$itemstring = $items[0] ?? ''; // if no items or something like
// $translator->trans('included_none')
}
return $translator->trans('included', ['%items%' => $itemstring]);
and in the translation file (english):
'included' => 'Included: %items%.',
'included_and' => ' and ',
'breakfast' => '%count% breakfast|%count% breakfasts', // etc. for all other stuff
Please note, that transChoice should automatically set the %count% placeholder to the count provided as the second parameter to transChoice.
alternate approaches
You could easily split the translatable strings into breakfast_singular and breakfast_plural if you wanted to avoid the use of transChoice, you would have to replace
transChoice($key, $count)
with
trans($key.($count > 1 ? '_plural' : '_singular'), ['%count%' => $count])
You could also expand the included string into included_single and included_multiple where the latter is being translated as 'Included: %items% and %last%', with appropriate parameters and conditionals.
Ultimately though, string generation or more specifically language generation isn't really a job for a simple translation engine.

Cakephp 3: Collections getting to middle array entities

I'm trying to build a view that shows the most recent (now four but eventually five) years of data in a chart. I'm able to pull the data successfully in a variable the shows the most recent 4 years(I don't have the fifth year in the database yet). In order to break it down for the view and add some calculations on associated arrays, I have created a collection. I can get to the first and last array entity but can not figure out how to break out the middle two arrays.
public function viewAsuFiveYear()
{
$asuFiveYearEnrollments = $this->Enrollments->find('all', [
'contain' => ['Azinstitutions', 'FallFtes', 'FallHeadcounts', 'ProjectedEnrollments',
'FallHeadcounts.Locations', 'FallHeadcounts.StudentTypes', 'FallHeadcounts.ResidentStatuses', 'FallHeadcounts.Campuses',
'FallFtes.Locations', 'FallFtes.StudentTypes', 'FallFtes.ResidentStatuses', 'FallFtes.Campuses']
], ['limit' => 5])->where(['azinstitution_id' => 1])->order(['enrollment_year' => 'DESC']);
$collection = new Collection($asuFiveYearEnrollments);
$yearone = $collection->first();
$yearTwo = $collection->take(1, 1);
$yearFour = $collection->last();
$collection1HC = new Collection($yearone->fall_headcounts);
$onCampusesHc1 = $collection1HC->match(['location_id' => 1 ])->match(['campus_id' => NULL]);
$collection4HC = new Collection($yearFour->fall_headcounts);
$onCampusesHc4 = $collection4HC->match(['location_id' => 1 ])->match(['campus_id' => NULL]);
$this->set(compact('asuFiveYearEnrollments', 'azinstitutions', 'yearone', 'yearTwo', 'yearFour', 'onCampusesHc1', 'onCampusesHc4'));
}
I tried ->take (one array, second position) but it times out with that. Not sure what filter I can use to get to the 2nd or 3rd entity array.
I believe I've figured it out. May not be the best answer but it works. for the second year I skipped the 1st array and grabbed the first array in what was left.
and the same with the third year.
$yearTwo = $collection->skip(1)->first();
$yearThree = $collection->skip(2)->first();

ASP.NET Entity Framework Order By and Then By not working

I have this line of code:
var inventory = dbInventory.Data
.SqlQuery( sql )
.OrderBy( m => m.isSold )
.ThenBy( m => m.lotNumber )
.ToList();
I this code for 4 pages on my website, the order is correct for the 3 out of the 4, for the 4th one, they dont want to go in order at all. For the one that is not working, all the isSold is false and they all have a lotNumber but its not returning the lotNumbers in order.
Please help.
This fixed my problem.
var inventory = dbInventory.Data.SqlQuery(sql).OrderBy(m => m.isSold).ThenBy(m => int.Parse(m.lotNumber)).ToList();

Unexpected notice: undefined index when null

I've written a little script that is supposed to create an array that looks something like this:
array(1 => array( 'month' => 'Jan',
'salary' => '01/31/2013',
'bonus' => '02/15/2013'),
2 => array('month' => '',...));
You get the basic idea: the index in the main array are the months (numerically), each holding an array that is to be filled dynamically. The month key depends on the language the user requested, the salary and bonus are assigned the dates when the salary and or bonus was payed. So far no surprizes.
To get the basic structure of that array, I thought this would be the easiest:
$this->months = array_fill_keys(range(1,12), array( 'month' => null,
'salary' => null,
'bonus' => null));
I then fill the array, and things run smoothly all the same, right up until the point where I want to write the data to a file, which I did like so:
private function writeFile()
{
foreach($this->months as $key => $vals)
{
if ($vals['month'] === null)
{//Only filled from date x to date y, some months can be empty
continue;
}
//this seems to raise notices?
if ($vals['salary'] === null)
{
$vals['salary'] = 'Does not apply';
}
fwrite($this->file, implode(',', $vals).PHP_EOL);
}
fclose($this->file);
return $this;
}
The line where I check if the salary is null raises notices: "Warning: Undefined index salary". At the moment I've had to add this to the code:
if (!array_key_exists('salary', $vals) || $vals['salary'] === null)
{
if (!array_key_exists('bonus', $vals) || $vals['bonus'] === null)
{
break;
}
$vals['salary'] = 'Does not apply';
}
To get to the result I need. I have googled this, and stumbled across this bug report, which was last modified 4 years ago (2009-05-08), but the status is still set to "no feedback".
Has anyone else encountered a similar glitch/bug? Or am I missing something here? How can I avoid this issue without the need for all too many if's and function calls without changing my settings (E_STRICT | E_ALL, as it should be).
BTW: I'm running PHP 5.4.7, on Slackware 14. For this little application, I'm using 2 Symfony components (ClassLoader and Console), but since this is part of an object that has nothing to do with Symfony, apart from being loaded through UniversalClassLoader I don't think that's relevant.
Since the bug is said to be PDO related: yes, I am using PDO, but in another class.
I am not sure , but try to use
$this->months = array_fill(1,12, array( 'month' => null,
'salary' => null,
'bonus' => null));
After a couple of var_dumps, I found out what the cause was: The array keys were range(1,12), to determine the which month was I was processing. For that I used a DateTime object in the following fashion:
$date->modify('+ '.$diff.' days');
$key = $date->format('m');
The problem was that the format call returns a string. The goal was to list when the salary and bonus are to be paid. The bonus has to be paid each 15th, or the following Wednesday, if the 15th was a Saturday or Sunday. The salary is to be paid the last day of the month, or the last Friday.
In other words, the bonus pay date is assigned like so:
$key = $date->format('m');
$this->months[$key]['month'] = $date->format('M');
if ($date->format('d') == 15)
{
//find find week-day (15th or following Wednesday)
$this->months[--$key]['bonus'] = $date->format('m/d/Y');
$key++;
//set date to end of month
}
//check week-day, and modify date if required
$this->months[$key]['salary'] = $date->format('m/d/Y');
Because the keys of the $this->months array are numeric, but the format used for $key is a 2-digit string, with leading zeroes, I was having problems.
Each 15th of the month, the $key value is coerced to an integer (decrement/increment operators), but the month is assigned using a string.
The information I provided in my original question was insufficient, sorry for that, but I had just put in an all-nighter. The fix, in the end was pretty easy:
$key = (int) $date->format('m');//cast
I sincerely appreciate all responses, and everyone contributing to the SO community. I would've deleted this question, but if nobody objects, I think I might leave it be as a testimony to my stupidity.

Drupal: Add onchange code to option_widgets in form_alter?

Do anyone know how I can add the following to form_alter?
Currently I've got two integer cck fields which are populated from sql using the php values command.
One field is for make, and the other is for model. Both makes and models are their own node types. Model has a node reference to make.
What I want to do on the Make drop down (CCK: INTEGER : SELECT), is on change, modify the contents of the model field. I've made my own bespoke form up, but it's too wieldy and want to use the basic drupal node edit forms.
Ideally I want to be able to pass this into the mix.
'#attributes' => array ('onchange'=> 'populatemodels(this,\'edit-field-model\')')
Does any one know of a way of doing this in the code?
In my form_alter adding the attribute doesn't produce any onchanges in the code:
#field_make (Array, 14 elements)
*
#type (String, 20 characters ) optionwidgets_select
*
#default_value (Array, 1 element)
o
0 (Array, 1 element)
+
value (String, 1 characters ) 8
*
#required (String, 1 characters ) 1
*
#columns (Array, 1 element)
o
0 (String, 5 characters ) value
*
#title (String, 4 characters ) Make
*
#description (String, 0 characters )
*
#delta (Integer) 0
*
#field_name (String, 10 characters ) field_make
*
#type_name (String, 3 characters ) car
*
#tree (Boolean) TRUE
*
#weight (String, 2 characters ) -1
*
#access (Boolean) TRUE
*
#count (Integer) 9
*
#attributes (Array, 1 element)
o
onchange (String, 39 characters ) populatemodels(this,'edit-field-model')
Thanks - Matt
I think I've had a break through.
cck/options_widgets.module
optionwidgets_select_process($element, $edit, &$form_state, $form) {
Additionally in my form_alter code, I added
drupal_add_js('sites/all/modules/adaptive/adaptive.js');
Which holds the populatemodels script
I've modded this code so that it passes attributes onto the next step
$element[$field_key] = array(
'#type' => 'select',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => isset($element['#required']) ? $element['#required'] : $field['required'],
'#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['multiple'],
'#options' => $options,
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
>>> '#attributes' => isset($element['#attributes']) ? $element['#attributes'] : NULL, <<
);
By adding '#attributes' => isset($element['#attributes']) ? $element['#attributes'] : NULL, the onchange now appears in the rendered code.

Resources